UefiCpuPkg/MpInitLib: Program AP stack in fixed address

Currently, MpInitLib will program AP stack in dynamic address. Each processor
will calculate its stack address by adding stack size based on the last stack
address. That means AP may have the different stack address everytime it is
wakeup by INIT-SIPI-SIPI.

When all APs have wakeup to execute AP task, each each has been assigned one
stack address. Once the timeout happened on some of APs, BSP will send INIT-
SIPI-SIPI to wake up APs. We need to re-assign stack for APs. Based on the
current implementation, we might assign one stack address used by other APs.
It will cause the unexpected stack overlapped issue.

This fix changed the stack assignment policy. We will record the stack address
assigned to AP at first time AP wakeup. When AP failed on AP task, BSP could
reassigned the same stack for it.

Getting initial APIC ID in assembly code could help AP to get saved its stack
address.

Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
This commit is contained in:
Jeff Fan 2016-11-14 11:38:25 +08:00
parent 46d4b8858f
commit 845c5be1fd
4 changed files with 119 additions and 27 deletions

View File

@ -114,7 +114,12 @@ Flat32Start: ; protected mode entry point
mov cr0, eax
SkipEnableExecuteDisable:
mov edi, esi
add edi, InitFlagLocation
cmp dword [edi], 1 ; 1 == ApInitConfig
jnz GetApicId
; AP init
mov edi, esi
add edi, LockLocation
mov eax, NotVacantFlag
@ -124,27 +129,65 @@ TestLock:
cmp eax, NotVacantFlag
jz TestLock
mov edi, esi
add edi, NumApsExecutingLocation
inc dword [edi]
mov ebx, [edi]
mov ecx, esi
add ecx, NumApsExecutingLocation
inc dword [ecx]
mov ebx, [ecx]
Releaselock:
mov eax, VacantFlag
xchg [edi], eax
ProgramStack:
mov edi, esi
add edi, StackSizeLocation
mov eax, [edi]
mov ecx, ebx
inc ecx
mul ecx ; EAX = StackSize * (CpuNumber + 1)
mov edi, esi
add edi, StackStartAddressLocation
add eax, [edi]
mov esp, eax
mov [edi], eax
jmp CProcedureInvoke
Releaselock:
mov eax, VacantFlag
mov edi, esi
add edi, LockLocation
xchg [edi], eax
GetApicId:
mov eax, 0
cpuid
cmp eax, 0bh
jnb X2Apic
; Processor is not x2APIC capable, so get 8-bit APIC ID
mov eax, 1
cpuid
shr ebx, 24
mov edx, ebx
jmp GetProcessorNumber
X2Apic:
; Processor is x2APIC capable, so get 32-bit x2APIC ID
mov eax, 0bh
xor ecx, ecx
cpuid
; edx save x2APIC ID
GetProcessorNumber:
;
; Get processor number for this AP
; Note that BSP may become an AP due to SwitchBsp()
;
xor ebx, ebx
lea eax, [esi + CpuInfoLocation]
mov edi, [eax]
GetNextProcNumber:
cmp [edi], edx ; APIC ID match?
jz ProgramStack
add edi, 16
inc ebx
jmp GetNextProcNumber
ProgramStack:
mov esp, [edi + 12]
CProcedureInvoke:
push ebp ; push BIST data at top of AP stack
xor ebp, ebp ; clear ebp for call stack trace

View File

@ -432,7 +432,8 @@ VOID
InitializeApData (
IN OUT CPU_MP_DATA *CpuMpData,
IN UINTN ProcessorNumber,
IN UINT32 BistData
IN UINT32 BistData,
IN UINTN ApTopOfStack
)
{
CPU_INFO_IN_HOB *CpuInfoInHob;
@ -441,6 +442,7 @@ InitializeApData (
CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();
CpuInfoInHob[ProcessorNumber].ApicId = GetApicId ();
CpuInfoInHob[ProcessorNumber].Health = BistData;
CpuInfoInHob[ProcessorNumber].ApTopOfStack = (UINT32) ApTopOfStack;
CpuMpData->CpuData[ProcessorNumber].Waiting = FALSE;
CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;
@ -478,6 +480,7 @@ ApWakeupFunction (
UINT32 BistData;
volatile UINT32 *ApStartupSignalBuffer;
CPU_INFO_IN_HOB *CpuInfoInHob;
UINTN ApTopOfStack;
//
// AP finished assembly code and begin to execute C code
@ -496,7 +499,8 @@ ApWakeupFunction (
//
// This is first time AP wakeup, get BIST information from AP stack
//
BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN));
ApTopOfStack = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;
BistData = *(UINT32 *) (ApTopOfStack - sizeof (UINTN));
//
// Do some AP initialize sync
//
@ -505,7 +509,7 @@ ApWakeupFunction (
// Sync BSP's Control registers to APs
//
RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
InitializeApData (CpuMpData, ProcessorNumber, BistData);
InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
} else {
//
@ -1194,7 +1198,7 @@ MpInitLibInitialize (
//
// Set BSP basic information
//
InitializeApData (CpuMpData, 0, 0);
InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer);
//
// Save assembly code information
//

View File

@ -133,6 +133,7 @@ typedef struct {
UINT32 InitialApicId;
UINT32 ApicId;
UINT32 Health;
UINT32 ApTopOfStack;
} CPU_INFO_IN_HOB;
//

View File

@ -119,6 +119,12 @@ LongModeStart:
mov es, ax
mov ss, ax
mov esi, ebx
lea edi, [esi + InitFlagLocation]
cmp qword [edi], 1 ; ApInitConfig
jnz GetApicId
; AP init
mov esi, ebx
mov edi, esi
add edi, LockLocation
@ -129,26 +135,64 @@ TestLock:
cmp rax, NotVacantFlag
jz TestLock
mov edi, esi
add edi, NumApsExecutingLocation
inc dword [edi]
mov ebx, [edi]
lea ecx, [esi + InitFlagLocation]
inc dword [ecx]
mov ebx, [ecx]
ProgramStack:
Releaselock:
mov rax, VacantFlag
xchg qword [edi], rax
; program stack
mov edi, esi
add edi, StackSizeLocation
mov rax, qword [edi]
mov eax, dword [edi]
mov ecx, ebx
inc ecx
mul ecx ; EAX = StackSize * (CpuNumber + 1)
mov edi, esi
add edi, StackStartAddressLocation
add rax, qword [edi]
mov rsp, rax
mov qword [edi], rax
jmp CProcedureInvoke
Releaselock:
mov rax, VacantFlag
mov edi, esi
add edi, LockLocation
xchg qword [edi], rax
GetApicId:
mov eax, 0
cpuid
cmp eax, 0bh
jnb X2Apic
; Processor is not x2APIC capable, so get 8-bit APIC ID
mov eax, 1
cpuid
shr ebx, 24
mov edx, ebx
jmp GetProcessorNumber
X2Apic:
; Processor is x2APIC capable, so get 32-bit x2APIC ID
mov eax, 0bh
xor ecx, ecx
cpuid
; edx save x2APIC ID
GetProcessorNumber:
;
; Get processor number for this AP
; Note that BSP may become an AP due to SwitchBsp()
;
xor ebx, ebx
lea eax, [esi + CpuInfoLocation]
mov edi, [eax]
GetNextProcNumber:
cmp dword [edi], edx ; APIC ID match?
jz ProgramStack
add edi, 16
inc ebx
jmp GetNextProcNumber
ProgramStack:
xor rsp, rsp
mov esp, dword [edi + 12]
CProcedureInvoke:
push rbp ; Push BIST data at top of AP stack