mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-28 16:14:04 +02:00
UefiCpuPkg/CpuMpPei: Implementation of PeiSwitchBSP ()
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18010 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
d11bbfff1f
commit
3798f35133
@ -58,6 +58,16 @@ typedef struct {
|
|||||||
UINTN RendezvousFunnelSize;
|
UINTN RendezvousFunnelSize;
|
||||||
} MP_ASSEMBLY_ADDRESS_MAP;
|
} MP_ASSEMBLY_ADDRESS_MAP;
|
||||||
|
|
||||||
|
//
|
||||||
|
// CPU exchange information for switch BSP
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINT8 State; // offset 0
|
||||||
|
UINTN StackPointer; // offset 4 / 8
|
||||||
|
IA32_DESCRIPTOR Gdtr; // offset 8 / 16
|
||||||
|
IA32_DESCRIPTOR Idtr; // offset 14 / 26
|
||||||
|
} CPU_EXCHANGE_ROLE_INFO;
|
||||||
|
|
||||||
typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA;
|
typedef struct _PEI_CPU_MP_DATA PEI_CPU_MP_DATA;
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
@ -124,6 +134,8 @@ struct _PEI_CPU_MP_DATA {
|
|||||||
UINTN ApFunctionArgument;
|
UINTN ApFunctionArgument;
|
||||||
volatile UINT32 FinishedCount;
|
volatile UINT32 FinishedCount;
|
||||||
BOOLEAN InitFlag;
|
BOOLEAN InitFlag;
|
||||||
|
CPU_EXCHANGE_ROLE_INFO BSPInfo;
|
||||||
|
CPU_EXCHANGE_ROLE_INFO APInfo;
|
||||||
MTRR_SETTINGS MtrrTable;
|
MTRR_SETTINGS MtrrTable;
|
||||||
PEI_CPU_DATA *CpuData;
|
PEI_CPU_DATA *CpuData;
|
||||||
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
|
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
|
||||||
|
@ -24,6 +24,10 @@ PROTECT_MODE_DS equ 18h
|
|||||||
VacantFlag equ 00h
|
VacantFlag equ 00h
|
||||||
NotVacantFlag equ 0ffh
|
NotVacantFlag equ 0ffh
|
||||||
|
|
||||||
|
CPU_SWITCH_STATE_IDLE equ 0
|
||||||
|
CPU_SWITCH_STATE_STORED equ 1
|
||||||
|
CPU_SWITCH_STATE_LOADED equ 2
|
||||||
|
|
||||||
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
|
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
|
||||||
StackStartAddressLocation equ LockLocation + 04h
|
StackStartAddressLocation equ LockLocation + 04h
|
||||||
StackSizeLocation equ LockLocation + 08h
|
StackSizeLocation equ LockLocation + 08h
|
||||||
|
@ -161,6 +161,85 @@ AsmGetAddressMap PROC near C PUBLIC
|
|||||||
ret
|
ret
|
||||||
AsmGetAddressMap ENDP
|
AsmGetAddressMap ENDP
|
||||||
|
|
||||||
|
PAUSE32 MACRO
|
||||||
|
DB 0F3h
|
||||||
|
DB 090h
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
|
||||||
|
;about to become an AP. It switches it'stack with the current AP.
|
||||||
|
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
AsmExchangeRole PROC near C PUBLIC
|
||||||
|
; DO NOT call other functions in this function, since 2 CPU may use 1 stack
|
||||||
|
; at the same time. If 1 CPU try to call a function, stack will be corrupted.
|
||||||
|
pushad
|
||||||
|
mov ebp,esp
|
||||||
|
|
||||||
|
; esi contains MyInfo pointer
|
||||||
|
mov esi, dword ptr [ebp+24h]
|
||||||
|
|
||||||
|
; edi contains OthersInfo pointer
|
||||||
|
mov edi, dword ptr [ebp+28h]
|
||||||
|
|
||||||
|
;Store EFLAGS, GDTR and IDTR register to stack
|
||||||
|
pushfd
|
||||||
|
mov eax, cr4
|
||||||
|
push eax ; push cr4 firstly
|
||||||
|
mov eax, cr0
|
||||||
|
push eax
|
||||||
|
|
||||||
|
sgdt fword ptr [esi+8]
|
||||||
|
sidt fword ptr [esi+14]
|
||||||
|
|
||||||
|
; Store the its StackPointer
|
||||||
|
mov dword ptr [esi+4],esp
|
||||||
|
|
||||||
|
; update its switch state to STORED
|
||||||
|
mov byte ptr [esi], CPU_SWITCH_STATE_STORED
|
||||||
|
|
||||||
|
WaitForOtherStored:
|
||||||
|
; wait until the other CPU finish storing its state
|
||||||
|
cmp byte ptr [edi], CPU_SWITCH_STATE_STORED
|
||||||
|
jz OtherStored
|
||||||
|
PAUSE32
|
||||||
|
jmp WaitForOtherStored
|
||||||
|
|
||||||
|
OtherStored:
|
||||||
|
; Since another CPU already stored its state, load them
|
||||||
|
; load GDTR value
|
||||||
|
lgdt fword ptr [edi+8]
|
||||||
|
|
||||||
|
; load IDTR value
|
||||||
|
lidt fword ptr [edi+14]
|
||||||
|
|
||||||
|
; load its future StackPointer
|
||||||
|
mov esp, dword ptr [edi+4]
|
||||||
|
|
||||||
|
; update the other CPU's switch state to LOADED
|
||||||
|
mov byte ptr [edi], CPU_SWITCH_STATE_LOADED
|
||||||
|
|
||||||
|
WaitForOtherLoaded:
|
||||||
|
; wait until the other CPU finish loading new state,
|
||||||
|
; otherwise the data in stack may corrupt
|
||||||
|
cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED
|
||||||
|
jz OtherLoaded
|
||||||
|
PAUSE32
|
||||||
|
jmp WaitForOtherLoaded
|
||||||
|
|
||||||
|
OtherLoaded:
|
||||||
|
; since the other CPU already get the data it want, leave this procedure
|
||||||
|
pop eax
|
||||||
|
mov cr0, eax
|
||||||
|
pop eax
|
||||||
|
mov cr4, eax
|
||||||
|
popfd
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
AsmExchangeRole ENDP
|
||||||
|
|
||||||
AsmInitializeGdt PROC near C PUBLIC
|
AsmInitializeGdt PROC near C PUBLIC
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -149,6 +149,80 @@ ASM_PFX(AsmGetAddressMap):
|
|||||||
popad
|
popad
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
|
||||||
|
;about to become an AP. It switches it'stack with the current AP.
|
||||||
|
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
global ASM_PFX(AsmExchangeRole)
|
||||||
|
ASM_PFX(AsmExchangeRole):
|
||||||
|
; DO NOT call other functions in this function, since 2 CPU may use 1 stack
|
||||||
|
; at the same time. If 1 CPU try to call a function, stack will be corrupted.
|
||||||
|
pushad
|
||||||
|
mov ebp,esp
|
||||||
|
|
||||||
|
; esi contains MyInfo pointer
|
||||||
|
mov esi, [ebp + 24h]
|
||||||
|
|
||||||
|
; edi contains OthersInfo pointer
|
||||||
|
mov edi, [ebp + 28h]
|
||||||
|
|
||||||
|
;Store EFLAGS, GDTR and IDTR register to stack
|
||||||
|
pushfd
|
||||||
|
mov eax, cr4
|
||||||
|
push eax ; push cr4 firstly
|
||||||
|
mov eax, cr0
|
||||||
|
push eax
|
||||||
|
|
||||||
|
sgdt [esi + 8]
|
||||||
|
sidt [esi + 14]
|
||||||
|
|
||||||
|
; Store the its StackPointer
|
||||||
|
mov [esi + 4],esp
|
||||||
|
|
||||||
|
; update its switch state to STORED
|
||||||
|
mov byte [esi], CPU_SWITCH_STATE_STORED
|
||||||
|
|
||||||
|
WaitForOtherStored:
|
||||||
|
; wait until the other CPU finish storing its state
|
||||||
|
cmp byte [edi], CPU_SWITCH_STATE_STORED
|
||||||
|
jz OtherStored
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherStored
|
||||||
|
|
||||||
|
OtherStored:
|
||||||
|
; Since another CPU already stored its state, load them
|
||||||
|
; load GDTR value
|
||||||
|
lgdt [edi + 8]
|
||||||
|
|
||||||
|
; load IDTR value
|
||||||
|
lidt [edi + 14]
|
||||||
|
|
||||||
|
; load its future StackPointer
|
||||||
|
mov esp, [edi + 4]
|
||||||
|
|
||||||
|
; update the other CPU's switch state to LOADED
|
||||||
|
mov byte [edi], CPU_SWITCH_STATE_LOADED
|
||||||
|
|
||||||
|
WaitForOtherLoaded:
|
||||||
|
; wait until the other CPU finish loading new state,
|
||||||
|
; otherwise the data in stack may corrupt
|
||||||
|
cmp byte [esi], CPU_SWITCH_STATE_LOADED
|
||||||
|
jz OtherLoaded
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherLoaded
|
||||||
|
|
||||||
|
OtherLoaded:
|
||||||
|
; since the other CPU already get the data it want, leave this procedure
|
||||||
|
pop eax
|
||||||
|
mov cr0, eax
|
||||||
|
pop eax
|
||||||
|
mov cr4, eax
|
||||||
|
popfd
|
||||||
|
|
||||||
|
popad
|
||||||
|
ret
|
||||||
|
|
||||||
global ASM_PFX(AsmInitializeGdt)
|
global ASM_PFX(AsmInitializeGdt)
|
||||||
ASM_PFX(AsmInitializeGdt):
|
ASM_PFX(AsmInitializeGdt):
|
||||||
push ebp
|
push ebp
|
||||||
|
@ -153,6 +153,25 @@ GetProcessorNumber (
|
|||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Worker function for SwitchBSP().
|
||||||
|
|
||||||
|
Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.
|
||||||
|
|
||||||
|
@param Buffer Pointer to CPU MP Data
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
FutureBSPProc (
|
||||||
|
IN VOID *Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEI_CPU_MP_DATA *DataInHob;
|
||||||
|
|
||||||
|
DataInHob = (PEI_CPU_MP_DATA *) Buffer;
|
||||||
|
AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This service retrieves the number of logical processor in the platform
|
This service retrieves the number of logical processor in the platform
|
||||||
and the number of those logical processors that are enabled on this boot.
|
and the number of those logical processors that are enabled on this boot.
|
||||||
@ -617,6 +636,118 @@ PeiStartupThisAP (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This service switches the requested AP to be the BSP from that point onward.
|
||||||
|
This service changes the BSP for all purposes. This call can only be performed
|
||||||
|
by the current BSP.
|
||||||
|
|
||||||
|
This service switches the requested AP to be the BSP from that point onward.
|
||||||
|
This service changes the BSP for all purposes. The new BSP can take over the
|
||||||
|
execution of the old BSP and continue seamlessly from where the old one left
|
||||||
|
off.
|
||||||
|
|
||||||
|
If the BSP cannot be switched prior to the return from this service, then
|
||||||
|
EFI_UNSUPPORTED must be returned.
|
||||||
|
|
||||||
|
@param[in] PeiServices An indirect pointer to the PEI Services Table
|
||||||
|
published by the PEI Foundation.
|
||||||
|
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
|
||||||
|
@param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
|
||||||
|
total number of logical processors minus 1. The total
|
||||||
|
number of logical processors can be retrieved by
|
||||||
|
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
|
||||||
|
@param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
|
||||||
|
AP. Otherwise, it will be disabled.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS BSP successfully switched.
|
||||||
|
@retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
|
||||||
|
service returning.
|
||||||
|
@retval EFI_UNSUPPORTED Switching the BSP is not supported.
|
||||||
|
@retval EFI_SUCCESS The calling processor is an AP.
|
||||||
|
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||||
|
ProcessorNumber does not exist.
|
||||||
|
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
|
||||||
|
AP.
|
||||||
|
@retval EFI_NOT_READY The specified AP is busy.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
PeiSwitchBSP (
|
||||||
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_MP_SERVICES_PPI *This,
|
||||||
|
IN UINTN ProcessorNumber,
|
||||||
|
IN BOOLEAN EnableOldBSP
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PEI_CPU_MP_DATA *PeiCpuMpData;
|
||||||
|
UINTN CallerNumber;
|
||||||
|
MSR_IA32_APIC_BASE ApicBaseMsr;
|
||||||
|
|
||||||
|
PeiCpuMpData = GetMpHobData ();
|
||||||
|
if (PeiCpuMpData == NULL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check whether caller processor is BSP
|
||||||
|
//
|
||||||
|
PeiWhoAmI (PeiServices, This, &CallerNumber);
|
||||||
|
if (CallerNumber != PeiCpuMpData->BspNumber) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProcessorNumber >= PeiCpuMpData->CpuCount) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check whether specified AP is disabled
|
||||||
|
//
|
||||||
|
if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateDisabled) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check whether ProcessorNumber specifies the current BSP
|
||||||
|
//
|
||||||
|
if (ProcessorNumber == PeiCpuMpData->BspNumber) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check whether specified AP is busy
|
||||||
|
//
|
||||||
|
if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateBusy) {
|
||||||
|
return EFI_NOT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Clear the BSP bit of MSR_IA32_APIC_BASE
|
||||||
|
//
|
||||||
|
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
|
||||||
|
ApicBaseMsr.Bits.Bsp = 0;
|
||||||
|
AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
|
||||||
|
|
||||||
|
PeiCpuMpData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
|
||||||
|
PeiCpuMpData->APInfo.State = CPU_SWITCH_STATE_IDLE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Need to wakeUp AP (future BSP).
|
||||||
|
//
|
||||||
|
WakeUpAP (PeiCpuMpData, FALSE, PeiCpuMpData->CpuData[ProcessorNumber].ApicId, FutureBSPProc, PeiCpuMpData);
|
||||||
|
|
||||||
|
AsmExchangeRole (&PeiCpuMpData->BSPInfo, &PeiCpuMpData->APInfo);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
|
||||||
|
//
|
||||||
|
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE_ADDRESS);
|
||||||
|
ApicBaseMsr.Bits.Bsp = 1;
|
||||||
|
AsmWriteMsr64 (MSR_IA32_APIC_BASE_ADDRESS, ApicBaseMsr.Uint64);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This return the handle number for the calling processor. This service may be
|
This return the handle number for the calling processor. This service may be
|
||||||
|
@ -17,9 +17,30 @@
|
|||||||
|
|
||||||
#include "CpuMpPei.h"
|
#include "CpuMpPei.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// The MP data for switch BSP
|
||||||
|
//
|
||||||
|
#define CPU_SWITCH_STATE_IDLE 0
|
||||||
|
#define CPU_SWITCH_STATE_STORED 1
|
||||||
|
#define CPU_SWITCH_STATE_LOADED 2
|
||||||
|
|
||||||
#define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds
|
#define CPU_CHECK_AP_INTERVAL 0x100 // 100 microseconds
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is called by both the BSP and the AP which is to become the BSP to
|
||||||
|
Exchange execution context including stack between them. After return from this
|
||||||
|
function, the BSP becomes AP and the AP becomes the BSP.
|
||||||
|
|
||||||
|
@param MyInfo Pointer to buffer holding the exchanging information for the executing processor.
|
||||||
|
@param OthersInfo Pointer to buffer holding the exchanging information for the peer.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
AsmExchangeRole (
|
||||||
|
IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
|
||||||
|
IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This service retrieves the number of logical processor in the platform
|
This service retrieves the number of logical processor in the platform
|
||||||
and the number of those logical processors that are enabled on this boot.
|
and the number of those logical processors that are enabled on this boot.
|
||||||
@ -229,6 +250,49 @@ PeiStartupThisAP (
|
|||||||
IN VOID *ProcedureArgument OPTIONAL
|
IN VOID *ProcedureArgument OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This service switches the requested AP to be the BSP from that point onward.
|
||||||
|
This service changes the BSP for all purposes. This call can only be performed
|
||||||
|
by the current BSP.
|
||||||
|
|
||||||
|
This service switches the requested AP to be the BSP from that point onward.
|
||||||
|
This service changes the BSP for all purposes. The new BSP can take over the
|
||||||
|
execution of the old BSP and continue seamlessly from where the old one left
|
||||||
|
off.
|
||||||
|
|
||||||
|
If the BSP cannot be switched prior to the return from this service, then
|
||||||
|
EFI_UNSUPPORTED must be returned.
|
||||||
|
|
||||||
|
@param[in] PeiServices An indirect pointer to the PEI Services Table
|
||||||
|
published by the PEI Foundation.
|
||||||
|
@param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
|
||||||
|
@param[in] ProcessorNumber The handle number of the AP. The range is from 0 to the
|
||||||
|
total number of logical processors minus 1. The total
|
||||||
|
number of logical processors can be retrieved by
|
||||||
|
EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
|
||||||
|
@param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an enabled
|
||||||
|
AP. Otherwise, it will be disabled.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS BSP successfully switched.
|
||||||
|
@retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to this
|
||||||
|
service returning.
|
||||||
|
@retval EFI_UNSUPPORTED Switching the BSP is not supported.
|
||||||
|
@retval EFI_SUCCESS The calling processor is an AP.
|
||||||
|
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||||
|
ProcessorNumber does not exist.
|
||||||
|
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or a disabled
|
||||||
|
AP.
|
||||||
|
@retval EFI_NOT_READY The specified AP is busy.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
PeiSwitchBSP (
|
||||||
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PEI_MP_SERVICES_PPI *This,
|
||||||
|
IN UINTN ProcessorNumber,
|
||||||
|
IN BOOLEAN EnableOldBSP
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This return the handle number for the calling processor. This service may be
|
This return the handle number for the calling processor. This service may be
|
||||||
|
@ -26,6 +26,9 @@ LONG_MODE_DS equ 30h
|
|||||||
VacantFlag equ 00h
|
VacantFlag equ 00h
|
||||||
NotVacantFlag equ 0ffh
|
NotVacantFlag equ 0ffh
|
||||||
|
|
||||||
|
CPU_SWITCH_STATE_IDLE equ 0
|
||||||
|
CPU_SWITCH_STATE_STORED equ 1
|
||||||
|
CPU_SWITCH_STATE_LOADED equ 2
|
||||||
|
|
||||||
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
|
LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
|
||||||
StackStartAddressLocation equ LockLocation + 08h
|
StackStartAddressLocation equ LockLocation + 08h
|
||||||
|
@ -193,6 +193,112 @@ AsmGetAddressMap PROC
|
|||||||
ret
|
ret
|
||||||
AsmGetAddressMap ENDP
|
AsmGetAddressMap ENDP
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
|
||||||
|
;about to become an AP. It switches it'stack with the current AP.
|
||||||
|
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
AsmExchangeRole PROC
|
||||||
|
; DO NOT call other functions in this function, since 2 CPU may use 1 stack
|
||||||
|
; at the same time. If 1 CPU try to call a function, stack will be corrupted.
|
||||||
|
|
||||||
|
push rax
|
||||||
|
push rbx
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rbp
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11
|
||||||
|
push r12
|
||||||
|
push r13
|
||||||
|
push r14
|
||||||
|
push r15
|
||||||
|
|
||||||
|
mov rax, cr0
|
||||||
|
push rax
|
||||||
|
|
||||||
|
mov rax, cr4
|
||||||
|
push rax
|
||||||
|
|
||||||
|
; rsi contains MyInfo pointer
|
||||||
|
mov rsi, rcx
|
||||||
|
|
||||||
|
; rdi contains OthersInfo pointer
|
||||||
|
mov rdi, rdx
|
||||||
|
|
||||||
|
;Store EFLAGS, GDTR and IDTR regiter to stack
|
||||||
|
pushfq
|
||||||
|
sgdt fword ptr [rsi + 16]
|
||||||
|
sidt fword ptr [rsi + 26]
|
||||||
|
|
||||||
|
; Store the its StackPointer
|
||||||
|
mov qword ptr [rsi + 8], rsp
|
||||||
|
|
||||||
|
; update its switch state to STORED
|
||||||
|
mov byte ptr [rsi], CPU_SWITCH_STATE_STORED
|
||||||
|
|
||||||
|
WaitForOtherStored:
|
||||||
|
; wait until the other CPU finish storing its state
|
||||||
|
cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED
|
||||||
|
jz OtherStored
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherStored
|
||||||
|
|
||||||
|
OtherStored:
|
||||||
|
; Since another CPU already stored its state, load them
|
||||||
|
; load GDTR value
|
||||||
|
lgdt fword ptr [rdi + 16]
|
||||||
|
|
||||||
|
; load IDTR value
|
||||||
|
lidt fword ptr [rdi + 26]
|
||||||
|
|
||||||
|
; load its future StackPointer
|
||||||
|
mov rsp, qword ptr [rdi + 8]
|
||||||
|
|
||||||
|
; update the other CPU's switch state to LOADED
|
||||||
|
mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED
|
||||||
|
|
||||||
|
WaitForOtherLoaded:
|
||||||
|
; wait until the other CPU finish loading new state,
|
||||||
|
; otherwise the data in stack may corrupt
|
||||||
|
cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED
|
||||||
|
jz OtherLoaded
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherLoaded
|
||||||
|
|
||||||
|
OtherLoaded:
|
||||||
|
; since the other CPU already get the data it want, leave this procedure
|
||||||
|
popfq
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
mov cr4, rax
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
mov cr0, rax
|
||||||
|
|
||||||
|
pop r15
|
||||||
|
pop r14
|
||||||
|
pop r13
|
||||||
|
pop r12
|
||||||
|
pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
|
||||||
|
ret
|
||||||
|
AsmExchangeRole ENDP
|
||||||
|
|
||||||
AsmInitializeGdt PROC
|
AsmInitializeGdt PROC
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
|
@ -187,6 +187,112 @@ ASM_PFX(AsmGetAddressMap):
|
|||||||
mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
|
||||||
|
;about to become an AP. It switches it'stack with the current AP.
|
||||||
|
;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
|
||||||
|
;-------------------------------------------------------------------------------------
|
||||||
|
global ASM_PFX(AsmExchangeRole)
|
||||||
|
ASM_PFX(AsmExchangeRole):
|
||||||
|
; DO NOT call other functions in this function, since 2 CPU may use 1 stack
|
||||||
|
; at the same time. If 1 CPU try to call a function, stack will be corrupted.
|
||||||
|
|
||||||
|
push rax
|
||||||
|
push rbx
|
||||||
|
push rcx
|
||||||
|
push rdx
|
||||||
|
push rsi
|
||||||
|
push rdi
|
||||||
|
push rbp
|
||||||
|
push r8
|
||||||
|
push r9
|
||||||
|
push r10
|
||||||
|
push r11
|
||||||
|
push r12
|
||||||
|
push r13
|
||||||
|
push r14
|
||||||
|
push r15
|
||||||
|
|
||||||
|
mov rax, cr0
|
||||||
|
push rax
|
||||||
|
|
||||||
|
mov rax, cr4
|
||||||
|
push rax
|
||||||
|
|
||||||
|
; rsi contains MyInfo pointer
|
||||||
|
mov rsi, rcx
|
||||||
|
|
||||||
|
; rdi contains OthersInfo pointer
|
||||||
|
mov rdi, rdx
|
||||||
|
|
||||||
|
;Store EFLAGS, GDTR and IDTR regiter to stack
|
||||||
|
pushfq
|
||||||
|
sgdt [rsi + 16]
|
||||||
|
sidt [rsi + 26]
|
||||||
|
|
||||||
|
; Store the its StackPointer
|
||||||
|
mov [rsi + 8], rsp
|
||||||
|
|
||||||
|
; update its switch state to STORED
|
||||||
|
mov byte [rsi], CPU_SWITCH_STATE_STORED
|
||||||
|
|
||||||
|
WaitForOtherStored:
|
||||||
|
; wait until the other CPU finish storing its state
|
||||||
|
cmp byte [rdi], CPU_SWITCH_STATE_STORED
|
||||||
|
jz OtherStored
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherStored
|
||||||
|
|
||||||
|
OtherStored:
|
||||||
|
; Since another CPU already stored its state, load them
|
||||||
|
; load GDTR value
|
||||||
|
lgdt [rdi + 16]
|
||||||
|
|
||||||
|
; load IDTR value
|
||||||
|
lidt [rdi + 26]
|
||||||
|
|
||||||
|
; load its future StackPointer
|
||||||
|
mov rsp, [rdi + 8]
|
||||||
|
|
||||||
|
; update the other CPU's switch state to LOADED
|
||||||
|
mov byte [rdi], CPU_SWITCH_STATE_LOADED
|
||||||
|
|
||||||
|
WaitForOtherLoaded:
|
||||||
|
; wait until the other CPU finish loading new state,
|
||||||
|
; otherwise the data in stack may corrupt
|
||||||
|
cmp byte [rsi], CPU_SWITCH_STATE_LOADED
|
||||||
|
jz OtherLoaded
|
||||||
|
pause
|
||||||
|
jmp WaitForOtherLoaded
|
||||||
|
|
||||||
|
OtherLoaded:
|
||||||
|
; since the other CPU already get the data it want, leave this procedure
|
||||||
|
popfq
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
mov cr4, rax
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
mov cr0, rax
|
||||||
|
|
||||||
|
pop r15
|
||||||
|
pop r14
|
||||||
|
pop r13
|
||||||
|
pop r12
|
||||||
|
pop r11
|
||||||
|
pop r10
|
||||||
|
pop r9
|
||||||
|
pop r8
|
||||||
|
pop rbp
|
||||||
|
pop rdi
|
||||||
|
pop rsi
|
||||||
|
pop rdx
|
||||||
|
pop rcx
|
||||||
|
pop rbx
|
||||||
|
pop rax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
global ASM_PFX(AsmInitializeGdt)
|
global ASM_PFX(AsmInitializeGdt)
|
||||||
ASM_PFX(AsmInitializeGdt):
|
ASM_PFX(AsmInitializeGdt):
|
||||||
push rbp
|
push rbp
|
||||||
|
Loading…
x
Reference in New Issue
Block a user