1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2009 - 2015, 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(gSmiMtrrs)
24ASM_GLOBAL  ASM_PFX(gcSmiIdtr)
25ASM_GLOBAL  ASM_PFX(gcSmiGdtr)
26ASM_GLOBAL  ASM_PFX(gcPsd)
27
28    .data
29
30NullSeg:    .quad 0                     # reserved by architecture
31CodeSeg32:
32            .word -1                    # LimitLow
33            .word 0                     # BaseLow
34            .byte 0                     # BaseMid
35            .byte 0x9b
36            .byte 0xcf                  # LimitHigh
37            .byte 0                     # BaseHigh
38ProtModeCodeSeg32:
39            .word -1                    # LimitLow
40            .word 0                     # BaseLow
41            .byte 0                     # BaseMid
42            .byte 0x9b
43            .byte 0xcf                  # LimitHigh
44            .byte 0                     # BaseHigh
45ProtModeSsSeg32:
46            .word -1                    # LimitLow
47            .word 0                     # BaseLow
48            .byte 0                     # BaseMid
49            .byte 0x93
50            .byte 0xcf                  # LimitHigh
51            .byte 0                     # BaseHigh
52DataSeg32:
53            .word -1                    # LimitLow
54            .word 0                     # BaseLow
55            .byte 0                     # BaseMid
56            .byte 0x93
57            .byte 0xcf                  # LimitHigh
58            .byte 0                     # BaseHigh
59CodeSeg16:
60            .word -1
61            .word 0
62            .byte 0
63            .byte 0x9b
64            .byte 0x8f
65            .byte 0
66DataSeg16:
67            .word -1
68            .word 0
69            .byte 0
70            .byte 0x93
71            .byte 0x8f
72            .byte 0
73CodeSeg64:
74            .word -1                    # LimitLow
75            .word 0                     # BaseLow
76            .byte 0                     # BaseMid
77            .byte 0x9b
78            .byte 0xaf                  # LimitHigh
79            .byte 0                     # BaseHigh
80# TSS Segment for X64 specially
81TssSeg:
82            .word TSS_DESC_SIZE - 1     # LimitLow
83            .word 0                     # BaseLow
84            .byte 0                     # BaseMid
85            .byte 0x89
86            .byte 0x00                  # LimitHigh
87            .byte 0                     # BaseHigh
88            .long 0                     # BaseUpper
89            .long 0                     # Reserved
90.equ  GDT_SIZE, .- NullSeg
91
92TssDescriptor:
93            .space 104, 0
94.equ  TSS_DESC_SIZE, .- TssDescriptor
95
96#
97# This structure serves as a template for all processors.
98#
99ASM_PFX(gcPsd):
100            .ascii  "PSDSIG  "
101            .word      PSD_SIZE
102            .word 2
103            .word      1 << 2
104            .word      CODE_SEL
105            .word      DATA_SEL
106            .word      DATA_SEL
107            .word      DATA_SEL
108            .word 0
109            .quad 0
110            .quad 0
111            .quad 0                     # fixed in InitializeMpServiceData()
112            .quad      NullSeg
113            .long      GDT_SIZE
114            .long 0
115            .space 24, 0
116            .quad      ASM_PFX(gSmiMtrrs)
117.equ  PSD_SIZE,  . - ASM_PFX(gcPsd)
118
119#
120# CODE & DATA segments for SMM runtime
121#
122.equ  CODE_SEL,    CodeSeg64 - NullSeg
123.equ  DATA_SEL,    DataSeg32 - NullSeg
124.equ  CODE32_SEL,  CodeSeg32 - NullSeg
125
126ASM_PFX(gcSmiGdtr):
127    .word      GDT_SIZE - 1
128    .quad      NullSeg
129
130ASM_PFX(gcSmiIdtr):
131    .word      IDT_SIZE - 1
132    .quad      _SmiIDT
133
134
135#
136# Here is the IDT. There are 32 (not 255) entries in it since only processor
137# generated exceptions will be handled.
138#
139_SmiIDT:
140# The following segment repeats 32 times:
141# No. 1
142    .word 0                             # Offset 0:15
143    .word CODE_SEL
144    .byte 0                             # Unused
145    .byte 0x8e                          # Interrupt Gate, Present
146    .word 0                             # Offset 16:31
147    .quad 0                             # Offset 32:63
148# No. 2
149    .word 0                             # Offset 0:15
150    .word CODE_SEL
151    .byte 0                             # Unused
152    .byte 0x8e                          # Interrupt Gate, Present
153    .word 0                             # Offset 16:31
154    .quad 0                             # Offset 32:63
155# No. 3
156    .word 0                             # Offset 0:15
157    .word CODE_SEL
158    .byte 0                             # Unused
159    .byte 0x8e                          # Interrupt Gate, Present
160    .word 0                             # Offset 16:31
161    .quad 0                             # Offset 32:63
162# No. 4
163    .word 0                             # Offset 0:15
164    .word CODE_SEL
165    .byte 0                             # Unused
166    .byte 0x8e                          # Interrupt Gate, Present
167    .word 0                             # Offset 16:31
168    .quad 0                             # Offset 32:63
169# No. 5
170    .word 0                             # Offset 0:15
171    .word CODE_SEL
172    .byte 0                             # Unused
173    .byte 0x8e                          # Interrupt Gate, Present
174    .word 0                             # Offset 16:31
175    .quad 0                             # Offset 32:63
176# No. 6
177    .word 0                             # Offset 0:15
178    .word CODE_SEL
179    .byte 0                             # Unused
180    .byte 0x8e                          # Interrupt Gate, Present
181    .word 0                             # Offset 16:31
182    .quad 0                             # Offset 32:63
183# No. 7
184    .word 0                             # Offset 0:15
185    .word CODE_SEL
186    .byte 0                             # Unused
187    .byte 0x8e                          # Interrupt Gate, Present
188    .word 0                             # Offset 16:31
189    .quad 0                             # Offset 32:63
190# No. 8
191    .word 0                             # Offset 0:15
192    .word CODE_SEL
193    .byte 0                             # Unused
194    .byte 0x8e                          # Interrupt Gate, Present
195    .word 0                             # Offset 16:31
196    .quad 0                             # Offset 32:63
197# No. 9
198    .word 0                             # Offset 0:15
199    .word CODE_SEL
200    .byte 0                             # Unused
201    .byte 0x8e                          # Interrupt Gate, Present
202    .word 0                             # Offset 16:31
203    .quad 0                             # Offset 32:63
204# No. 10
205    .word 0                             # Offset 0:15
206    .word CODE_SEL
207    .byte 0                             # Unused
208    .byte 0x8e                          # Interrupt Gate, Present
209    .word 0                             # Offset 16:31
210    .quad 0                             # Offset 32:63
211# No. 11
212    .word 0                             # Offset 0:15
213    .word CODE_SEL
214    .byte 0                             # Unused
215    .byte 0x8e                          # Interrupt Gate, Present
216    .word 0                             # Offset 16:31
217    .quad 0                             # Offset 32:63
218# No. 12
219    .word 0                             # Offset 0:15
220    .word CODE_SEL
221    .byte 0                             # Unused
222    .byte 0x8e                          # Interrupt Gate, Present
223    .word 0                             # Offset 16:31
224    .quad 0                             # Offset 32:63
225# No. 13
226    .word 0                             # Offset 0:15
227    .word CODE_SEL
228    .byte 0                             # Unused
229    .byte 0x8e                          # Interrupt Gate, Present
230    .word 0                             # Offset 16:31
231    .quad 0                             # Offset 32:63
232# No. 14
233    .word 0                             # Offset 0:15
234    .word CODE_SEL
235    .byte 0                             # Unused
236    .byte 0x8e                          # Interrupt Gate, Present
237    .word 0                             # Offset 16:31
238    .quad 0                             # Offset 32:63
239# No. 15
240    .word 0                             # Offset 0:15
241    .word CODE_SEL
242    .byte 0                             # Unused
243    .byte 0x8e                          # Interrupt Gate, Present
244    .word 0                             # Offset 16:31
245    .quad 0                             # Offset 32:63
246# No. 16
247    .word 0                             # Offset 0:15
248    .word CODE_SEL
249    .byte 0                             # Unused
250    .byte 0x8e                          # Interrupt Gate, Present
251    .word 0                             # Offset 16:31
252    .quad 0                             # Offset 32:63
253# No. 17
254    .word 0                             # Offset 0:15
255    .word CODE_SEL
256    .byte 0                             # Unused
257    .byte 0x8e                          # Interrupt Gate, Present
258    .word 0                             # Offset 16:31
259    .quad 0                             # Offset 32:63
260# No. 18
261    .word 0                             # Offset 0:15
262    .word CODE_SEL
263    .byte 0                             # Unused
264    .byte 0x8e                          # Interrupt Gate, Present
265    .word 0                             # Offset 16:31
266    .quad 0                             # Offset 32:63
267# No. 19
268    .word 0                             # Offset 0:15
269    .word CODE_SEL
270    .byte 0                             # Unused
271    .byte 0x8e                          # Interrupt Gate, Present
272    .word 0                             # Offset 16:31
273    .quad 0                             # Offset 32:63
274# No. 20
275    .word 0                             # Offset 0:15
276    .word CODE_SEL
277    .byte 0                             # Unused
278    .byte 0x8e                          # Interrupt Gate, Present
279    .word 0                             # Offset 16:31
280    .quad 0                             # Offset 32:63
281# No. 21
282    .word 0                             # Offset 0:15
283    .word CODE_SEL
284    .byte 0                             # Unused
285    .byte 0x8e                          # Interrupt Gate, Present
286    .word 0                             # Offset 16:31
287    .quad 0                             # Offset 32:63
288# No. 22
289    .word 0                             # Offset 0:15
290    .word CODE_SEL
291    .byte 0                             # Unused
292    .byte 0x8e                          # Interrupt Gate, Present
293    .word 0                             # Offset 16:31
294    .quad 0                             # Offset 32:63
295# No. 23
296    .word 0                             # Offset 0:15
297    .word CODE_SEL
298    .byte 0                             # Unused
299    .byte 0x8e                          # Interrupt Gate, Present
300    .word 0                             # Offset 16:31
301    .quad 0                             # Offset 32:63
302# No. 24
303    .word 0                             # Offset 0:15
304    .word CODE_SEL
305    .byte 0                             # Unused
306    .byte 0x8e                          # Interrupt Gate, Present
307    .word 0                             # Offset 16:31
308    .quad 0                             # Offset 32:63
309# No. 25
310    .word 0                             # Offset 0:15
311    .word CODE_SEL
312    .byte 0                             # Unused
313    .byte 0x8e                          # Interrupt Gate, Present
314    .word 0                             # Offset 16:31
315    .quad 0                             # Offset 32:63
316# No. 26
317    .word 0                             # Offset 0:15
318    .word CODE_SEL
319    .byte 0                             # Unused
320    .byte 0x8e                          # Interrupt Gate, Present
321    .word 0                             # Offset 16:31
322    .quad 0                             # Offset 32:63
323# No. 27
324    .word 0                             # Offset 0:15
325    .word CODE_SEL
326    .byte 0                             # Unused
327    .byte 0x8e                          # Interrupt Gate, Present
328    .word 0                             # Offset 16:31
329    .quad 0                             # Offset 32:63
330# No. 28
331    .word 0                             # Offset 0:15
332    .word CODE_SEL
333    .byte 0                             # Unused
334    .byte 0x8e                          # Interrupt Gate, Present
335    .word 0                             # Offset 16:31
336    .quad 0                             # Offset 32:63
337# No. 29
338    .word 0                             # Offset 0:15
339    .word CODE_SEL
340    .byte 0                             # Unused
341    .byte 0x8e                          # Interrupt Gate, Present
342    .word 0                             # Offset 16:31
343    .quad 0                             # Offset 32:63
344# No. 30
345    .word 0                             # Offset 0:15
346    .word CODE_SEL
347    .byte 0                             # Unused
348    .byte 0x8e                          # Interrupt Gate, Present
349    .word 0                             # Offset 16:31
350    .quad 0                             # Offset 32:63
351# No. 31
352    .word 0                             # Offset 0:15
353    .word CODE_SEL
354    .byte 0                             # Unused
355    .byte 0x8e                          # Interrupt Gate, Present
356    .word 0                             # Offset 16:31
357    .quad 0                             # Offset 32:63
358# No. 32
359    .word 0                             # Offset 0:15
360    .word CODE_SEL
361    .byte 0                             # Unused
362    .byte 0x8e                          # Interrupt Gate, Present
363    .word 0                             # Offset 16:31
364    .quad 0                             # Offset 32:63
365
366_SmiIDTEnd:
367
368.equ  IDT_SIZE, (_SmiIDTEnd - _SmiIDT)
369
370    .text
371
372#------------------------------------------------------------------------------
373# _SmiExceptionEntryPoints is the collection of exception entry points followed
374# by a common exception handler.
375#
376# Stack frame would be as follows as specified in IA32 manuals:
377# +---------------------+ <-- 16-byte aligned ensured by processor
378# +    Old SS           +
379# +---------------------+
380# +    Old RSP          +
381# +---------------------+
382# +    RFlags           +
383# +---------------------+
384# +    CS               +
385# +---------------------+
386# +    RIP              +
387# +---------------------+
388# +    Error Code       +
389# +---------------------+
390# +   Vector Number     +
391# +---------------------+
392# +    RBP              +
393# +---------------------+ <-- RBP, 16-byte aligned
394#
395# RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
396#------------------------------------------------------------------------------
397ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
398ASM_PFX(PageFaultIdtHandlerSmmProfile):
399    pushq   $0x0e                    # Page Fault
400    .byte   0x40, 0xf6, 0xc4, 0x08    #test    spl, 8
401    jnz     L1
402    pushq   (%rsp)
403    movq    $0, 8(%rsp)
404L1:
405    pushq   %rbp
406    movq    %rsp, %rbp
407
408    #
409    # Since here the stack pointer is 16-byte aligned, so
410    # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
411    # is 16-byte aligned
412    #
413
414## UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
415## UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
416    pushq   %r15
417    pushq   %r14
418    pushq   %r13
419    pushq   %r12
420    pushq   %r11
421    pushq   %r10
422    pushq   %r9
423    pushq   %r8
424    pushq   %rax
425    pushq   %rcx
426    pushq   %rdx
427    pushq   %rbx
428    pushq   48(%rbp)                   # RSP
429    pushq   (%rbp)                     # RBP
430    pushq   %rsi
431    pushq   %rdi
432
433## UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
434    movzwq 56(%rbp), %rax
435    pushq   %rax                       # for ss
436    movzwq  32(%rbp), %rax
437    pushq   %rax                       # for cs
438    movq    %ds, %rax
439    pushq   %rax
440    movq    %es, %rax
441    pushq   %rax
442    movq    %fs, %rax
443    pushq   %rax
444    movq    %gs, %rax
445    pushq   %rax
446
447## UINT64  Rip;
448    pushq   24(%rbp)
449
450## UINT64  Gdtr[2], Idtr[2];
451    subq    $16, %rsp
452    sidt    (%rsp)
453    subq    $16, %rsp
454    sgdt    (%rsp)
455
456## UINT64  Ldtr, Tr;
457    xorq    %rax, %rax
458    strw    %ax
459    pushq   %rax
460    sldtw   %ax
461    pushq   %rax
462
463## UINT64  RFlags;
464    pushq   40(%rbp)
465
466## UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
467    movq    %cr8, %rax
468    pushq   %rax
469    movq    %cr4, %rax
470    orq     $0x208, %rax
471    movq    %rax, %cr4
472    pushq   %rax
473    movq    %cr3, %rax
474    pushq   %rax
475    movq    %cr2, %rax
476    pushq   %rax
477    xorq    %rax, %rax
478    pushq   %rax
479    movq    %cr0, %rax
480    pushq   %rax
481
482## UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
483    movq    %dr7, %rax
484    pushq   %rax
485    movq    %dr6, %rax
486    pushq   %rax
487    movq    %dr3, %rax
488    pushq   %rax
489    movq    %dr2, %rax
490    pushq   %rax
491    movq    %dr1, %rax
492    pushq   %rax
493    movq    %dr0, %rax
494    pushq   %rax
495
496## FX_SAVE_STATE_X64 FxSaveState;
497
498    subq    $512, %rsp
499    movq    %rsp, %rdi
500    .byte   0xf, 0xae, 0x7                  # fxsave [rdi]
501
502# UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
503    cld
504
505## UINT32  ExceptionData;
506    pushq   16(%rbp)
507
508## call into exception handler
509    movq    8(%rbp), %rcx
510    movabsq $ASM_PFX(SmiPFHandler), %rax
511
512## Prepare parameter and call
513    movq    %rsp, %rdx
514    #
515    # Per X64 calling convention, allocate maximum parameter stack space
516    # and make sure RSP is 16-byte aligned
517    #
518    subq    $4 * 8 + 8, %rsp
519    call    *%rax
520    addq    $4 * 8 + 8, %rsp
521    jmp     L5
522
523L5:
524## UINT64  ExceptionData;
525    addq    $8, %rsp
526
527## FX_SAVE_STATE_X64 FxSaveState;
528
529    movq    %rsp, %rsi
530    .byte   0xf, 0xae, 0xe                 # fxrstor [rsi]
531    addq    $512, %rsp
532
533## UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
534## Skip restoration of DRx registers to support debuggers
535## that set breakpoints in interrupt/exception context
536    addq    $8 * 6, %rsp
537
538## UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
539    popq    %rax
540    movq    %rax, %cr0
541    addq    $8, %rsp                      # not for Cr1
542    popq    %rax
543    movq    %rax, %cr2
544    popq    %rax
545    movq    %rax, %cr3
546    popq    %rax
547    movq    %rax, %cr4
548    popq    %rax
549    movq    %rax, %cr8
550
551## UINT64  RFlags;
552    popq    40(%rbp)
553
554## UINT64  Ldtr, Tr;
555## UINT64  Gdtr[2], Idtr[2];
556## Best not let anyone mess with these particular registers...
557    addq    $48, %rsp
558
559## UINT64  Rip;
560    popq    24(%rbp)
561
562## UINT64  Gs, Fs, Es, Ds, Cs, Ss;
563    popq    %rax
564    # mov   gs, rax ; not for gs
565    popq    %rax
566    # mov   fs, rax ; not for fs
567    # (X64 will not use fs and gs, so we do not restore it)
568    popq    %rax
569    movq    %rax, %es
570    popq    %rax
571    movq    %rax, %ds
572    popq    32(%rbp)                      # for cs
573    popq    56(%rbp)                      # for ss
574
575## UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
576## UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
577    popq    %rdi
578    popq    %rsi
579    addq    $8, %rsp                      # not for rbp
580    popq    48(%rbp)                      # for rsp
581    popq    %rbx
582    popq    %rdx
583    popq    %rcx
584    popq    %rax
585    popq    %r8
586    popq    %r9
587    popq    %r10
588    popq    %r11
589    popq    %r12
590    popq    %r13
591    popq    %r14
592    popq    %r15
593
594    movq    %rbp, %rsp
595
596# Enable TF bit after page fault handler runs
597    btsl    $8, 40(%rsp)                 #RFLAGS
598
599    popq    %rbp
600    addq    $16, %rsp                    # skip INT# & ErrCode
601    iretq
602
603ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)
604ASM_PFX(InitializeIDTSmmStackGuard):
605# If SMM Stack Guard feature is enabled, set the IST field of
606# the interrupt gate for Page Fault Exception to be 1
607#
608    movabsq  $_SmiIDT + 14 * 16, %rax
609    movb     $1, 4(%rax)
610    ret
611