• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
4# This program and the accompanying materials
5# are licensed and made available under the terms and conditions of the BSD License
6# which accompanies this distribution.  The full text of the license may be found at
7# http://opensource.org/licenses/bsd-license.php.
8#
9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11#
12# Module Name:
13#
14#   SmiException.S
15#
16# Abstract:
17#
18#   Exception handlers used in SM mode
19#
20#------------------------------------------------------------------------------
21
22ASM_GLOBAL  ASM_PFX(SmiPFHandler)
23ASM_GLOBAL  ASM_PFX(gcSmiIdtr)
24ASM_GLOBAL  ASM_PFX(gcSmiGdtr)
25ASM_GLOBAL  ASM_PFX(gcPsd)
26
27    .data
28
29NullSeg:    .quad 0                     # reserved by architecture
30CodeSeg32:
31            .word -1                    # LimitLow
32            .word 0                     # BaseLow
33            .byte 0                     # BaseMid
34            .byte 0x9b
35            .byte 0xcf                  # LimitHigh
36            .byte 0                     # BaseHigh
37ProtModeCodeSeg32:
38            .word -1                    # LimitLow
39            .word 0                     # BaseLow
40            .byte 0                     # BaseMid
41            .byte 0x9b
42            .byte 0xcf                  # LimitHigh
43            .byte 0                     # BaseHigh
44ProtModeSsSeg32:
45            .word -1                    # LimitLow
46            .word 0                     # BaseLow
47            .byte 0                     # BaseMid
48            .byte 0x93
49            .byte 0xcf                  # LimitHigh
50            .byte 0                     # BaseHigh
51DataSeg32:
52            .word -1                    # LimitLow
53            .word 0                     # BaseLow
54            .byte 0                     # BaseMid
55            .byte 0x93
56            .byte 0xcf                  # LimitHigh
57            .byte 0                     # BaseHigh
58CodeSeg16:
59            .word -1
60            .word 0
61            .byte 0
62            .byte 0x9b
63            .byte 0x8f
64            .byte 0
65DataSeg16:
66            .word -1
67            .word 0
68            .byte 0
69            .byte 0x93
70            .byte 0x8f
71            .byte 0
72CodeSeg64:
73            .word -1                    # LimitLow
74            .word 0                     # BaseLow
75            .byte 0                     # BaseMid
76            .byte 0x9b
77            .byte 0xaf                  # LimitHigh
78            .byte 0                     # BaseHigh
79# TSS Segment for X64 specially
80TssSeg:
81            .word TSS_DESC_SIZE - 1     # LimitLow
82            .word 0                     # BaseLow
83            .byte 0                     # BaseMid
84            .byte 0x89
85            .byte 0x00                  # LimitHigh
86            .byte 0                     # BaseHigh
87            .long 0                     # BaseUpper
88            .long 0                     # Reserved
89.equ  GDT_SIZE, .- NullSeg
90
91TssDescriptor:
92            .space 104, 0
93.equ  TSS_DESC_SIZE, .- TssDescriptor
94
95#
96# This structure serves as a template for all processors.
97#
98ASM_PFX(gcPsd):
99            .ascii  "PSDSIG  "
100            .word      PSD_SIZE
101            .word 2
102            .word      1 << 2
103            .word      CODE_SEL
104            .word      DATA_SEL
105            .word      DATA_SEL
106            .word      DATA_SEL
107            .word 0
108            .quad 0
109            .quad 0
110            .quad 0                     # fixed in InitializeMpServiceData()
111            .quad      NullSeg
112            .long      GDT_SIZE
113            .long 0
114            .space 24, 0
115            .quad      0
116.equ  PSD_SIZE,  . - ASM_PFX(gcPsd)
117
118#
119# CODE & DATA segments for SMM runtime
120#
121.equ  CODE_SEL,    CodeSeg64 - NullSeg
122.equ  DATA_SEL,    DataSeg32 - NullSeg
123.equ  CODE32_SEL,  CodeSeg32 - NullSeg
124
125ASM_PFX(gcSmiGdtr):
126    .word      GDT_SIZE - 1
127    .quad      NullSeg
128
129ASM_PFX(gcSmiIdtr):
130    .word      0
131    .quad      0
132
133    .text
134
135#------------------------------------------------------------------------------
136# _SmiExceptionEntryPoints is the collection of exception entry points followed
137# by a common exception handler.
138#
139# Stack frame would be as follows as specified in IA32 manuals:
140# +---------------------+ <-- 16-byte aligned ensured by processor
141# +    Old SS           +
142# +---------------------+
143# +    Old RSP          +
144# +---------------------+
145# +    RFlags           +
146# +---------------------+
147# +    CS               +
148# +---------------------+
149# +    RIP              +
150# +---------------------+
151# +    Error Code       +
152# +---------------------+
153# +   Vector Number     +
154# +---------------------+
155# +    RBP              +
156# +---------------------+ <-- RBP, 16-byte aligned
157#
158# RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
159#------------------------------------------------------------------------------
160ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
161ASM_PFX(PageFaultIdtHandlerSmmProfile):
162    pushq   $0x0e                    # Page Fault
163    .byte   0x40, 0xf6, 0xc4, 0x08    #test    spl, 8
164    jnz     L1
165    pushq   (%rsp)
166    movq    $0, 8(%rsp)
167L1:
168    pushq   %rbp
169    movq    %rsp, %rbp
170
171    #
172    # Since here the stack pointer is 16-byte aligned, so
173    # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
174    # is 16-byte aligned
175    #
176
177## UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
178## UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
179    pushq   %r15
180    pushq   %r14
181    pushq   %r13
182    pushq   %r12
183    pushq   %r11
184    pushq   %r10
185    pushq   %r9
186    pushq   %r8
187    pushq   %rax
188    pushq   %rcx
189    pushq   %rdx
190    pushq   %rbx
191    pushq   48(%rbp)                   # RSP
192    pushq   (%rbp)                     # RBP
193    pushq   %rsi
194    pushq   %rdi
195
196## UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
197    movzwq 56(%rbp), %rax
198    pushq   %rax                       # for ss
199    movzwq  32(%rbp), %rax
200    pushq   %rax                       # for cs
201    movq    %ds, %rax
202    pushq   %rax
203    movq    %es, %rax
204    pushq   %rax
205    movq    %fs, %rax
206    pushq   %rax
207    movq    %gs, %rax
208    pushq   %rax
209
210## UINT64  Rip;
211    pushq   24(%rbp)
212
213## UINT64  Gdtr[2], Idtr[2];
214    subq    $16, %rsp
215    sidt    (%rsp)
216    subq    $16, %rsp
217    sgdt    (%rsp)
218
219## UINT64  Ldtr, Tr;
220    xorq    %rax, %rax
221    strw    %ax
222    pushq   %rax
223    sldtw   %ax
224    pushq   %rax
225
226## UINT64  RFlags;
227    pushq   40(%rbp)
228
229## UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
230    movq    %cr8, %rax
231    pushq   %rax
232    movq    %cr4, %rax
233    orq     $0x208, %rax
234    movq    %rax, %cr4
235    pushq   %rax
236    movq    %cr3, %rax
237    pushq   %rax
238    movq    %cr2, %rax
239    pushq   %rax
240    xorq    %rax, %rax
241    pushq   %rax
242    movq    %cr0, %rax
243    pushq   %rax
244
245## UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
246    movq    %dr7, %rax
247    pushq   %rax
248    movq    %dr6, %rax
249    pushq   %rax
250    movq    %dr3, %rax
251    pushq   %rax
252    movq    %dr2, %rax
253    pushq   %rax
254    movq    %dr1, %rax
255    pushq   %rax
256    movq    %dr0, %rax
257    pushq   %rax
258
259## FX_SAVE_STATE_X64 FxSaveState;
260
261    subq    $512, %rsp
262    movq    %rsp, %rdi
263    .byte   0xf, 0xae, 0x7                  # fxsave [rdi]
264
265# UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
266    cld
267
268## UINT32  ExceptionData;
269    pushq   16(%rbp)
270
271## call into exception handler
272    movq    8(%rbp), %rcx
273    movabsq $ASM_PFX(SmiPFHandler), %rax
274
275## Prepare parameter and call
276    movq    %rsp, %rdx
277    #
278    # Per X64 calling convention, allocate maximum parameter stack space
279    # and make sure RSP is 16-byte aligned
280    #
281    subq    $4 * 8 + 8, %rsp
282    call    *%rax
283    addq    $4 * 8 + 8, %rsp
284    jmp     L5
285
286L5:
287## UINT64  ExceptionData;
288    addq    $8, %rsp
289
290## FX_SAVE_STATE_X64 FxSaveState;
291
292    movq    %rsp, %rsi
293    .byte   0xf, 0xae, 0xe                 # fxrstor [rsi]
294    addq    $512, %rsp
295
296## UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
297## Skip restoration of DRx registers to support debuggers
298## that set breakpoints in interrupt/exception context
299    addq    $8 * 6, %rsp
300
301## UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
302    popq    %rax
303    movq    %rax, %cr0
304    addq    $8, %rsp                      # not for Cr1
305    popq    %rax
306    movq    %rax, %cr2
307    popq    %rax
308    movq    %rax, %cr3
309    popq    %rax
310    movq    %rax, %cr4
311    popq    %rax
312    movq    %rax, %cr8
313
314## UINT64  RFlags;
315    popq    40(%rbp)
316
317## UINT64  Ldtr, Tr;
318## UINT64  Gdtr[2], Idtr[2];
319## Best not let anyone mess with these particular registers...
320    addq    $48, %rsp
321
322## UINT64  Rip;
323    popq    24(%rbp)
324
325## UINT64  Gs, Fs, Es, Ds, Cs, Ss;
326    popq    %rax
327    # mov   gs, rax ; not for gs
328    popq    %rax
329    # mov   fs, rax ; not for fs
330    # (X64 will not use fs and gs, so we do not restore it)
331    popq    %rax
332    movq    %rax, %es
333    popq    %rax
334    movq    %rax, %ds
335    popq    32(%rbp)                      # for cs
336    popq    56(%rbp)                      # for ss
337
338## UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
339## UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
340    popq    %rdi
341    popq    %rsi
342    addq    $8, %rsp                      # not for rbp
343    popq    48(%rbp)                      # for rsp
344    popq    %rbx
345    popq    %rdx
346    popq    %rcx
347    popq    %rax
348    popq    %r8
349    popq    %r9
350    popq    %r10
351    popq    %r11
352    popq    %r12
353    popq    %r13
354    popq    %r14
355    popq    %r15
356
357    movq    %rbp, %rsp
358
359# Enable TF bit after page fault handler runs
360    btsl    $8, 40(%rsp)                 #RFLAGS
361
362    popq    %rbp
363    addq    $16, %rsp                    # skip INT# & ErrCode
364    iretq
365
366