2016-06-14 10:29:11 +02:00
|
|
|
;------------------------------------------------------------------------------ ;
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
; Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
|
2019-04-04 01:07:22 +02:00
|
|
|
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
2016-06-14 10:29:11 +02:00
|
|
|
;
|
|
|
|
; Module Name:
|
|
|
|
;
|
|
|
|
; SmiException.nasm
|
|
|
|
;
|
|
|
|
; Abstract:
|
|
|
|
;
|
|
|
|
; Exception handlers used in SM mode
|
|
|
|
;
|
|
|
|
;-------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
extern ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
|
|
|
|
extern ASM_PFX(SmiPFHandler)
|
2018-08-20 05:35:58 +02:00
|
|
|
extern ASM_PFX(mSetupDebugTrap)
|
2016-06-14 10:29:11 +02:00
|
|
|
|
|
|
|
global ASM_PFX(gcSmiIdtr)
|
|
|
|
global ASM_PFX(gcSmiGdtr)
|
2016-10-23 17:19:52 +02:00
|
|
|
global ASM_PFX(gTaskGateDescriptor)
|
2016-06-14 10:29:11 +02:00
|
|
|
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:
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
DW EXCEPTION_TSS_DESC_SIZE ; LimitLow
|
2016-06-14 10:29:11 +02:00
|
|
|
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
|
UefiCpuPkg/PiSmmCpu: Add Shadow Stack Support for X86 SMM.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1521
We scan the SMM code with ROPgadget.
http://shell-storm.org/project/ROPgadget/
https://github.com/JonathanSalwan/ROPgadget/tree/master
This tool reports the gadget in SMM driver.
This patch enabled CET ShadowStack for X86 SMM.
If CET is supported, SMM will enable CET ShadowStack.
SMM CET will save the OS CET context at SmmEntry and
restore OS CET context at SmmExit.
Test:
1) test Intel internal platform (x64 only, CET enabled/disabled)
Boot test:
CET supported or not supported CPU
on CET supported platform
CET enabled/disabled
PcdCpuSmmCetEnable enabled/disabled
Single core/Multiple core
PcdCpuSmmStackGuard enabled/disabled
PcdCpuSmmProfileEnable enabled/disabled
PcdCpuSmmStaticPageTable enabled/disabled
CET exception test:
#CF generated with PcdCpuSmmStackGuard enabled/disabled.
Other exception test:
#PF for normal stack overflow
#PF for NX protection
#PF for RO protection
CET env test:
Launch SMM in CET enabled/disabled environment (DXE) - no impact to DXE
The test case can be found at
https://github.com/jyao1/SecurityEx/tree/master/ControlFlowPkg
2) test ovmf (both IA32 and X64 SMM, CET disabled only)
test OvmfIa32/Ovmf3264, with -D SMM_REQUIRE.
qemu-system-x86_64.exe -machine q35,smm=on -smp 4
-serial file:serial.log
-drive if=pflash,format=raw,unit=0,file=OVMF_CODE.fd,readonly=on
-drive if=pflash,format=raw,unit=1,file=OVMF_VARS.fd
QEMU emulator version 3.1.0 (v3.1.0-11736-g7a30e7adb0-dirty)
3) not tested
IA32 CET enabled platform
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yao Jiewen <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
2019-02-22 14:30:36 +01:00
|
|
|
DD 0 ; SSP
|
|
|
|
EXCEPTION_TSS_DESC_SIZE equ $ - ExceptionTssDescriptor
|
2016-06-14 10:29:11 +02:00
|
|
|
|
|
|
|
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
|
2016-12-06 05:39:01 +01:00
|
|
|
DD 0
|
2016-06-14 10:29:11 +02:00
|
|
|
PSD_SIZE equ $ - ASM_PFX(gcPsd)
|
|
|
|
|
|
|
|
ASM_PFX(gcSmiGdtr):
|
|
|
|
DW GDT_SIZE - 1
|
|
|
|
DD NullSeg
|
|
|
|
|
|
|
|
ASM_PFX(gcSmiIdtr):
|
2016-10-23 17:19:52 +02:00
|
|
|
DW 0
|
|
|
|
DD 0
|
2016-06-14 10:29:11 +02:00
|
|
|
|
2016-10-23 17:19:52 +02:00
|
|
|
ASM_PFX(gTaskGateDescriptor):
|
2016-06-14 10:29:11 +02:00
|
|
|
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
|
2018-03-23 20:54:19 +01:00
|
|
|
fxsave [edi]
|
2016-06-14 10:29:11 +02:00
|
|
|
|
|
|
|
; 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
|
2018-03-23 20:54:19 +01:00
|
|
|
fxrstor [esi]
|
2016-06-14 10:29:11 +02:00
|
|
|
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
|
2018-03-23 20:54:19 +01:00
|
|
|
fxsave [edi]
|
2016-06-14 10:29:11 +02:00
|
|
|
|
|
|
|
; 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
|
2018-03-23 20:54:19 +01:00
|
|
|
fxrstor [esi]
|
2016-06-14 10:29:11 +02:00
|
|
|
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
|
2018-08-20 05:35:58 +02:00
|
|
|
cmp byte [dword ASM_PFX(mSetupDebugTrap)], 0
|
2016-06-14 10:29:11 +02:00
|
|
|
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
|
|
|
|
|