UefiCpuPkg/MpInitLib: support 64-bit AP stack addresses
authorLaszlo Ersek <lersek@redhat.com>
Wed, 16 Nov 2016 22:31:11 +0000 (23:31 +0100)
committerLaszlo Ersek <lersek@redhat.com>
Thu, 17 Nov 2016 09:58:18 +0000 (10:58 +0100)
The cached "CPU_INFO_IN_HOB.ApTopOfStack" field currently has type UINT32.
This is not ideal because the AP stacks are located within
"CpuMpData->Buffer", which is allocated with a plain AllocatePages() call
in MpInitLibInitialize():

  platform  CpuMpPei included  PEI RAM > 4GB  result
  --------  -----------------  -------------  ------
  Ia32      *                  n/a            good
  Ia32X64   no                 n/a            BAD
  Ia32X64   yes                n/a            good
  X64       no                 *              BAD
  X64       yes                no             good
  X64       yes                yes            BAD

- If we are on an Ia32X64 or X64 platform that does not include CpuMpPei,
  then CpuDxe cannot reuse the CPU_INFO_IN_HOB structures preallocated by
  CpuMpPei (through the CpuInitMpLib GUID HOB), and then AllocatePages()
  -- invoked first in 64-bit DXE -- could return an address outside of
  32-bit address space.

- If we are on an X64 platform where the permanent PEI RAM extends above
  the 32-bit address space, then the same issue can surface even if
  CpuMpPei is included: even the original allocation of the
  CPU_INFO_IN_HOB structures, by CpuMpPei, could be satisfied from above
  4GB.

The original "AP init" branch in "X64/MpFuncs.nasm" correctly considers a
64-bit stack start: the "MP_CPU_EXCHANGE_INFO.StackStart" field has type
UINTN, and the code uses QWORD addition and movement to set RSP from it.

Adapt the "GetApicId" branch of "X64/MpFuncs.nasm":

- change the type of "CPU_INFO_IN_HOB.ApTopOfStack" to UINT64,

- remove the explicit truncation to UINT32 in InitializeApData(),

- update the "GetNextProcNumber" iteration size to the new size of
  "CPU_INFO_IN_HOB",

- set RSP with a QWORD movement from "CPU_INFO_IN_HOB.ApTopOfStack".

Because the same CPU_INFO_IN_HOB structure is used by "Ia32/MpFuncs.nasm",
we have to update the "GetNextProcNumber" iteration size there as well.
The ESP setting can be preserved as a DWORD movement from the original
offset (decimal 12), since our integers are little endian.

Cc: Jeff Fan <jeff.fan@intel.com>
Fixes: 845c5be1fd9bf7edfac4a103dfab70829686978f
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/Library/MpInitLib/MpLib.c
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm

index 4bfa084c85a91457a1e60bc5cb5be217ca6fb3a7..64e51d87ae2462155ec4e34a2c4d69bb37345381 100644 (file)
@@ -181,7 +181,7 @@ GetProcessorNumber:
 GetNextProcNumber:\r
     cmp         [edi], edx                       ; APIC ID match?\r
     jz          ProgramStack\r
-    add         edi, 16\r
+    add         edi, 20\r
     inc         ebx\r
     jmp         GetNextProcNumber    \r
 \r
index 3c2e6d6b89d98ecc09901a48c4757db3646acd46..15dbfa1e7d6c7f5e9d85d88e0030c38ea65f4a40 100644 (file)
@@ -433,7 +433,7 @@ InitializeApData (
   IN OUT CPU_MP_DATA      *CpuMpData,\r
   IN     UINTN            ProcessorNumber,\r
   IN     UINT32           BistData,\r
-  IN     UINT           ApTopOfStack\r
+  IN     UINT64           ApTopOfStack\r
   )\r
 {\r
   CPU_INFO_IN_HOB          *CpuInfoInHob;\r
@@ -442,7 +442,7 @@ InitializeApData (
   CpuInfoInHob[ProcessorNumber].InitialApicId = GetInitialApicId ();\r
   CpuInfoInHob[ProcessorNumber].ApicId        = GetApicId ();\r
   CpuInfoInHob[ProcessorNumber].Health        = BistData;\r
-  CpuInfoInHob[ProcessorNumber].ApTopOfStack  = (UINT32) ApTopOfStack;\r
+  CpuInfoInHob[ProcessorNumber].ApTopOfStack  = ApTopOfStack;\r
 \r
   CpuMpData->CpuData[ProcessorNumber].Waiting    = FALSE;\r
   CpuMpData->CpuData[ProcessorNumber].CpuHealthy = (BistData == 0) ? TRUE : FALSE;\r
@@ -480,7 +480,7 @@ ApWakeupFunction (
   UINT32                     BistData;\r
   volatile UINT32            *ApStartupSignalBuffer;\r
   CPU_INFO_IN_HOB            *CpuInfoInHob;\r
-  UINT                     ApTopOfStack;\r
+  UINT64                     ApTopOfStack;\r
 \r
   //\r
   // AP finished assembly code and begin to execute C code\r
@@ -500,7 +500,7 @@ ApWakeupFunction (
       // This is first time AP wakeup, get BIST information from AP stack\r
       //\r
       ApTopOfStack  = CpuMpData->Buffer + (ProcessorNumber + 1) * CpuMpData->CpuApStackSize;\r
-      BistData = *(UINT32 *) (ApTopOfStack - sizeof (UINTN));\r
+      BistData = *(UINT32 *) ((UINTN) ApTopOfStack - sizeof (UINTN));\r
       //\r
       // Do some AP initialize sync\r
       //\r
index 0ac777a099b13ee179053e848f056579a70f7bb9..f73a469ae84f5831fb2d1931a3a83412eb149f16 100644 (file)
@@ -129,12 +129,14 @@ typedef struct {
 // we need to make sure the each fields offset same in different\r
 // architecture.\r
 //\r
+#pragma pack (1)\r
 typedef struct {\r
   UINT32                         InitialApicId;\r
   UINT32                         ApicId;\r
   UINT32                         Health;\r
-  UINT32                         ApTopOfStack;\r
+  UINT64                         ApTopOfStack;\r
 } CPU_INFO_IN_HOB;\r
+#pragma pack ()\r
 \r
 //\r
 // AP reset code information including code address and size,\r
index 138b97312b1d02d2e549f7065087b2c561207555..aaabb50c54684493e1b5f9c2b4e98225f2c19efe 100644 (file)
@@ -185,13 +185,12 @@ GetProcessorNumber:
 GetNextProcNumber:\r
     cmp         dword [edi], edx                      ; APIC ID match?\r
     jz          ProgramStack\r
-    add         edi, 16\r
+    add         edi, 20\r
     inc         ebx\r
     jmp         GetNextProcNumber    \r
 \r
 ProgramStack:\r
-    xor         rsp, rsp\r
-    mov         esp, dword [edi + 12]\r
+    mov         rsp, qword [edi + 12]\r
 \r
 CProcedureInvoke:\r
     push       rbp               ; Push BIST data at top of AP stack\r