Move SmmDebug feature from ASM to C.

SmmDebug feature is implemented in ASM, which is not easy to maintain.
So we move it to C function.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: "Yao, Jiewen" <jiewen.yao@intel.com>
Reviewed-by: "Kinney, Michael D" <michael.d.kinney@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18946 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Yao, Jiewen 2015-11-25 08:51:15 +00:00 committed by jyao1
parent 0b256fb1dd
commit f45f2d4ad4
5 changed files with 113 additions and 122 deletions

View File

@ -24,7 +24,6 @@ ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
ASM_GLOBAL ASM_PFX(gSmiCr3) ASM_GLOBAL ASM_PFX(gSmiCr3)
ASM_GLOBAL ASM_PFX(gSmiStack) ASM_GLOBAL ASM_PFX(gSmiStack)
ASM_GLOBAL ASM_PFX(gSmbase) ASM_GLOBAL ASM_PFX(gSmbase)
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard)) ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr) ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
@ -148,43 +147,22 @@ L5:
# jmp _SmiHandler # instruction is not needed # jmp _SmiHandler # instruction is not needed
_SmiHandler: _SmiHandler:
cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)) movl (%esp), %ebx
jz L3
L6: pushl %ebx
call L1 movl $ASM_PFX(CpuSmmDebugEntry), %eax
L1: call *%eax
popl %ebp popl %ecx
movl $0x80000001, %eax
cpuid
btl $29, %edx # check cpuid to identify X64 or IA32
leal (0x7fc8 - (L1 - _SmiEntryPoint))(%ebp), %edi
leal 4(%edi), %esi
jnc L2
addl $4, %esi
L2:
movl (%esi), %ecx
movl (%edi), %edx
L7:
movl %ecx, %dr6
movl %edx, %dr7 # restore DR6 & DR7 before running C code
L3:
pushl (%esp)
pushl %ebx
movl $ASM_PFX(SmiRendezvous), %eax movl $ASM_PFX(SmiRendezvous), %eax
call *%eax call *%eax
popl %ecx popl %ecx
pushl %ebx
cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)) movl $ASM_PFX(CpuSmmDebugExit), %eax
jz L4 call *%eax
popl %ecx
movl %dr6, %ecx
movl %dr7, %edx
movl %ecx, (%esi)
movl %edx, (%edi)
L4:
rsm rsm

View File

@ -35,13 +35,14 @@ PROTECT_MODE_DS EQU 20h
TSS_SEGMENT EQU 40h TSS_SEGMENT EQU 40h
SmiRendezvous PROTO C SmiRendezvous PROTO C
CpuSmmDebugEntry PROTO C
CpuSmmDebugExit PROTO C
EXTERNDEF gcSmiHandlerTemplate:BYTE EXTERNDEF gcSmiHandlerTemplate:BYTE
EXTERNDEF gcSmiHandlerSize:WORD EXTERNDEF gcSmiHandlerSize:WORD
EXTERNDEF gSmiCr3:DWORD EXTERNDEF gSmiCr3:DWORD
EXTERNDEF gSmiStack:DWORD EXTERNDEF gSmiStack:DWORD
EXTERNDEF gSmbase:DWORD EXTERNDEF gSmbase:DWORD
EXTERNDEF FeaturePcdGet (PcdCpuSmmDebug):BYTE
EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE
EXTERNDEF gSmiHandlerIdtr:FWORD EXTERNDEF gSmiHandlerIdtr:FWORD
@ -151,40 +152,23 @@ gSmiCr3 DD ?
; jmp _SmiHandler ; instruction is not needed ; jmp _SmiHandler ; instruction is not needed
_SmiHandler PROC _SmiHandler PROC
cmp FeaturePcdGet (PcdCpuSmmDebug), 0 mov ebx, [esp] ; CPU Index
jz @3
call @1
@1:
pop ebp
mov eax, 80000001h
cpuid
bt edx, 29 ; check cpuid to identify X64 or IA32
lea edi, [ebp - (@1 - _SmiEntryPoint) + 7fc8h]
lea esi, [edi + 4]
jnc @2
add esi, 4
@2:
mov ecx, [esi]
mov edx, [edi]
@5:
mov dr6, ecx
mov dr7, edx ; restore DR6 & DR7 before running C code
@3:
mov ecx, [esp] ; CPU Index
push ecx push ebx
mov eax, CpuSmmDebugEntry
call eax
pop ecx
push ebx
mov eax, SmiRendezvous mov eax, SmiRendezvous
call eax call eax
pop ecx pop ecx
cmp FeaturePcdGet (PcdCpuSmmDebug), 0 push ebx
jz @4 mov eax, CpuSmmDebugExit
call eax
pop ecx
mov ecx, dr6
mov edx, dr7
mov [esi], ecx
mov [edi], edx
@4:
rsm rsm
_SmiHandler ENDP _SmiHandler ENDP

View File

@ -940,6 +940,65 @@ SmmStartupThisAp (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/**
This funciton sets DR6 & DR7 according to SMM save state, before running SMM C code.
They are useful when you want to enable hardware breakpoints in SMM without entry SMM mode.
NOTE: It might not be appreciated in runtime since it might
conflict with OS debugging facilities. Turn them off in RELEASE.
@param CpuIndex CPU Index
**/
VOID
EFIAPI
CpuSmmDebugEntry (
IN UINTN CpuIndex
)
{
SMRAM_SAVE_STATE_MAP *CpuSaveState;
if (FeaturePcdGet (PcdCpuSmmDebug)) {
CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
AsmWriteDr6 (CpuSaveState->x86._DR6);
AsmWriteDr7 (CpuSaveState->x86._DR7);
} else {
AsmWriteDr6 ((UINTN)CpuSaveState->x64._DR6);
AsmWriteDr7 ((UINTN)CpuSaveState->x64._DR7);
}
}
}
/**
This funciton restores DR6 & DR7 to SMM save state.
NOTE: It might not be appreciated in runtime since it might
conflict with OS debugging facilities. Turn them off in RELEASE.
@param CpuIndex CPU Index
**/
VOID
EFIAPI
CpuSmmDebugExit (
IN UINTN CpuIndex
)
{
SMRAM_SAVE_STATE_MAP *CpuSaveState;
if (FeaturePcdGet (PcdCpuSmmDebug)) {
CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
CpuSaveState->x86._DR7 = (UINT32)AsmReadDr7 ();
CpuSaveState->x86._DR6 = (UINT32)AsmReadDr6 ();
} else {
CpuSaveState->x64._DR7 = AsmReadDr7 ();
CpuSaveState->x64._DR6 = AsmReadDr6 ();
}
}
}
/** /**
C function for SMI entry, each processor comes here upon SMI trigger. C function for SMI entry, each processor comes here upon SMI trigger.

View File

@ -24,7 +24,6 @@ ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
ASM_GLOBAL ASM_PFX(gSmiCr3) ASM_GLOBAL ASM_PFX(gSmiCr3)
ASM_GLOBAL ASM_PFX(gSmiStack) ASM_GLOBAL ASM_PFX(gSmiStack)
ASM_GLOBAL ASM_PFX(gSmbase) ASM_GLOBAL ASM_PFX(gSmbase)
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug))
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr) ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
# #
@ -163,20 +162,7 @@ LongMode: # long mode (64-bit code) starts here
# jmp _SmiHandler ; instruction is not needed # jmp _SmiHandler ; instruction is not needed
_SmiHandler: _SmiHandler:
movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax movq (%rsp), %rbx
cmpb $0, (%rax)
jz L1
.byte 0x48, 0x8b, 0x0d # mov rcx, [rip + disp32]
.long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
.byte 0x48, 0x8b, 0x15 # mov rdx, [rip + disp32]
.long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
movq %rcx, %dr6
movq %rdx, %dr7
L1:
movabsq $ASM_PFX(SmiRendezvous), %rax
movq (%rsp), %rcx
# Save FP registers # Save FP registers
subq $0x208, %rsp subq $0x208, %rsp
@ -184,7 +170,19 @@ L1:
fxsave (%rsp) fxsave (%rsp)
addq $-0x20, %rsp addq $-0x20, %rsp
movq %rbx, %rcx
movabsq $ASM_PFX(CpuSmmDebugEntry), %rax
call *%rax call *%rax
movq %rbx, %rcx
movabsq $ASM_PFX(SmiRendezvous), %rax
call *%rax
movq %rbx, %rcx
movabsq $ASM_PFX(CpuSmmDebugExit), %rax
call *%rax
addq $0x20, %rsp addq $0x20, %rsp
# #
@ -193,17 +191,6 @@ L1:
.byte 0x48 # FXRSTOR64 .byte 0x48 # FXRSTOR64
fxrstor (%rsp) fxrstor (%rsp)
movabsq $ASM_PFX(FeaturePcdGet (PcdCpuSmmDebug)), %rax
cmpb $0, (%rax)
jz L2
movq %dr7, %rdx
movq %dr6, %rcx
.byte 0x48, 0x89, 0x15 # mov [rip + disp32], rdx
.long SSM_DR7 - (. + 4 - _SmiEntryPoint + 0x8000)
.byte 0x48, 0x89, 0x0d # mov [rip + disp32], rcx
.long SSM_DR6 - (. + 4 - _SmiEntryPoint + 0x8000)
L2:
rsm rsm
ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint

View File

@ -22,12 +22,13 @@
; Variables referenced by C code ; Variables referenced by C code
; ;
EXTERNDEF SmiRendezvous:PROC EXTERNDEF SmiRendezvous:PROC
EXTERNDEF CpuSmmDebugEntry:PROC
EXTERNDEF CpuSmmDebugExit:PROC
EXTERNDEF gcSmiHandlerTemplate:BYTE EXTERNDEF gcSmiHandlerTemplate:BYTE
EXTERNDEF gcSmiHandlerSize:WORD EXTERNDEF gcSmiHandlerSize:WORD
EXTERNDEF gSmiCr3:DWORD EXTERNDEF gSmiCr3:DWORD
EXTERNDEF gSmiStack:DWORD EXTERNDEF gSmiStack:DWORD
EXTERNDEF gSmbase:DWORD EXTERNDEF gSmbase:DWORD
EXTERNDEF FeaturePcdGet (PcdCpuSmmDebug):BYTE
EXTERNDEF gSmiHandlerIdtr:FWORD EXTERNDEF gSmiHandlerIdtr:FWORD
@ -157,26 +158,7 @@ Base:
; jmp _SmiHandler ; instruction is not needed ; jmp _SmiHandler ; instruction is not needed
_SmiHandler: _SmiHandler:
; mov rbx, [rsp] ; rbx <- CpuIndex
; The following lines restore DR6 & DR7 before running C code. They are useful
; when you want to enable hardware breakpoints in SMM.
;
; NOTE: These lines might not be appreciated in runtime since they might
; conflict with OS debugging facilities. Turn them off in RELEASE.
;
mov rax, offset FeaturePcdGet (PcdCpuSmmDebug) ;Get absolute address. Avoid RIP relative addressing
cmp byte ptr [rax], 0
jz @1
DB 48h, 8bh, 0dh ; mov rcx, [rip + disp32]
DD SSM_DR6 - ($ + 4 - _SmiEntryPoint + 8000h)
DB 48h, 8bh, 15h ; mov rdx, [rip + disp32]
DD SSM_DR7 - ($ + 4 - _SmiEntryPoint + 8000h)
mov dr6, rcx
mov dr7, rdx
@1:
mov rcx, [rsp] ; rcx <- CpuIndex
mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous
; ;
; Save FP registers ; Save FP registers
@ -186,7 +168,19 @@ _SmiHandler:
fxsave [rsp] fxsave [rsp]
add rsp, -20h add rsp, -20h
mov rcx, rbx
mov rax, CpuSmmDebugEntry
call rax call rax
mov rcx, rbx
mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous
call rax
mov rcx, rbx
mov rax, CpuSmmDebugExit
call rax
add rsp, 20h add rsp, 20h
; ;
@ -195,17 +189,6 @@ _SmiHandler:
DB 48h ; FXRSTOR64 DB 48h ; FXRSTOR64
fxrstor [rsp] fxrstor [rsp]
mov rax, offset FeaturePcdGet (PcdCpuSmmDebug) ;Get absolute address. Avoid RIP relative addressing
cmp byte ptr [rax], 0
jz @2
mov rdx, dr7
mov rcx, dr6
DB 48h, 89h, 15h ; mov [rip + disp32], rdx
DD SSM_DR7 - ($ + 4 - _SmiEntryPoint + 8000h)
DB 48h, 89h, 0dh ; mov [rip + disp32], rcx
DD SSM_DR6 - ($ + 4 - _SmiEntryPoint + 8000h)
@2:
rsm rsm
gcSmiHandlerSize DW $ - _SmiEntryPoint gcSmiHandlerSize DW $ - _SmiEntryPoint