https://bugzilla.tianocore.org/show_bug.cgi?id=849
In V2, use "mov rax, strict qword 0" to replace the hard code db.
1. Use lea instruction to get the address instead of mov instruction.
2. Use the dummy address as jmp destination, and add the logic to fix up
the address to the absolute address at boot time.
3. On MpFuncs.nasm, use ExchangeInfo to record InitializeFloatingPointUnits.
This way is same to MpInitLib.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Liming Gao <liming.gao@intel.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
(cherry picked from commit e21e355e2c
)
# Conflicts:
# UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
385 lines
11 KiB
NASM
385 lines
11 KiB
NASM
;------------------------------------------------------------------------------ ;
|
|
; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
; This program and the accompanying materials
|
|
; are licensed and made available under the terms and conditions of the BSD License
|
|
; which accompanies this distribution. The full text of the license may be found at
|
|
; http://opensource.org/licenses/bsd-license.php.
|
|
;
|
|
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
;
|
|
; Module Name:
|
|
;
|
|
; SmiException.nasm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; Exception handlers used in SM mode
|
|
;
|
|
;-------------------------------------------------------------------------------
|
|
|
|
extern ASM_PFX(SmiPFHandler)
|
|
|
|
global ASM_PFX(gcSmiIdtr)
|
|
global ASM_PFX(gcSmiGdtr)
|
|
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
|
|
; TSS Segment for X64 specially
|
|
TssSeg:
|
|
DW TSS_DESC_SIZE ; LimitLow
|
|
DW 0 ; BaseLow
|
|
DB 0 ; BaseMid
|
|
DB 0x89
|
|
DB 0x80 ; LimitHigh
|
|
DB 0 ; BaseHigh
|
|
DD 0 ; BaseUpper
|
|
DD 0 ; Reserved
|
|
GDT_SIZE equ $ - NullSeg
|
|
|
|
; Create TSS Descriptor just after GDT
|
|
TssDescriptor:
|
|
DD 0 ; Reserved
|
|
DQ 0 ; RSP0
|
|
DQ 0 ; RSP1
|
|
DQ 0 ; RSP2
|
|
DD 0 ; Reserved
|
|
DD 0 ; Reserved
|
|
DQ 0 ; IST1
|
|
DQ 0 ; IST2
|
|
DQ 0 ; IST3
|
|
DQ 0 ; IST4
|
|
DQ 0 ; IST5
|
|
DQ 0 ; IST6
|
|
DQ 0 ; IST7
|
|
DD 0 ; Reserved
|
|
DD 0 ; Reserved
|
|
DW 0 ; Reserved
|
|
DW 0 ; I/O Map Base Address
|
|
TSS_DESC_SIZE equ $ - TssDescriptor
|
|
|
|
;
|
|
; This structure serves as a template for all processors.
|
|
;
|
|
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 ; fixed in InitializeMpServiceData()
|
|
DQ NullSeg
|
|
DD GDT_SIZE
|
|
DD 0
|
|
times 24 DB 0
|
|
DQ 0
|
|
PSD_SIZE equ $ - ASM_PFX(gcPsd)
|
|
|
|
;
|
|
; CODE & DATA segments for SMM runtime
|
|
;
|
|
CODE_SEL equ CodeSeg64 - NullSeg
|
|
DATA_SEL equ DataSeg32 - NullSeg
|
|
CODE32_SEL equ CodeSeg32 - NullSeg
|
|
|
|
ASM_PFX(gcSmiGdtr):
|
|
DW GDT_SIZE - 1
|
|
DQ NullSeg
|
|
|
|
ASM_PFX(gcSmiIdtr):
|
|
DW 0
|
|
DQ 0
|
|
|
|
DEFAULT REL
|
|
SECTION .text
|
|
|
|
;------------------------------------------------------------------------------
|
|
; _SmiExceptionEntryPoints is the collection of exception entrypoints followed
|
|
; by a common exception handler.
|
|
;
|
|
; Stack frame would be as follows as specified in IA32 manuals:
|
|
;
|
|
; +---------------------+ <-- 16-byte aligned ensured by processor
|
|
; + Old SS +
|
|
; +---------------------+
|
|
; + Old RSP +
|
|
; +---------------------+
|
|
; + RFlags +
|
|
; +---------------------+
|
|
; + CS +
|
|
; +---------------------+
|
|
; + RIP +
|
|
; +---------------------+
|
|
; + Error Code +
|
|
; +---------------------+
|
|
; + Vector Number +
|
|
; +---------------------+
|
|
; + RBP +
|
|
; +---------------------+ <-- RBP, 16-byte aligned
|
|
;
|
|
; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
|
|
;------------------------------------------------------------------------------
|
|
global ASM_PFX(PageFaultIdtHandlerSmmProfile)
|
|
ASM_PFX(PageFaultIdtHandlerSmmProfile):
|
|
push 0xe ; Page Fault
|
|
test spl, 8 ; odd multiple of 8 => ErrCode present
|
|
jnz .0
|
|
push qword [rsp] ; duplicate INT# if no ErrCode
|
|
mov qword [rsp + 8], 0
|
|
.0:
|
|
push rbp
|
|
mov rbp, rsp
|
|
|
|
;
|
|
; Since here the stack pointer is 16-byte aligned, so
|
|
; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
|
|
; is 16-byte aligned
|
|
;
|
|
|
|
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
|
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
|
push r15
|
|
push r14
|
|
push r13
|
|
push r12
|
|
push r11
|
|
push r10
|
|
push r9
|
|
push r8
|
|
push rax
|
|
push rcx
|
|
push rdx
|
|
push rbx
|
|
push qword [rbp + 48] ; RSP
|
|
push qword [rbp] ; RBP
|
|
push rsi
|
|
push rdi
|
|
|
|
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
|
movzx rax, word [rbp + 56]
|
|
push rax ; for ss
|
|
movzx rax, word [rbp + 32]
|
|
push rax ; for cs
|
|
mov rax, ds
|
|
push rax
|
|
mov rax, es
|
|
push rax
|
|
mov rax, fs
|
|
push rax
|
|
mov rax, gs
|
|
push rax
|
|
|
|
;; UINT64 Rip;
|
|
push qword [rbp + 24]
|
|
|
|
;; UINT64 Gdtr[2], Idtr[2];
|
|
sub rsp, 16
|
|
sidt [rsp]
|
|
sub rsp, 16
|
|
sgdt [rsp]
|
|
|
|
;; UINT64 Ldtr, Tr;
|
|
xor rax, rax
|
|
str ax
|
|
push rax
|
|
sldt ax
|
|
push rax
|
|
|
|
;; UINT64 RFlags;
|
|
push qword [rbp + 40]
|
|
|
|
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
|
mov rax, cr8
|
|
push rax
|
|
mov rax, cr4
|
|
or rax, 0x208
|
|
mov cr4, rax
|
|
push rax
|
|
mov rax, cr3
|
|
push rax
|
|
mov rax, cr2
|
|
push rax
|
|
xor rax, rax
|
|
push rax
|
|
mov rax, cr0
|
|
push rax
|
|
|
|
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
|
mov rax, dr7
|
|
push rax
|
|
mov rax, dr6
|
|
push rax
|
|
mov rax, dr3
|
|
push rax
|
|
mov rax, dr2
|
|
push rax
|
|
mov rax, dr1
|
|
push rax
|
|
mov rax, dr0
|
|
push rax
|
|
|
|
;; FX_SAVE_STATE_X64 FxSaveState;
|
|
|
|
sub rsp, 512
|
|
mov rdi, rsp
|
|
db 0xf, 0xae, 00000111y ;fxsave [rdi]
|
|
|
|
; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
|
|
cld
|
|
|
|
;; UINT32 ExceptionData;
|
|
push qword [rbp + 16]
|
|
|
|
;; call into exception handler
|
|
mov rcx, [rbp + 8]
|
|
lea rax, [ASM_PFX(SmiPFHandler)]
|
|
|
|
;; Prepare parameter and call
|
|
mov rdx, rsp
|
|
;
|
|
; Per X64 calling convention, allocate maximum parameter stack space
|
|
; and make sure RSP is 16-byte aligned
|
|
;
|
|
sub rsp, 4 * 8 + 8
|
|
call rax
|
|
add rsp, 4 * 8 + 8
|
|
jmp .1
|
|
|
|
.1:
|
|
;; UINT64 ExceptionData;
|
|
add rsp, 8
|
|
|
|
;; FX_SAVE_STATE_X64 FxSaveState;
|
|
|
|
mov rsi, rsp
|
|
db 0xf, 0xae, 00001110y ; fxrstor [rsi]
|
|
add rsp, 512
|
|
|
|
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
|
;; Skip restoration of DRx registers to support debuggers
|
|
;; that set breakpoints in interrupt/exception context
|
|
add rsp, 8 * 6
|
|
|
|
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
|
pop rax
|
|
mov cr0, rax
|
|
add rsp, 8 ; not for Cr1
|
|
pop rax
|
|
mov cr2, rax
|
|
pop rax
|
|
mov cr3, rax
|
|
pop rax
|
|
mov cr4, rax
|
|
pop rax
|
|
mov cr8, rax
|
|
|
|
;; UINT64 RFlags;
|
|
pop qword [rbp + 40]
|
|
|
|
;; UINT64 Ldtr, Tr;
|
|
;; UINT64 Gdtr[2], Idtr[2];
|
|
;; Best not let anyone mess with these particular registers...
|
|
add rsp, 48
|
|
|
|
;; UINT64 Rip;
|
|
pop qword [rbp + 24]
|
|
|
|
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
|
pop rax
|
|
; mov gs, rax ; not for gs
|
|
pop rax
|
|
; mov fs, rax ; not for fs
|
|
; (X64 will not use fs and gs, so we do not restore it)
|
|
pop rax
|
|
mov es, rax
|
|
pop rax
|
|
mov ds, rax
|
|
pop qword [rbp + 32] ; for cs
|
|
pop qword [rbp + 56] ; for ss
|
|
|
|
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
|
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
|
pop rdi
|
|
pop rsi
|
|
add rsp, 8 ; not for rbp
|
|
pop qword [rbp + 48] ; for rsp
|
|
pop rbx
|
|
pop rdx
|
|
pop rcx
|
|
pop rax
|
|
pop r8
|
|
pop r9
|
|
pop r10
|
|
pop r11
|
|
pop r12
|
|
pop r13
|
|
pop r14
|
|
pop r15
|
|
|
|
mov rsp, rbp
|
|
|
|
; Enable TF bit after page fault handler runs
|
|
bts dword [rsp + 40], 8 ;RFLAGS
|
|
|
|
pop rbp
|
|
add rsp, 16 ; skip INT# & ErrCode
|
|
iretq
|
|
|