123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- ;------------------------------------------------------------------------------ ;
- ; Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
- ; SPDX-License-Identifier: BSD-2-Clause-Patent
- ;
- ; Module Name:
- ;
- ; SmiException.nasm
- ;
- ; Abstract:
- ;
- ; Exception handlers used in SM mode
- ;
- ;-------------------------------------------------------------------------------
- extern ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
- extern ASM_PFX(SmiPFHandler)
- extern ASM_PFX(mSetupDebugTrap)
- global ASM_PFX(gcSmiIdtr)
- global ASM_PFX(gcSmiGdtr)
- global ASM_PFX(gTaskGateDescriptor)
- global ASM_PFX(gcPsd)
- SECTION .data
- NullSeg: DQ 0 ; reserved by architecture
- CodeSeg32:
- DW -1 ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x9b
- DB 0xcf ; LimitHigh
- DB 0 ; BaseHigh
- ProtModeCodeSeg32:
- DW -1 ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x9b
- DB 0xcf ; LimitHigh
- DB 0 ; BaseHigh
- ProtModeSsSeg32:
- DW -1 ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x93
- DB 0xcf ; LimitHigh
- DB 0 ; BaseHigh
- DataSeg32:
- DW -1 ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x93
- DB 0xcf ; LimitHigh
- DB 0 ; BaseHigh
- CodeSeg16:
- DW -1
- DW 0
- DB 0
- DB 0x9b
- DB 0x8f
- DB 0
- DataSeg16:
- DW -1
- DW 0
- DB 0
- DB 0x93
- DB 0x8f
- DB 0
- CodeSeg64:
- DW -1 ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x9b
- DB 0xaf ; LimitHigh
- DB 0 ; BaseHigh
- GDT_SIZE equ $ - NullSeg
- TssSeg:
- DW TSS_DESC_SIZE ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x89
- DB 0x80 ; LimitHigh
- DB 0 ; BaseHigh
- ExceptionTssSeg:
- DW EXCEPTION_TSS_DESC_SIZE ; LimitLow
- DW 0 ; BaseLow
- DB 0 ; BaseMid
- DB 0x89
- DB 0x80 ; LimitHigh
- DB 0 ; BaseHigh
- CODE_SEL equ CodeSeg32 - NullSeg
- DATA_SEL equ DataSeg32 - NullSeg
- TSS_SEL equ TssSeg - NullSeg
- EXCEPTION_TSS_SEL equ ExceptionTssSeg - NullSeg
- struc IA32_TSS
- resw 1
- resw 1
- .ESP0: resd 1
- .SS0: resw 1
- resw 1
- .ESP1: resd 1
- .SS1: resw 1
- resw 1
- .ESP2: resd 1
- .SS2: resw 1
- resw 1
- ._CR3: resd 1
- .EIP: resd 1
- .EFLAGS: resd 1
- ._EAX: resd 1
- ._ECX: resd 1
- ._EDX: resd 1
- ._EBX: resd 1
- ._ESP: resd 1
- ._EBP: resd 1
- ._ESI: resd 1
- ._EDI: resd 1
- ._ES: resw 1
- resw 1
- ._CS: resw 1
- resw 1
- ._SS: resw 1
- resw 1
- ._DS: resw 1
- resw 1
- ._FS: resw 1
- resw 1
- ._GS: resw 1
- resw 1
- .LDT: resw 1
- resw 1
- resw 1
- resw 1
- endstruc
- ; Create 2 TSS segments just after GDT
- TssDescriptor:
- DW 0 ; PreviousTaskLink
- DW 0 ; Reserved
- DD 0 ; ESP0
- DW 0 ; SS0
- DW 0 ; Reserved
- DD 0 ; ESP1
- DW 0 ; SS1
- DW 0 ; Reserved
- DD 0 ; ESP2
- DW 0 ; SS2
- DW 0 ; Reserved
- DD 0 ; CR3
- DD 0 ; EIP
- DD 0 ; EFLAGS
- DD 0 ; EAX
- DD 0 ; ECX
- DD 0 ; EDX
- DD 0 ; EBX
- DD 0 ; ESP
- DD 0 ; EBP
- DD 0 ; ESI
- DD 0 ; EDI
- DW 0 ; ES
- DW 0 ; Reserved
- DW 0 ; CS
- DW 0 ; Reserved
- DW 0 ; SS
- DW 0 ; Reserved
- DW 0 ; DS
- DW 0 ; Reserved
- DW 0 ; FS
- DW 0 ; Reserved
- DW 0 ; GS
- DW 0 ; Reserved
- DW 0 ; LDT Selector
- DW 0 ; Reserved
- DW 0 ; T
- DW 0 ; I/O Map Base
- TSS_DESC_SIZE equ $ - TssDescriptor
- ExceptionTssDescriptor:
- DW 0 ; PreviousTaskLink
- DW 0 ; Reserved
- DD 0 ; ESP0
- DW 0 ; SS0
- DW 0 ; Reserved
- DD 0 ; ESP1
- DW 0 ; SS1
- DW 0 ; Reserved
- DD 0 ; ESP2
- DW 0 ; SS2
- DW 0 ; Reserved
- DD 0 ; CR3
- DD PFHandlerEntry ; EIP
- DD 00000002 ; EFLAGS
- DD 0 ; EAX
- DD 0 ; ECX
- DD 0 ; EDX
- DD 0 ; EBX
- DD 0 ; ESP
- DD 0 ; EBP
- DD 0 ; ESI
- DD 0 ; EDI
- DW DATA_SEL ; ES
- DW 0 ; Reserved
- DW CODE_SEL ; CS
- DW 0 ; Reserved
- DW DATA_SEL ; SS
- DW 0 ; Reserved
- DW DATA_SEL ; DS
- DW 0 ; Reserved
- DW DATA_SEL ; FS
- DW 0 ; Reserved
- DW DATA_SEL ; GS
- DW 0 ; Reserved
- DW 0 ; LDT Selector
- DW 0 ; Reserved
- DW 0 ; T
- DW 0 ; I/O Map Base
- DD 0 ; SSP
- EXCEPTION_TSS_DESC_SIZE equ $ - ExceptionTssDescriptor
- ASM_PFX(gcPsd):
- DB 'PSDSIG '
- DW PSD_SIZE
- DW 2
- DW 1 << 2
- DW CODE_SEL
- DW DATA_SEL
- DW DATA_SEL
- DW DATA_SEL
- DW 0
- DQ 0
- DQ 0
- DQ 0
- DD 0
- DD NullSeg
- DD GDT_SIZE
- DD 0
- times 24 DB 0
- DD 0
- DD 0
- PSD_SIZE equ $ - ASM_PFX(gcPsd)
- ASM_PFX(gcSmiGdtr):
- DW GDT_SIZE - 1
- DD NullSeg
- ASM_PFX(gcSmiIdtr):
- DW 0
- DD 0
- ASM_PFX(gTaskGateDescriptor):
- DW 0 ; Reserved
- DW EXCEPTION_TSS_SEL ; TSS Segment selector
- DB 0 ; Reserved
- DB 0x85 ; Task Gate, present, DPL = 0
- DW 0 ; Reserved
- SECTION .text
- ;------------------------------------------------------------------------------
- ; PageFaultIdtHandlerSmmProfile is the entry point page fault only
- ;
- ;
- ; Stack:
- ; +---------------------+
- ; + EFlags +
- ; +---------------------+
- ; + CS +
- ; +---------------------+
- ; + EIP +
- ; +---------------------+
- ; + Error Code +
- ; +---------------------+
- ; + Vector Number +
- ; +---------------------+
- ; + EBP +
- ; +---------------------+ <-- EBP
- ;
- ;
- ;------------------------------------------------------------------------------
- global ASM_PFX(PageFaultIdtHandlerSmmProfile)
- ASM_PFX(PageFaultIdtHandlerSmmProfile):
- push 0xe ; Page Fault
- push ebp
- mov ebp, esp
- ;
- ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
- ; is 16-byte aligned
- ;
- and esp, 0xfffffff0
- sub esp, 12
- ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
- push eax
- push ecx
- push edx
- push ebx
- lea ecx, [ebp + 6 * 4]
- push ecx ; ESP
- push dword [ebp] ; EBP
- push esi
- push edi
- ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
- mov eax, ss
- push eax
- movzx eax, word [ebp + 4 * 4]
- push eax
- mov eax, ds
- push eax
- mov eax, es
- push eax
- mov eax, fs
- push eax
- mov eax, gs
- push eax
- ;; UINT32 Eip;
- mov eax, [ebp + 3 * 4]
- push eax
- ;; UINT32 Gdtr[2], Idtr[2];
- sub esp, 8
- sidt [esp]
- mov eax, [esp + 2]
- xchg eax, [esp]
- and eax, 0xFFFF
- mov [esp+4], eax
- sub esp, 8
- sgdt [esp]
- mov eax, [esp + 2]
- xchg eax, [esp]
- and eax, 0xFFFF
- mov [esp+4], eax
- ;; UINT32 Ldtr, Tr;
- xor eax, eax
- str ax
- push eax
- sldt ax
- push eax
- ;; UINT32 EFlags;
- mov eax, [ebp + 5 * 4]
- push eax
- ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
- mov eax, cr4
- or eax, 0x208
- mov cr4, eax
- push eax
- mov eax, cr3
- push eax
- mov eax, cr2
- push eax
- xor eax, eax
- push eax
- mov eax, cr0
- push eax
- ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- mov eax, dr7
- push eax
- mov eax, dr6
- push eax
- mov eax, dr3
- push eax
- mov eax, dr2
- push eax
- mov eax, dr1
- push eax
- mov eax, dr0
- push eax
- ;; FX_SAVE_STATE_IA32 FxSaveState;
- sub esp, 512
- mov edi, esp
- fxsave [edi]
- ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
- cld
- ;; UINT32 ExceptionData;
- push dword [ebp + 2 * 4]
- ;; call into exception handler
- ;; Prepare parameter and call
- mov edx, esp
- push edx
- mov edx, dword [ebp + 1 * 4]
- push edx
- ;
- ; Call External Exception Handler
- ;
- mov eax, ASM_PFX(SmiPFHandler)
- call eax
- add esp, 8
- ;; UINT32 ExceptionData;
- add esp, 4
- ;; FX_SAVE_STATE_IA32 FxSaveState;
- mov esi, esp
- fxrstor [esi]
- add esp, 512
- ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- ;; Skip restoration of DRx registers to support debuggers
- ;; that set breakpoint in interrupt/exception context
- add esp, 4 * 6
- ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
- pop eax
- mov cr0, eax
- add esp, 4 ; not for Cr1
- pop eax
- mov cr2, eax
- pop eax
- mov cr3, eax
- pop eax
- mov cr4, eax
- ;; UINT32 EFlags;
- pop dword [ebp + 5 * 4]
- ;; UINT32 Ldtr, Tr;
- ;; UINT32 Gdtr[2], Idtr[2];
- ;; Best not let anyone mess with these particular registers...
- add esp, 24
- ;; UINT32 Eip;
- pop dword [ebp + 3 * 4]
- ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
- ;; NOTE - modified segment registers could hang the debugger... We
- ;; could attempt to insulate ourselves against this possibility,
- ;; but that poses risks as well.
- ;;
- pop gs
- pop fs
- pop es
- pop ds
- pop dword [ebp + 4 * 4]
- pop ss
- ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
- pop edi
- pop esi
- add esp, 4 ; not for ebp
- add esp, 4 ; not for esp
- pop ebx
- pop edx
- pop ecx
- pop eax
- mov esp, ebp
- pop ebp
- ; Enable TF bit after page fault handler runs
- bts dword [esp + 16], 8 ; EFLAGS
- add esp, 8 ; skip INT# & ErrCode
- Return:
- iretd
- ;
- ; Page Fault Exception Handler entry when SMM Stack Guard is enabled
- ; Executiot starts here after a task switch
- ;
- PFHandlerEntry:
- ;
- ; Get this processor's TSS
- ;
- sub esp, 8
- sgdt [esp + 2]
- mov eax, [esp + 4] ; GDT base
- add esp, 8
- mov ecx, [eax + TSS_SEL + 2]
- shl ecx, 8
- mov cl, [eax + TSS_SEL + 7]
- ror ecx, 8 ; ecx = TSS base
- mov ebp, esp
- ;
- ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
- ; is 16-byte aligned
- ;
- and esp, 0xfffffff0
- sub esp, 12
- ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
- push dword [ecx + IA32_TSS._EAX]
- push dword [ecx + IA32_TSS._ECX]
- push dword [ecx + IA32_TSS._EDX]
- push dword [ecx + IA32_TSS._EBX]
- push dword [ecx + IA32_TSS._ESP]
- push dword [ecx + IA32_TSS._EBP]
- push dword [ecx + IA32_TSS._ESI]
- push dword [ecx + IA32_TSS._EDI]
- ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
- movzx eax, word [ecx + IA32_TSS._SS]
- push eax
- movzx eax, word [ecx + IA32_TSS._CS]
- push eax
- movzx eax, word [ecx + IA32_TSS._DS]
- push eax
- movzx eax, word [ecx + IA32_TSS._ES]
- push eax
- movzx eax, word [ecx + IA32_TSS._FS]
- push eax
- movzx eax, word [ecx + IA32_TSS._GS]
- push eax
- ;; UINT32 Eip;
- push dword [ecx + IA32_TSS.EIP]
- ;; UINT32 Gdtr[2], Idtr[2];
- sub esp, 8
- sidt [esp]
- mov eax, [esp + 2]
- xchg eax, [esp]
- and eax, 0xFFFF
- mov [esp+4], eax
- sub esp, 8
- sgdt [esp]
- mov eax, [esp + 2]
- xchg eax, [esp]
- and eax, 0xFFFF
- mov [esp+4], eax
- ;; UINT32 Ldtr, Tr;
- mov eax, TSS_SEL
- push eax
- movzx eax, word [ecx + IA32_TSS.LDT]
- push eax
- ;; UINT32 EFlags;
- push dword [ecx + IA32_TSS.EFLAGS]
- ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
- mov eax, cr4
- or eax, 0x208
- mov cr4, eax
- push eax
- mov eax, cr3
- push eax
- mov eax, cr2
- push eax
- xor eax, eax
- push eax
- mov eax, cr0
- push eax
- ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- mov eax, dr7
- push eax
- mov eax, dr6
- push eax
- mov eax, dr3
- push eax
- mov eax, dr2
- push eax
- mov eax, dr1
- push eax
- mov eax, dr0
- push eax
- ;; FX_SAVE_STATE_IA32 FxSaveState;
- ;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
- ;; when executing fxsave/fxrstor instruction
- clts
- sub esp, 512
- mov edi, esp
- fxsave [edi]
- ; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
- cld
- ;; UINT32 ExceptionData;
- push dword [ebp]
- ;; call into exception handler
- mov ebx, ecx
- mov eax, ASM_PFX(SmiPFHandler)
- ;; Prepare parameter and call
- mov edx, esp
- push edx
- mov edx, 14
- push edx
- ;
- ; Call External Exception Handler
- ;
- call eax
- add esp, 8
- mov ecx, ebx
- ;; UINT32 ExceptionData;
- add esp, 4
- ;; FX_SAVE_STATE_IA32 FxSaveState;
- mov esi, esp
- fxrstor [esi]
- add esp, 512
- ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
- ;; Skip restoration of DRx registers to support debuggers
- ;; that set breakpoints in interrupt/exception context
- add esp, 4 * 6
- ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
- pop eax
- mov cr0, eax
- add esp, 4 ; not for Cr1
- pop eax
- mov cr2, eax
- pop eax
- mov dword [ecx + IA32_TSS._CR3], eax
- pop eax
- mov cr4, eax
- ;; UINT32 EFlags;
- pop dword [ecx + IA32_TSS.EFLAGS]
- ;; UINT32 Ldtr, Tr;
- ;; UINT32 Gdtr[2], Idtr[2];
- ;; Best not let anyone mess with these particular registers...
- add esp, 24
- ;; UINT32 Eip;
- pop dword [ecx + IA32_TSS.EIP]
- ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
- ;; NOTE - modified segment registers could hang the debugger... We
- ;; could attempt to insulate ourselves against this possibility,
- ;; but that poses risks as well.
- ;;
- pop eax
- o16 mov [ecx + IA32_TSS._GS], ax
- pop eax
- o16 mov [ecx + IA32_TSS._FS], ax
- pop eax
- o16 mov [ecx + IA32_TSS._ES], ax
- pop eax
- o16 mov [ecx + IA32_TSS._DS], ax
- pop eax
- o16 mov [ecx + IA32_TSS._CS], ax
- pop eax
- o16 mov [ecx + IA32_TSS._SS], ax
- ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
- pop dword [ecx + IA32_TSS._EDI]
- pop dword [ecx + IA32_TSS._ESI]
- add esp, 4 ; not for ebp
- add esp, 4 ; not for esp
- pop dword [ecx + IA32_TSS._EBX]
- pop dword [ecx + IA32_TSS._EDX]
- pop dword [ecx + IA32_TSS._ECX]
- pop dword [ecx + IA32_TSS._EAX]
- mov esp, ebp
- ; Set single step DB# if SMM profile is enabled and page fault exception happens
- cmp byte [dword ASM_PFX(mSetupDebugTrap)], 0
- jz @Done2
- ; Create return context for iretd in stub function
- mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
- mov ebx, dword [ecx + IA32_TSS.EIP]
- mov [eax - 0xc], ebx ; create EIP in old stack
- movzx ebx, word [ecx + IA32_TSS._CS]
- mov [eax - 0x8], ebx ; create CS in old stack
- mov ebx, dword [ecx + IA32_TSS.EFLAGS]
- bts ebx, 8
- mov [eax - 0x4], ebx ; create eflags in old stack
- mov eax, dword [ecx + IA32_TSS._ESP] ; Get old stack pointer
- sub eax, 0xc ; minus 12 byte
- mov dword [ecx + IA32_TSS._ESP], eax ; Set new stack pointer
- ; Replace the EIP of interrupted task with stub function
- mov eax, ASM_PFX(PageFaultStubFunction)
- mov dword [ecx + IA32_TSS.EIP], eax
- ; Jump to the iretd so next page fault handler as a task will start again after iretd.
- @Done2:
- add esp, 4 ; skip ErrCode
- jmp Return
- global ASM_PFX(PageFaultStubFunction)
- ASM_PFX(PageFaultStubFunction):
- ;
- ; we need clean TS bit in CR0 to execute
- ; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
- ;
- clts
- iretd
|