public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Min Xu" <min.m.xu@intel.com>
To: devel@edk2.groups.io
Cc: Min Xu <min.m.xu@intel.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Erdem Aktas <erdemaktas@google.com>,
	James Bottomley <jejb@linux.ibm.com>,
	Jiewen Yao <jiewen.yao@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: [PATCH V3 5/8] OvmfPkg/IntelTdx: Add Sec to bring up both Legacy and Tdx guest
Date: Sun, 20 Feb 2022 10:33:16 +0800	[thread overview]
Message-ID: <20220220023319.1495-6-min.m.xu@intel.com> (raw)
In-Reply-To: <20220220023319.1495-1-min.m.xu@intel.com>

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 TdxStartup () 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>
Signed-off-by: Min Xu <min.m.xu@intel.com>
---
 OvmfPkg/IntelTdx/Sec/SecMain.c         | 198 +++++++++++++++++++++++++
 OvmfPkg/IntelTdx/Sec/SecMain.inf       |  61 ++++++++
 OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm | 151 +++++++++++++++++++
 3 files changed, 410 insertions(+)
 create mode 100644 OvmfPkg/IntelTdx/Sec/SecMain.c
 create mode 100644 OvmfPkg/IntelTdx/Sec/SecMain.inf
 create mode 100644 OvmfPkg/IntelTdx/Sec/X64/SecEntry.nasm

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


  parent reply	other threads:[~2022-02-20  2:33 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-20  2:33 [PATCH V3 0/8] Introduce TDVF Config-B (basic) in OvmfPkg Min Xu
2022-02-20  2:33 ` [PATCH V3 1/8] OvmfPkg: Add TdxWorkArea definition Min Xu
2022-02-20  2:33 ` [PATCH V3 2/8] OvmfPkg: Add PrePiHobListPointerLibTdx Min Xu
2022-02-23 10:26   ` Gerd Hoffmann
2022-02-20  2:33 ` [PATCH V3 3/8] OvmfPkg: Update EFI_HOB_PLATFORM_INFO with more platform settings Min Xu
2022-02-23 10:27   ` Gerd Hoffmann
2022-02-20  2:33 ` [PATCH V3 4/8] OvmfPkg: Add TdxStartupLib Min Xu
2022-02-23 10:50   ` Gerd Hoffmann
2022-02-24  1:09     ` [edk2-devel] " Min Xu
2022-02-24  6:22       ` Gerd Hoffmann
2022-02-20  2:33 ` Min Xu [this message]
2022-02-23 10:53   ` [PATCH V3 5/8] OvmfPkg/IntelTdx: Add Sec to bring up both Legacy and Tdx guest Gerd Hoffmann
2022-02-20  2:33 ` [PATCH V3 6/8] OvmfPkg: Update TdxDxe to set TDX PCDs Min Xu
2022-02-23 10:58   ` Gerd Hoffmann
2022-02-20  2:33 ` [PATCH V3 7/8] OvmfPkg: Update DxeAcpiTimerLib to read HostBridgeDevId in PlatformInfoHob Min Xu
2022-02-23 11:03   ` Gerd Hoffmann
2022-02-24  2:12     ` Min Xu
2022-02-20  2:33 ` [PATCH V3 8/8] OvmfPkg: Introduce IntelTdxX64 for TDVF Config-B Min Xu
2022-02-23 11:06   ` Gerd Hoffmann
2022-02-24  2:14     ` [edk2-devel] " Min Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220220023319.1495-6-min.m.xu@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox