UefiCpuPkg/MpInitLib: Simplify logic in SwitchBsp

When switch bsp, old bsp and new bsp put CR0/CR4 into stack, and put IDT
and GDT register into a structure. After they exchange their stack, they
restore these registers. This logic is now implemented by assembly code.
This patch aims to reuse (Save/Restore)VolatileRegisters function to
replace such assembly code for better code readability.

Cc: Eric Dong <eric.dong@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
This commit is contained in:
Liu, Zhiguang 2022-08-26 15:04:46 +08:00 committed by mergify[bot]
parent 76ec17526b
commit d1abb876f4
4 changed files with 56 additions and 63 deletions

View File

@ -284,15 +284,8 @@ ASM_PFX(AsmExchangeRole):
; edi contains OthersInfo pointer ; edi contains OthersInfo pointer
mov edi, [ebp + 28h] mov edi, [ebp + 28h]
;Store EFLAGS, GDTR and IDTR register to stack ;Store EFLAGS to stack
pushfd pushfd
mov eax, cr4
push eax ; push cr4 firstly
mov eax, cr0
push eax
sgdt [esi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
sidt [esi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; Store the its StackPointer ; Store the its StackPointer
mov [esi + CPU_EXCHANGE_ROLE_INFO.StackPointer],esp mov [esi + CPU_EXCHANGE_ROLE_INFO.StackPointer],esp
@ -308,13 +301,6 @@ WaitForOtherStored:
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them
; load GDTR value
lgdt [edi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
; load IDTR value
lidt [edi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; load its future StackPointer ; load its future StackPointer
mov esp, [edi + CPU_EXCHANGE_ROLE_INFO.StackPointer] mov esp, [edi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
@ -331,10 +317,6 @@ WaitForOtherLoaded:
OtherLoaded: OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
pop eax
mov cr0, eax
pop eax
mov cr4, eax
popfd popfd
popad popad

View File

@ -1,7 +1,7 @@
/** @file /** @file
CPU MP Initialize Library common functions. CPU MP Initialize Library common functions.
Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR> Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020, AMD Inc. All rights reserved.<BR> Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
@ -15,6 +15,29 @@
EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID; EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
/**
Save the volatile registers required to be restored following INIT IPI.
@param[out] VolatileRegisters Returns buffer saved the volatile resisters
**/
VOID
SaveVolatileRegisters (
OUT CPU_VOLATILE_REGISTERS *VolatileRegisters
);
/**
Restore the volatile registers following INIT IPI.
@param[in] VolatileRegisters Pointer to volatile resisters
@param[in] IsRestoreDr TRUE: Restore DRx if supported
FALSE: Do not restore DRx
**/
VOID
RestoreVolatileRegisters (
IN CPU_VOLATILE_REGISTERS *VolatileRegisters,
IN BOOLEAN IsRestoreDr
);
/** /**
The function will check if BSP Execute Disable is enabled. The function will check if BSP Execute Disable is enabled.
@ -83,7 +106,12 @@ FutureBSPProc (
CPU_MP_DATA *DataInHob; CPU_MP_DATA *DataInHob;
DataInHob = (CPU_MP_DATA *)Buffer; DataInHob = (CPU_MP_DATA *)Buffer;
//
// Save and restore volatile registers when switch BSP
//
SaveVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo); AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
RestoreVolatileRegisters (&DataInHob->APInfo.VolatileRegisters, FALSE);
} }
/** /**
@ -2233,7 +2261,12 @@ SwitchBSPWorker (
// //
WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData, TRUE); WakeUpAP (CpuMpData, FALSE, ProcessorNumber, FutureBSPProc, CpuMpData, TRUE);
//
// Save and restore volatile registers when switch BSP
//
SaveVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo); AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);
RestoreVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters, FALSE);
// //
// Set the BSP bit of MSR_IA32_APIC_BASE on new BSP // Set the BSP bit of MSR_IA32_APIC_BASE on new BSP

View File

@ -68,14 +68,31 @@ typedef struct {
UINTN Size; UINTN Size;
} MICROCODE_PATCH_INFO; } MICROCODE_PATCH_INFO;
//
// CPU volatile registers around INIT-SIPI-SIPI
//
typedef struct {
UINTN Cr0;
UINTN Cr3;
UINTN Cr4;
UINTN Dr0;
UINTN Dr1;
UINTN Dr2;
UINTN Dr3;
UINTN Dr6;
UINTN Dr7;
IA32_DESCRIPTOR Gdtr;
IA32_DESCRIPTOR Idtr;
UINT16 Tr;
} CPU_VOLATILE_REGISTERS;
// //
// CPU exchange information for switch BSP // CPU exchange information for switch BSP
// //
typedef struct { typedef struct {
UINT8 State; // offset 0 UINT8 State; // offset 0
UINTN StackPointer; // offset 4 / 8 UINTN StackPointer; // offset 4 / 8
IA32_DESCRIPTOR Gdtr; // offset 8 / 16 CPU_VOLATILE_REGISTERS VolatileRegisters; // offset 8 / 16
IA32_DESCRIPTOR Idtr; // offset 14 / 26
} CPU_EXCHANGE_ROLE_INFO; } CPU_EXCHANGE_ROLE_INFO;
// //
@ -112,24 +129,6 @@ typedef enum {
CpuStateDisabled CpuStateDisabled
} CPU_STATE; } CPU_STATE;
//
// CPU volatile registers around INIT-SIPI-SIPI
//
typedef struct {
UINTN Cr0;
UINTN Cr3;
UINTN Cr4;
UINTN Dr0;
UINTN Dr1;
UINTN Dr2;
UINTN Dr3;
UINTN Dr6;
UINTN Dr7;
IA32_DESCRIPTOR Gdtr;
IA32_DESCRIPTOR Idtr;
UINT16 Tr;
} CPU_VOLATILE_REGISTERS;
// //
// AP related data // AP related data
// //

View File

@ -482,22 +482,13 @@ ASM_PFX(AsmExchangeRole):
push r14 push r14
push r15 push r15
mov rax, cr0
push rax
mov rax, cr4
push rax
; rsi contains MyInfo pointer ; rsi contains MyInfo pointer
mov rsi, rcx mov rsi, rcx
; rdi contains OthersInfo pointer ; rdi contains OthersInfo pointer
mov rdi, rdx mov rdi, rdx
;Store EFLAGS, GDTR and IDTR regiter to stack
pushfq pushfq
sgdt [rsi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
sidt [rsi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; Store the its StackPointer ; Store the its StackPointer
mov [rsi + CPU_EXCHANGE_ROLE_INFO.StackPointer], rsp mov [rsi + CPU_EXCHANGE_ROLE_INFO.StackPointer], rsp
@ -513,12 +504,6 @@ WaitForOtherStored:
jmp WaitForOtherStored jmp WaitForOtherStored
OtherStored: OtherStored:
; Since another CPU already stored its state, load them
; load GDTR value
lgdt [rdi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
; load IDTR value
lidt [rdi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; load its future StackPointer ; load its future StackPointer
mov rsp, [rdi + CPU_EXCHANGE_ROLE_INFO.StackPointer] mov rsp, [rdi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
@ -538,12 +523,6 @@ OtherLoaded:
; since the other CPU already get the data it want, leave this procedure ; since the other CPU already get the data it want, leave this procedure
popfq popfq
pop rax
mov cr4, rax
pop rax
mov cr0, rax
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13