]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/IntelTdx: Add Sec to bring up both Legacy and Tdx guest
authorMin Xu <min.m.xu@intel.com>
Sat, 18 Dec 2021 13:36:08 +0000 (21:36 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sat, 2 Apr 2022 10:09:47 +0000 (10:09 +0000)
RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

OvmfPkg/IntelTdx/Sec is a simplied version of OvmfPkg/Sec. There
are below differences between these 2 Sec
 - IntelTdx/Sec only supports Legacy guest and Tdx guest in X64.
 - IntelTdx/Sec calls PeilessStartup () to jump from SEC to DXE directly.
 - IntelTdx/Sec uses MemoryAllocationLib / HobLib / PrePiLib in
   EmbeddedPkg.

Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
OvmfPkg/IntelTdx/Sec/SecMain.c [new file with mode: 0644]
OvmfPkg/IntelTdx/Sec/SecMain.inf [new file with mode: 0644]
OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm [new file with mode: 0644]

diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.c b/OvmfPkg/IntelTdx/Sec/SecMain.c
new file mode 100644 (file)
index 0000000..26d56be
--- /dev/null
@@ -0,0 +1,198 @@
+/** @file\r
+  Main SEC phase code.  Transitions to PEI.\r
+\r
+  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+  Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiCpuLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/LocalApicLib.h>\r
+#include <Library/CpuExceptionHandlerLib.h>\r
+#include <IndustryStandard/Tdx.h>\r
+#include <Library/PlatformInitLib.h>\r
+\r
+#include <Library/PeilessStartupLib.h>\r
+\r
+#define SEC_IDT_ENTRY_COUNT  34\r
+\r
+typedef struct _SEC_IDT_TABLE {\r
+  EFI_PEI_SERVICES            *PeiService;\r
+  IA32_IDT_GATE_DESCRIPTOR    IdtTable[SEC_IDT_ENTRY_COUNT];\r
+} SEC_IDT_TABLE;\r
+\r
+//\r
+// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
+//\r
+IA32_IDT_GATE_DESCRIPTOR  mIdtEntryTemplate = {\r
+  {                                      // Bits\r
+    0xffe4,                              // OffsetLow\r
+    0x10,                                // Selector\r
+    0x0,                                 // Reserved_0\r
+    IA32_IDT_GATE_TYPE_INTERRUPT_32,     // GateType\r
+    0xffff                               // OffsetHigh\r
+  }\r
+};\r
+\r
+VOID\r
+EFIAPI\r
+SecCoreStartupWithStack (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER  *BootFv,\r
+  IN VOID                        *TopOfCurrentStack\r
+  )\r
+{\r
+  EFI_SEC_PEI_HAND_OFF  SecCoreData;\r
+  SEC_IDT_TABLE         IdtTableInStack;\r
+  IA32_DESCRIPTOR       IdtDescriptor;\r
+  UINT32                Index;\r
+  volatile UINT8        *Table;\r
+\r
+  if (TdIsEnabled ()) {\r
+    //\r
+    // For Td guests, the memory map info is in TdHobLib. It should be processed\r
+    // first so that the memory is accepted. Otherwise access to the unaccepted\r
+    // memory will trigger tripple fault.\r
+    //\r
+    if (ProcessTdxHobList () != EFI_SUCCESS) {\r
+      CpuDeadLoop ();\r
+    }\r
+  }\r
+\r
+  //\r
+  // To ensure SMM can't be compromised on S3 resume, we must force re-init of\r
+  // the BaseExtractGuidedSectionLib. Since this is before library contructors\r
+  // are called, we must use a loop rather than SetMem.\r
+  //\r
+  Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);\r
+  for (Index = 0;\r
+       Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);\r
+       ++Index)\r
+  {\r
+    Table[Index] = 0;\r
+  }\r
+\r
+  //\r
+  // Initialize IDT - Since this is before library constructors are called,\r
+  // we use a loop rather than CopyMem.\r
+  //\r
+  IdtTableInStack.PeiService = NULL;\r
+\r
+  for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
+    //\r
+    // Declare the local variables that actually move the data elements as\r
+    // volatile to prevent the optimizer from replacing this function with\r
+    // the intrinsic memcpy()\r
+    //\r
+    CONST UINT8     *Src;\r
+    volatile UINT8  *Dst;\r
+    UINTN           Byte;\r
+\r
+    Src = (CONST UINT8 *)&mIdtEntryTemplate;\r
+    Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];\r
+\r
+    for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {\r
+      Dst[Byte] = Src[Byte];\r
+    }\r
+  }\r
+\r
+  IdtDescriptor.Base  = (UINTN)&IdtTableInStack.IdtTable;\r
+  IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
+\r
+  ProcessLibraryConstructorList (NULL, NULL);\r
+\r
+  //\r
+  // Load the IDTR.\r
+  //\r
+  AsmWriteIdtr (&IdtDescriptor);\r
+\r
+  if (TdIsEnabled ()) {\r
+    //\r
+    // InitializeCpuExceptionHandlers () should be called in Td guests so that\r
+    // #VE exceptions can be handled correctly.\r
+    //\r
+    InitializeCpuExceptionHandlers (NULL);\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
+    (UINT32)(UINTN)BootFv,\r
+    (UINT32)(UINTN)TopOfCurrentStack\r
+    ));\r
+\r
+  //\r
+  // Initialize floating point operating environment\r
+  // to be compliant with UEFI spec.\r
+  //\r
+  InitializeFloatingPointUnits ();\r
+\r
+  //\r
+  // ASSERT that the Page Tables were set by the reset vector code to\r
+  // the address we expect.\r
+  //\r
+  ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));\r
+\r
+  //\r
+  // |-------------|       <-- TopOfCurrentStack\r
+  // |   Stack     | 32k\r
+  // |-------------|\r
+  // |    Heap     | 32k\r
+  // |-------------|       <-- SecCoreData.TemporaryRamBase\r
+  //\r
+\r
+  ASSERT (\r
+    (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
+            PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
+    (UINTN)TopOfCurrentStack\r
+    );\r
+\r
+  //\r
+  // Initialize SEC hand-off state\r
+  //\r
+  SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);\r
+\r
+  SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
+  SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
+\r
+  SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
+  SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+  SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
+  SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+  SecCoreData.BootFirmwareVolumeBase = BootFv;\r
+  SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;\r
+\r
+  //\r
+  // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
+  //\r
+  IoWrite8 (0x21, 0xff);\r
+  IoWrite8 (0xA1, 0xff);\r
+\r
+  //\r
+  // Initialize Local APIC Timer hardware and disable Local APIC Timer\r
+  // interrupts before initializing the Debug Agent and the debug timer is\r
+  // enabled.\r
+  //\r
+  InitializeApicTimer (0, MAX_UINT32, TRUE, 5);\r
+  DisableApicTimerInterrupt ();\r
+\r
+  PeilessStartup (&SecCoreData);\r
+\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+}\r
diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.inf b/OvmfPkg/IntelTdx/Sec/SecMain.inf
new file mode 100644 (file)
index 0000000..df2e749
--- /dev/null
@@ -0,0 +1,61 @@
+## @file\r
+#  SEC Driver\r
+#\r
+#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+#\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SecMain\r
+  FILE_GUID                      = 69d96630-eb64-4b33-8491-13a5cf023dcf\r
+  MODULE_TYPE                    = SEC\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SecMain\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = X64\r
+#\r
+\r
+[Sources]\r
+  SecMain.c\r
+  X64/SecEntry.nasm\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  EmbeddedPkg/EmbeddedPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  DebugLib\r
+  BaseMemoryLib\r
+  PcdLib\r
+  UefiCpuLib\r
+  DebugAgentLib\r
+  IoLib\r
+  PeCoffLib\r
+  PeCoffGetEntryPointLib\r
+  PeCoffExtraActionLib\r
+  ExtractGuidedSectionLib\r
+  LocalApicLib\r
+  MemEncryptSevLib\r
+  CpuExceptionHandlerLib\r
+  PeilessStartupLib\r
+  PlatformInitLib\r
+\r
+[Pcd]\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize\r
+  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase\r
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase\r
diff --git a/OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm b/OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm
new file mode 100644 (file)
index 0000000..4528fec
--- /dev/null
@@ -0,0 +1,151 @@
+;------------------------------------------------------------------------------\r
+;*\r
+;*   Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
+;*   SPDX-License-Identifier: BSD-2-Clause-Patent\r
+;*\r
+;*    CpuAsm.asm\r
+;*\r
+;*   Abstract:\r
+;*\r
+;------------------------------------------------------------------------------\r
+\r
+#include <Base.h>\r
+%include "TdxCommondefs.inc"\r
+\r
+DEFAULT REL\r
+SECTION .text\r
+\r
+extern ASM_PFX(SecCoreStartupWithStack)\r
+\r
+%macro  tdcall  0\r
+  db  0x66, 0x0f, 0x01, 0xcc\r
+%endmacro\r
+\r
+;\r
+; SecCore Entry Point\r
+;\r
+; Processor is in flat protected mode\r
+;\r
+; @param[in]  RAX   Initial value of the EAX register (BIST: Built-in Self Test)\r
+; @param[in]  DI    'BP': boot-strap processor, or 'AP': application processor\r
+; @param[in]  RBP   Pointer to the start of the Boot Firmware Volume\r
+; @param[in]  DS    Selector allowing flat access to all addresses\r
+; @param[in]  ES    Selector allowing flat access to all addresses\r
+; @param[in]  FS    Selector allowing flat access to all addresses\r
+; @param[in]  GS    Selector allowing flat access to all addresses\r
+; @param[in]  SS    Selector allowing flat access to all addresses\r
+;\r
+; @return     None  This routine does not return\r
+;\r
+global ASM_PFX(_ModuleEntryPoint)\r
+ASM_PFX(_ModuleEntryPoint):\r
+\r
+    ;\r
+    ; Guest type is stored in OVMF_WORK_AREA\r
+    ;\r
+    %define OVMF_WORK_AREA        FixedPcdGet32 (PcdOvmfWorkAreaBase)\r
+    %define VM_GUEST_TYPE_TDX     2\r
+    mov     eax, OVMF_WORK_AREA\r
+    cmp     byte[eax], VM_GUEST_TYPE_TDX\r
+    jne     InitStack\r
+\r
+    mov     rax, TDCALL_TDINFO\r
+    tdcall\r
+\r
+    ;\r
+    ; R8  [31:0]  NUM_VCPUS\r
+    ;     [63:32] MAX_VCPUS\r
+    ; R9  [31:0]  VCPU_INDEX\r
+    ; Td Guest set the VCPU0 as the BSP, others are the APs\r
+    ; APs jump to spinloop and get released by DXE's MpInitLib\r
+    ;\r
+    mov     rax, r9\r
+    and     rax, 0xffff\r
+    test    rax, rax\r
+    jne     ParkAp\r
+\r
+InitStack:\r
+\r
+    ;\r
+    ; Fill the temporary RAM with the initial stack value.\r
+    ; The loop below will seed the heap as well, but that's harmless.\r
+    ;\r
+    mov     rax, (FixedPcdGet32 (PcdInitValueInTempStack) << 32) | FixedPcdGet32 (PcdInitValueInTempStack)\r
+                                                              ; qword to store\r
+    mov     rdi, FixedPcdGet32 (PcdOvmfSecPeiTempRamBase)     ; base address,\r
+                                                              ;   relative to\r
+                                                              ;   ES\r
+    mov     rcx, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) / 8 ; qword count\r
+    cld                                                       ; store from base\r
+                                                              ;   up\r
+    rep stosq\r
+\r
+    ;\r
+    ; Load temporary RAM stack based on PCDs\r
+    ;\r
+    %define SEC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + \\r
+                          FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))\r
+    mov     rsp, SEC_TOP_OF_STACK\r
+    nop\r
+\r
+    ;\r
+    ; Setup parameters and call SecCoreStartupWithStack\r
+    ;   rcx: BootFirmwareVolumePtr\r
+    ;   rdx: TopOfCurrentStack\r
+    ;\r
+    mov     rcx, rbp\r
+    mov     rdx, rsp\r
+    sub     rsp, 0x20\r
+    call    ASM_PFX(SecCoreStartupWithStack)\r
+\r
+    ;\r
+    ; Note: BSP never gets here. APs will be unblocked by DXE\r
+    ;\r
+    ; R8  [31:0]  NUM_VCPUS\r
+    ;     [63:32] MAX_VCPUS\r
+    ; R9  [31:0]  VCPU_INDEX\r
+    ;\r
+ParkAp:\r
+\r
+    mov     rbp,  r9\r
+\r
+.do_wait_loop:\r
+    mov     rsp, FixedPcdGet32 (PcdOvmfSecGhcbBackupBase)\r
+\r
+    ;\r
+    ; register itself in [rsp + CpuArrivalOffset]\r
+    ;\r
+    mov       rax, 1\r
+    lock xadd dword [rsp + CpuArrivalOffset], eax\r
+    inc       eax\r
+\r
+.check_arrival_cnt:\r
+    cmp       eax, r8d\r
+    je        .check_command\r
+    mov       eax, dword[rsp + CpuArrivalOffset]\r
+    jmp       .check_arrival_cnt\r
+\r
+.check_command:\r
+    mov     eax, dword[rsp + CommandOffset]\r
+    cmp     eax, MpProtectedModeWakeupCommandNoop\r
+    je      .check_command\r
+\r
+    cmp     eax, MpProtectedModeWakeupCommandWakeup\r
+    je      .do_wakeup\r
+\r
+    ; Don't support this command, so ignore\r
+    jmp     .check_command\r
+\r
+.do_wakeup:\r
+    ;\r
+    ; BSP sets these variables before unblocking APs\r
+    ;   RAX:  WakeupVectorOffset\r
+    ;   RBX:  Relocated mailbox address\r
+    ;   RBP:  vCpuId\r
+    ;\r
+    mov     rax, 0\r
+    mov     eax, dword[rsp + WakeupVectorOffset]\r
+    mov     rbx, [rsp + WakeupArgsRelocatedMailBox]\r
+    nop\r
+    jmp     rax\r
+    jmp     $\r