• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1;------------------------------------------------------------------------------ ;
2; Copyright (c) 2016, 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;   SmiException.nasm
14;
15; Abstract:
16;
17;   Exception handlers used in SM mode
18;
19;-------------------------------------------------------------------------------
20
21extern  ASM_PFX(SmiPFHandler)
22
23global  ASM_PFX(gcSmiIdtr)
24global  ASM_PFX(gcSmiGdtr)
25global  ASM_PFX(gcPsd)
26
27    SECTION .data
28
29NullSeg: DQ 0                   ; reserved by architecture
30CodeSeg32:
31            DW      -1                  ; LimitLow
32            DW      0                   ; BaseLow
33            DB      0                   ; BaseMid
34            DB      0x9b
35            DB      0xcf                ; LimitHigh
36            DB      0                   ; BaseHigh
37ProtModeCodeSeg32:
38            DW      -1                  ; LimitLow
39            DW      0                   ; BaseLow
40            DB      0                   ; BaseMid
41            DB      0x9b
42            DB      0xcf                ; LimitHigh
43            DB      0                   ; BaseHigh
44ProtModeSsSeg32:
45            DW      -1                  ; LimitLow
46            DW      0                   ; BaseLow
47            DB      0                   ; BaseMid
48            DB      0x93
49            DB      0xcf                ; LimitHigh
50            DB      0                   ; BaseHigh
51DataSeg32:
52            DW      -1                  ; LimitLow
53            DW      0                   ; BaseLow
54            DB      0                   ; BaseMid
55            DB      0x93
56            DB      0xcf                ; LimitHigh
57            DB      0                   ; BaseHigh
58CodeSeg16:
59            DW      -1
60            DW      0
61            DB      0
62            DB      0x9b
63            DB      0x8f
64            DB      0
65DataSeg16:
66            DW      -1
67            DW      0
68            DB      0
69            DB      0x93
70            DB      0x8f
71            DB      0
72CodeSeg64:
73            DW      -1                  ; LimitLow
74            DW      0                   ; BaseLow
75            DB      0                   ; BaseMid
76            DB      0x9b
77            DB      0xaf                ; LimitHigh
78            DB      0                   ; BaseHigh
79; TSS Segment for X64 specially
80TssSeg:
81            DW      TSS_DESC_SIZE       ; LimitLow
82            DW      0                   ; BaseLow
83            DB      0                   ; BaseMid
84            DB      0x89
85            DB      0x80                ; LimitHigh
86            DB      0                   ; BaseHigh
87            DD      0                   ; BaseUpper
88            DD      0                   ; Reserved
89GDT_SIZE equ $ -   NullSeg
90
91; Create TSS Descriptor just after GDT
92TssDescriptor:
93            DD      0                   ; Reserved
94            DQ      0                   ; RSP0
95            DQ      0                   ; RSP1
96            DQ      0                   ; RSP2
97            DD      0                   ; Reserved
98            DD      0                   ; Reserved
99            DQ      0                   ; IST1
100            DQ      0                   ; IST2
101            DQ      0                   ; IST3
102            DQ      0                   ; IST4
103            DQ      0                   ; IST5
104            DQ      0                   ; IST6
105            DQ      0                   ; IST7
106            DD      0                   ; Reserved
107            DD      0                   ; Reserved
108            DW      0                   ; Reserved
109            DW      0                   ; I/O Map Base Address
110TSS_DESC_SIZE equ $ -   TssDescriptor
111
112;
113; This structure serves as a template for all processors.
114;
115ASM_PFX(gcPsd):
116            DB      'PSDSIG  '
117            DW      PSD_SIZE
118            DW      2
119            DW      1 << 2
120            DW      CODE_SEL
121            DW      DATA_SEL
122            DW      DATA_SEL
123            DW      DATA_SEL
124            DW      0
125            DQ      0
126            DQ      0
127            DQ      0                   ; fixed in InitializeMpServiceData()
128            DQ        NullSeg
129            DD      GDT_SIZE
130            DD      0
131            times   24 DB 0
132            DQ      0
133PSD_SIZE  equ $ -   ASM_PFX(gcPsd)
134
135;
136; CODE & DATA segments for SMM runtime
137;
138CODE_SEL    equ   CodeSeg64 -   NullSeg
139DATA_SEL    equ   DataSeg32 -   NullSeg
140CODE32_SEL  equ   CodeSeg32 -   NullSeg
141
142ASM_PFX(gcSmiGdtr):
143    DW      GDT_SIZE - 1
144    DQ        NullSeg
145
146ASM_PFX(gcSmiIdtr):
147    DW      0
148    DQ      0
149
150    DEFAULT REL
151    SECTION .text
152
153;------------------------------------------------------------------------------
154; _SmiExceptionEntryPoints is the collection of exception entrypoints followed
155; by a common exception handler.
156;
157; Stack frame would be as follows as specified in IA32 manuals:
158;
159; +---------------------+ <-- 16-byte aligned ensured by processor
160; +    Old SS           +
161; +---------------------+
162; +    Old RSP          +
163; +---------------------+
164; +    RFlags           +
165; +---------------------+
166; +    CS               +
167; +---------------------+
168; +    RIP              +
169; +---------------------+
170; +    Error Code       +
171; +---------------------+
172; +   Vector Number     +
173; +---------------------+
174; +    RBP              +
175; +---------------------+ <-- RBP, 16-byte aligned
176;
177; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
178;------------------------------------------------------------------------------
179global ASM_PFX(PageFaultIdtHandlerSmmProfile)
180ASM_PFX(PageFaultIdtHandlerSmmProfile):
181    push    0xe                         ; Page Fault
182    test    spl, 8                      ; odd multiple of 8 => ErrCode present
183    jnz     .0
184    push    qword [rsp]                       ; duplicate INT# if no ErrCode
185    mov     qword [rsp + 8], 0
186.0:
187    push    rbp
188    mov     rbp, rsp
189
190    ;
191    ; Since here the stack pointer is 16-byte aligned, so
192    ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
193    ; is 16-byte aligned
194    ;
195
196;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
197;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
198    push    r15
199    push    r14
200    push    r13
201    push    r12
202    push    r11
203    push    r10
204    push    r9
205    push    r8
206    push    rax
207    push    rcx
208    push    rdx
209    push    rbx
210    push    qword [rbp + 48]  ; RSP
211    push    qword [rbp]       ; RBP
212    push    rsi
213    push    rdi
214
215;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
216    movzx   rax, word [rbp + 56]
217    push    rax                      ; for ss
218    movzx   rax, word [rbp + 32]
219    push    rax                      ; for cs
220    mov     rax, ds
221    push    rax
222    mov     rax, es
223    push    rax
224    mov     rax, fs
225    push    rax
226    mov     rax, gs
227    push    rax
228
229;; UINT64  Rip;
230    push    qword [rbp + 24]
231
232;; UINT64  Gdtr[2], Idtr[2];
233    sub     rsp, 16
234    sidt    [rsp]
235    sub     rsp, 16
236    sgdt    [rsp]
237
238;; UINT64  Ldtr, Tr;
239    xor     rax, rax
240    str     ax
241    push    rax
242    sldt    ax
243    push    rax
244
245;; UINT64  RFlags;
246    push    qword [rbp + 40]
247
248;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
249    mov     rax, cr8
250    push    rax
251    mov     rax, cr4
252    or      rax, 0x208
253    mov     cr4, rax
254    push    rax
255    mov     rax, cr3
256    push    rax
257    mov     rax, cr2
258    push    rax
259    xor     rax, rax
260    push    rax
261    mov     rax, cr0
262    push    rax
263
264;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
265    mov     rax, dr7
266    push    rax
267    mov     rax, dr6
268    push    rax
269    mov     rax, dr3
270    push    rax
271    mov     rax, dr2
272    push    rax
273    mov     rax, dr1
274    push    rax
275    mov     rax, dr0
276    push    rax
277
278;; FX_SAVE_STATE_X64 FxSaveState;
279
280    sub rsp, 512
281    mov rdi, rsp
282    db 0xf, 0xae, 00000111y ;fxsave [rdi]
283
284; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
285    cld
286
287;; UINT32  ExceptionData;
288    push    qword [rbp + 16]
289
290;; call into exception handler
291    mov     rcx, [rbp + 8]
292    mov     rax, ASM_PFX(SmiPFHandler)
293
294;; Prepare parameter and call
295    mov     rdx, rsp
296    ;
297    ; Per X64 calling convention, allocate maximum parameter stack space
298    ; and make sure RSP is 16-byte aligned
299    ;
300    sub     rsp, 4 * 8 + 8
301    call    rax
302    add     rsp, 4 * 8 + 8
303    jmp     .1
304
305.1:
306;; UINT64  ExceptionData;
307    add     rsp, 8
308
309;; FX_SAVE_STATE_X64 FxSaveState;
310
311    mov rsi, rsp
312    db 0xf, 0xae, 00001110y ; fxrstor [rsi]
313    add rsp, 512
314
315;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
316;; Skip restoration of DRx registers to support debuggers
317;; that set breakpoints in interrupt/exception context
318  add     rsp, 8 * 6
319
320;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
321    pop     rax
322    mov     cr0, rax
323    add     rsp, 8   ; not for Cr1
324    pop     rax
325    mov     cr2, rax
326    pop     rax
327    mov     cr3, rax
328    pop     rax
329    mov     cr4, rax
330    pop     rax
331    mov     cr8, rax
332
333;; UINT64  RFlags;
334    pop     qword [rbp + 40]
335
336;; UINT64  Ldtr, Tr;
337;; UINT64  Gdtr[2], Idtr[2];
338;; Best not let anyone mess with these particular registers...
339    add     rsp, 48
340
341;; UINT64  Rip;
342    pop     qword [rbp + 24]
343
344;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;
345    pop     rax
346    ; mov     gs, rax ; not for gs
347    pop     rax
348    ; mov     fs, rax ; not for fs
349    ; (X64 will not use fs and gs, so we do not restore it)
350    pop     rax
351    mov     es, rax
352    pop     rax
353    mov     ds, rax
354    pop     qword [rbp + 32]  ; for cs
355    pop     qword [rbp + 56]  ; for ss
356
357;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
358;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
359    pop     rdi
360    pop     rsi
361    add     rsp, 8               ; not for rbp
362    pop     qword [rbp + 48] ; for rsp
363    pop     rbx
364    pop     rdx
365    pop     rcx
366    pop     rax
367    pop     r8
368    pop     r9
369    pop     r10
370    pop     r11
371    pop     r12
372    pop     r13
373    pop     r14
374    pop     r15
375
376    mov     rsp, rbp
377
378; Enable TF bit after page fault handler runs
379    bts     dword [rsp + 40], 8  ;RFLAGS
380
381    pop     rbp
382    add     rsp, 16           ; skip INT# & ErrCode
383    iretq
384
385