]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.asm
UefiCpuPkg: Add PiSmmCpuDxeSmm module X64 files
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmiEntry.asm
CommitLineData
427e3573
MK
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
3; This program and the accompanying materials\r
4; are licensed and made available under the terms and conditions of the BSD License\r
5; which accompanies this distribution. The full text of the license may be found at\r
6; http://opensource.org/licenses/bsd-license.php.\r
7;\r
8; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10;\r
11; Module Name:\r
12;\r
13; SmiEntry.asm\r
14;\r
15; Abstract:\r
16;\r
17; Code template of the SMI handler for a particular processor\r
18;\r
19;-------------------------------------------------------------------------------\r
20\r
21;\r
22; Variables referenced by C code\r
23;\r
24EXTERNDEF SmiRendezvous:PROC\r
25EXTERNDEF gcSmiHandlerTemplate:BYTE\r
26EXTERNDEF gcSmiHandlerSize:WORD\r
27EXTERNDEF gSmiCr3:DWORD\r
28EXTERNDEF gSmiStack:DWORD\r
29EXTERNDEF gSmbase:DWORD\r
30EXTERNDEF FeaturePcdGet (PcdCpuSmmDebug):BYTE\r
31EXTERNDEF gSmiHandlerIdtr:FWORD\r
32\r
33\r
34;\r
35; Constants relating to PROCESSOR_SMM_DESCRIPTOR\r
36;\r
37DSC_OFFSET EQU 0fb00h\r
38DSC_GDTPTR EQU 30h\r
39DSC_GDTSIZ EQU 38h\r
40DSC_CS EQU 14\r
41DSC_DS EQU 16\r
42DSC_SS EQU 18\r
43DSC_OTHERSEG EQU 20\r
44;\r
45; Constants relating to CPU State Save Area\r
46;\r
47SSM_DR6 EQU 0ffd0h\r
48SSM_DR7 EQU 0ffc8h\r
49\r
50PROTECT_MODE_CS EQU 08h\r
51PROTECT_MODE_DS EQU 20h\r
52LONG_MODE_CS EQU 38h\r
53TSS_SEGMENT EQU 40h\r
54GDT_SIZE EQU 50h\r
55\r
56 .code\r
57\r
58gcSmiHandlerTemplate LABEL BYTE\r
59\r
60_SmiEntryPoint:\r
61 ;\r
62 ; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-\r
63 ; bit addressing mode. And that coincidence has been used in the following\r
64 ; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a\r
65 ; base address register, it is actually BX that is referenced.\r
66 ;\r
67 DB 0bbh ; mov bx, imm16\r
68 DW offset _GdtDesc - _SmiEntryPoint + 8000h ; bx = GdtDesc offset\r
69; fix GDT descriptor\r
70 DB 2eh, 0a1h ; mov ax, cs:[offset16]\r
71 DW DSC_OFFSET + DSC_GDTSIZ\r
72 DB 48h ; dec ax\r
73 DB 2eh\r
74 mov [rdi], eax ; mov cs:[bx], ax\r
75 DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]\r
76 DW DSC_OFFSET + DSC_GDTPTR\r
77 DB 2eh\r
78 mov [rdi + 2], ax ; mov cs:[bx + 2], eax\r
79 DB 66h, 2eh\r
80 lgdt fword ptr [rdi] ; lgdt fword ptr cs:[bx]\r
81; Patch ProtectedMode Segment\r
82 DB 0b8h ; mov ax, imm16\r
83 DW PROTECT_MODE_CS ; set AX for segment directly\r
84 DB 2eh\r
85 mov [rdi - 2], eax ; mov cs:[bx - 2], ax\r
86; Patch ProtectedMode entry\r
87 DB 66h, 0bfh ; mov edi, SMBASE\r
88gSmbase DD ?\r
89 lea ax, [edi + (@ProtectedMode - _SmiEntryPoint) + 8000h]\r
90 DB 2eh\r
91 mov [rdi - 6], ax ; mov cs:[bx - 6], eax\r
92; Switch into @ProtectedMode\r
93 mov rbx, cr0\r
94 DB 66h\r
95 and ebx, 9ffafff3h\r
96 DB 66h\r
97 or ebx, 00000023h\r
98\r
99 mov cr0, rbx\r
100 DB 66h, 0eah\r
101 DD ?\r
102 DW ?\r
103\r
104_GdtDesc FWORD ?\r
105@ProtectedMode:\r
106 mov ax, PROTECT_MODE_DS\r
107 mov ds, ax\r
108 mov es, ax\r
109 mov fs, ax\r
110 mov gs, ax\r
111 mov ss, ax\r
112 DB 0bch ; mov esp, imm32\r
113gSmiStack DD ?\r
114 jmp ProtFlatMode\r
115\r
116ProtFlatMode:\r
117 DB 0b8h ; mov eax, offset gSmiCr3\r
118gSmiCr3 DD ?\r
119 mov cr3, rax\r
120 mov eax, 668h ; as cr4.PGE is not set here, refresh cr3\r
121 mov cr4, rax ; in PreModifyMtrrs() to flush TLB.\r
122; Load TSS\r
123 sub esp, 8 ; reserve room in stack\r
124 sgdt fword ptr [rsp]\r
125 mov eax, [rsp + 2] ; eax = GDT base\r
126 add esp, 8\r
127 mov edx, eax\r
128 add edx, GDT_SIZE\r
129 mov [rax + TSS_SEGMENT + 2], dl\r
130 mov [rax + TSS_SEGMENT + 3], dh\r
131 DB 0c1h, 0eah, 10h ; shr edx, 16\r
132 mov [rax + TSS_SEGMENT + 4], dl\r
133 mov [rax + TSS_SEGMENT + 7], dh\r
134 mov edx, eax\r
135 mov dl, 89h\r
136 mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag\r
137 mov eax, TSS_SEGMENT\r
138 ltr ax\r
139\r
140; Switch into @LongMode\r
141 push LONG_MODE_CS ; push cs hardcore here\r
142 call Base ; push return address for retf later\r
143Base:\r
144 add dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg\r
145 mov ecx, 0c0000080h\r
146 rdmsr\r
147 or ah, 1\r
148 wrmsr\r
149 mov rbx, cr0\r
150 bts ebx, 31\r
151 mov cr0, rbx\r
152 retf\r
153@LongMode: ; long mode (64-bit code) starts here\r
154 mov rax, offset gSmiHandlerIdtr\r
155 lidt fword ptr [rax]\r
156 lea ebx, [rdi + DSC_OFFSET]\r
157 mov ax, [rbx + DSC_DS]\r
158 mov ds, eax\r
159 mov ax, [rbx + DSC_OTHERSEG]\r
160 mov es, eax\r
161 mov fs, eax\r
162 mov gs, eax\r
163 mov ax, [rbx + DSC_SS]\r
164 mov ss, eax\r
165; jmp _SmiHandler ; instruction is not needed\r
166\r
167_SmiHandler:\r
168;\r
169; The following lines restore DR6 & DR7 before running C code. They are useful\r
170; when you want to enable hardware breakpoints in SMM.\r
171;\r
172; NOTE: These lines might not be appreciated in runtime since they might\r
173; conflict with OS debugging facilities. Turn them off in RELEASE.\r
174;\r
175 mov rax, offset FeaturePcdGet (PcdCpuSmmDebug) ;Get absolute address. Avoid RIP relative addressing\r
176 cmp byte ptr [rax], 0\r
177 jz @1\r
178\r
179 DB 48h, 8bh, 0dh ; mov rcx, [rip + disp32]\r
180 DD SSM_DR6 - ($ + 4 - _SmiEntryPoint + 8000h)\r
181 DB 48h, 8bh, 15h ; mov rdx, [rip + disp32]\r
182 DD SSM_DR7 - ($ + 4 - _SmiEntryPoint + 8000h)\r
183 mov dr6, rcx\r
184 mov dr7, rdx\r
185@1:\r
186 mov rcx, [rsp] ; rcx <- CpuIndex\r
187 mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous\r
188\r
189 ;\r
190 ; Save FP registers\r
191 ;\r
192 sub rsp, 208h\r
193 DB 48h ; FXSAVE64\r
194 fxsave [rsp]\r
195\r
196 add rsp, -20h\r
197 call rax\r
198 add rsp, 20h\r
199\r
200 ;\r
201 ; Restore FP registers\r
202 ;\r
203 DB 48h ; FXRSTOR64\r
204 fxrstor [rsp]\r
205\r
206 mov rax, offset FeaturePcdGet (PcdCpuSmmDebug) ;Get absolute address. Avoid RIP relative addressing\r
207 cmp byte ptr [rax], 0\r
208 jz @2\r
209\r
210 mov rdx, dr7\r
211 mov rcx, dr6\r
212 DB 48h, 89h, 15h ; mov [rip + disp32], rdx\r
213 DD SSM_DR7 - ($ + 4 - _SmiEntryPoint + 8000h)\r
214 DB 48h, 89h, 0dh ; mov [rip + disp32], rcx\r
215 DD SSM_DR6 - ($ + 4 - _SmiEntryPoint + 8000h)\r
216@2:\r
217 rsm\r
218\r
219gcSmiHandlerSize DW $ - _SmiEntryPoint\r
220\r
221 END\r