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