From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.158.5]) by mx.groups.io with SMTP id smtpd.web12.453.1614718141998417433 for ; Tue, 02 Mar 2021 12:49:02 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@ibm.com header.s=pp1 header.b=Rck8FhkM; spf=pass (domain: linux.ibm.com, ip: 148.163.158.5, mailfrom: tobin@linux.ibm.com) Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.43/8.16.0.43) with SMTP id 122KhKPS191382; Tue, 2 Mar 2021 15:49:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=FwmI2Z3fmd9hER7HOKsoOC4E+G72go4BC72kK8ZmILA=; b=Rck8FhkMhU+gf+BtQZStzjdMgyVSW+O+EIS2qKfD3sWlJadAXdjyYScnLNQoVVYNzqTh o0Z7h/PhzpSF7ynSeGX185ay+Movy6lHEi6NVKBn3iPCY4foPBmuPTh7yFe36xEDEhSY jeEiIE/ZV9FWKfud1zo0glTA1Cq8pBzKWTmlQSSXEO58BtKQqKy7V8qO0yk2X3Xj7BZ3 DAN4Z+msIHW7EtkAap4PMLeDEoDt1U07V9E3jALxO8EqIImoy3e1d57Hc0H60kHL10pC 6N7dIqkC6elTTrh391K1PkZMqSDBdYTQanL/uZ3TEJMUVELmqQrl8W3ZjTn9naBxNQUC lg== Received: from ppma01dal.us.ibm.com (83.d6.3fa9.ip4.static.sl-reverse.com [169.63.214.131]) by mx0b-001b2d01.pphosted.com with ESMTP id 371vn7r8bh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 02 Mar 2021 15:48:59 -0500 Received: from pps.filterd (ppma01dal.us.ibm.com [127.0.0.1]) by ppma01dal.us.ibm.com (8.16.0.42/8.16.0.42) with SMTP id 122KkqMW028086; Tue, 2 Mar 2021 20:48:57 GMT Received: from b03cxnp08026.gho.boulder.ibm.com (b03cxnp08026.gho.boulder.ibm.com [9.17.130.18]) by ppma01dal.us.ibm.com with ESMTP id 371qmuagy6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 02 Mar 2021 20:48:57 +0000 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 122Kmtgm23658894 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 2 Mar 2021 20:48:55 GMT Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0213AC605B; Tue, 2 Mar 2021 20:48:55 +0000 (GMT) Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6DDC3C6059; Tue, 2 Mar 2021 20:48:54 +0000 (GMT) Received: from amdrome1.watson.ibm.com (unknown [9.2.130.16]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP; Tue, 2 Mar 2021 20:48:54 +0000 (GMT) From: "Tobin Feldman-Fitzthum" To: devel@edk2.groups.io Cc: Dov Murik , Tobin Feldman-Fitzthum , Tobin Feldman-Fitzthum , James Bottomley , Hubertus Franke , Brijesh Singh , Ashish Kalra , Jon Grimm , Tom Lendacky Subject: [RFC PATCH 13/14] OvmfPkg/AmdSev: Don't overwrite MH stack Date: Tue, 2 Mar 2021 15:48:38 -0500 Message-Id: <20210302204839.82042-14-tobin@linux.ibm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210302204839.82042-1-tobin@linux.ibm.com> References: <20210302204839.82042-1-tobin@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.369,18.0.761 definitions=2021-03-02_08:2021-03-01,2021-03-02 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 mlxlogscore=999 adultscore=0 suspectscore=0 spamscore=0 lowpriorityscore=0 mlxscore=0 phishscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2103020156 Content-Transfer-Encoding: 8bit When restoring pages, the Migration Handler shoudl avoid overwriting its own stack. Signed-off-by: Tobin Feldman-Fitzthum --- .../ConfidentialMigrationDxe.inf | 2 + OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h | 235 ++++++++++++++++++ .../ConfidentialMigrationDxe.c | 30 ++- 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf index 8dadfd1d13..2816952863 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.inf @@ -16,6 +16,7 @@ [Sources] ConfidentialMigrationDxe.c VirtualMemory.h + MpLib.h [Packages] MdePkg/MdePkg.dec @@ -36,6 +37,7 @@ gUefiOvmfPkgTokenSpaceGuid.PcdIsConfidentialMigrationTarget gUefiOvmfPkgTokenSpaceGuid.PcdStartConfidentialMigrationHandler gUefiOvmfPkgTokenSpaceGuid.PcdConfidentialMigrationMailboxBase + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize [Depex] gEfiMpServiceProtocolGuid diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h b/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h new file mode 100644 index 0000000000..5007e25243 --- /dev/null +++ b/OvmfPkg/AmdSev/ConfidentialMigration/MpLib.h @@ -0,0 +1,235 @@ +/** @file + Common header file for MP Initialize Library. + -- adapted from UefiCpuPkg/Library/MpInitLib/MpLib.h + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, AMD Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef _MP_LIB_H_ +#define _MP_LIB_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#define CPU_INIT_MP_LIB_HOB_GUID \ + { \ + 0x58eb6a19, 0x3699, 0x4c68, { 0xa8, 0x36, 0xda, 0xcd, 0x8e, 0xdc, 0xad, 0x4a } \ + } + + +// +// 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; + +// +// AP initialization state during APs wakeup +// +typedef enum { + ApInitConfig = 1, + ApInitReconfig = 2, + ApInitDone = 3 +} AP_INIT_STATE; + +// +// AP state +// +// The state transitions for an AP when it process a procedure are: +// Idle ----> Ready ----> Busy ----> Idle +// [BSP] [AP] [AP] +// +typedef enum { + CpuStateIdle, + CpuStateReady, + CpuStateBusy, + CpuStateFinished, + CpuStateDisabled +} CPU_STATE; + +// +// CPU volatile registers around INIT-SIPI-SIPI +// +typedef struct { + UINTN Cr0; + UINTN Cr3; + UINTN Cr4; + UINTN Dr0; + UINTN Dr1; + UINTN Dr2; + UINTN Dr3; + UINTN Dr6; + UINTN Dr7; + IA32_DESCRIPTOR Gdtr; + IA32_DESCRIPTOR Idtr; + UINT16 Tr; +} CPU_VOLATILE_REGISTERS; + +// +// AP related data +// +typedef struct { + SPIN_LOCK ApLock; + volatile UINT32 *StartupApSignal; + volatile UINTN ApFunction; + volatile UINTN ApFunctionArgument; + BOOLEAN CpuHealthy; + volatile CPU_STATE State; + CPU_VOLATILE_REGISTERS VolatileRegisters; + BOOLEAN Waiting; + BOOLEAN *Finished; + UINT64 ExpectedTime; + UINT64 CurrentTime; + UINT64 TotalTime; + EFI_EVENT WaitEvent; + UINT32 ProcessorSignature; + UINT8 PlatformId; + UINT64 MicrocodeEntryAddr; +} CPU_AP_DATA; + +// +// Basic CPU information saved in Guided HOB. +// Because the contents will be shard between PEI and DXE, +// we need to make sure the each fields offset same in different +// architecture. +// +#pragma pack (1) +typedef struct { + UINT32 InitialApicId; + UINT32 ApicId; + UINT32 Health; + UINT64 ApTopOfStack; +} CPU_INFO_IN_HOB; +#pragma pack () + +// +// AP reset code information including code address and size, +// this structure will be shared be C code and assembly code. +// It is natural aligned by design. +// +typedef struct { + UINT8 *RendezvousFunnelAddress; + UINTN ModeEntryOffset; + UINTN RendezvousFunnelSize; + UINT8 *RelocateApLoopFuncAddress; + UINTN RelocateApLoopFuncSize; + UINTN ModeTransitionOffset; +} MP_ASSEMBLY_ADDRESS_MAP; + +typedef struct _CPU_MP_DATA CPU_MP_DATA; + +#pragma pack(1) + +// +// MP CPU exchange information for AP reset code +// This structure is required to be packed because fixed field offsets +// into this structure are used in assembly code in this module +// +typedef struct { + UINTN Lock; + UINTN StackStart; + UINTN StackSize; + UINTN CFunction; + IA32_DESCRIPTOR GdtrProfile; + IA32_DESCRIPTOR IdtrProfile; + UINTN BufferStart; + UINTN ModeOffset; + UINTN ApIndex; + UINTN CodeSegment; + UINTN DataSegment; + UINTN EnableExecuteDisable; + UINTN Cr3; + UINTN InitFlag; + CPU_INFO_IN_HOB *CpuInfo; + UINTN NumApsExecuting; + CPU_MP_DATA *CpuMpData; + UINTN InitializeFloatingPointUnitsAddress; + UINT32 ModeTransitionMemory; + UINT16 ModeTransitionSegment; + UINT32 ModeHighMemory; + UINT16 ModeHighSegment; + // + // Enable5LevelPaging indicates whether 5-level paging is enabled in long mode. + // + BOOLEAN Enable5LevelPaging; +} MP_CPU_EXCHANGE_INFO; + +#pragma pack() + +// +// CPU MP Data save in memory +// +struct _CPU_MP_DATA { + UINT64 CpuInfoInHob; + UINT32 CpuCount; + UINT32 BspNumber; + // + // The above fields data will be passed from PEI to DXE + // Please make sure the fields offset same in the different + // architecture. + // + SPIN_LOCK MpLock; + UINTN Buffer; + UINTN CpuApStackSize; + MP_ASSEMBLY_ADDRESS_MAP AddressMap; + UINTN WakeupBuffer; + UINTN WakeupBufferHigh; + UINTN BackupBuffer; + UINTN BackupBufferSize; + + volatile UINT32 FinishedCount; + UINT32 RunningCount; + BOOLEAN SingleThread; + EFI_AP_PROCEDURE Procedure; + VOID *ProcArguments; + BOOLEAN *Finished; + UINT64 ExpectedTime; + UINT64 CurrentTime; + UINT64 TotalTime; + EFI_EVENT WaitEvent; + UINTN **FailedCpuList; + + AP_INIT_STATE InitFlag; + BOOLEAN SwitchBspFlag; + UINTN NewBspNumber; + CPU_EXCHANGE_ROLE_INFO BSPInfo; + CPU_EXCHANGE_ROLE_INFO APInfo; + MTRR_SETTINGS MtrrTable; + UINT8 ApLoopMode; + UINT8 ApTargetCState; + UINT16 PmCodeSegment; + CPU_AP_DATA *CpuData; + volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo; + + UINT32 CurrentTimerCount; + UINTN DivideValue; + UINT8 Vector; + BOOLEAN PeriodicMode; + BOOLEAN TimerInterruptState; + UINT64 MicrocodePatchAddress; + UINT64 MicrocodePatchRegionSize; + + // + // Whether need to use Init-Sipi-Sipi to wake up the APs. + // Two cases need to set this value to TRUE. One is in HLT + // loop mode, the other is resume from S3 which loop mode + // will be hardcode change to HLT mode by PiSmmCpuDxeSmm + // driver. + // + BOOLEAN WakeUpByInitSipiSipi; +}; + +extern EFI_GUID mCpuInitMpLibHobGuid; + +#endif diff --git a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c index f609e16f8d..42b99be552 100644 --- a/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c +++ b/OvmfPkg/AmdSev/ConfidentialMigration/ConfidentialMigrationDxe.c @@ -12,6 +12,8 @@ #include #include "VirtualMemory.h" +#include "MpLib.h" + // // Functions implemented by the migration handler // @@ -114,6 +116,7 @@ PrepareMigrationHandlerPageTables ( mMigrationHelperPageTables = (UINT64)Start | AddressEncMask; } + VOID SwitchToMigrationHelperPageTables(VOID) { @@ -121,6 +124,25 @@ SwitchToMigrationHelperPageTables(VOID) } +UINT64 +GetMHTopOfStack() +{ + EFI_HOB_GUID_TYPE *GuidHob; + VOID *DataInHob; + CPU_MP_DATA *CpuMpData; + CPU_INFO_IN_HOB *CpuInfoInHob; + + GuidHob = GetFirstGuidHob (&mCpuInitMpLibHobGuid); + ASSERT(GuidHob != NULL); + + DataInHob = GET_GUID_HOB_DATA (GuidHob); + CpuMpData = (CPU_MP_DATA *) (*(UINTN *) DataInHob); + CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; + + return CpuInfoInHob[MigrationHandlerCpuIndex].ApTopOfStack; + +} + VOID EFIAPI @@ -132,6 +154,8 @@ MigrationHandlerMain ( UINT64 mailbox_end; UINT64 pagetable_start; UINT64 pagetable_end; + UINT64 stack_start; + UINT64 stack_end; UINT64 params_base; MH_COMMAND_PARAMETERS *params; VOID *page_va; @@ -153,6 +177,9 @@ MigrationHandlerMain ( pagetable_start = mMigrationHelperPageTables; pagetable_end = pagetable_start + 11 * EFI_PAGE_SIZE; + stack_end = GetMHTopOfStack(); + stack_start = stack_end - PcdGet32(PcdCpuApStackSize); + DisableInterrupts(); params->go = 0; @@ -177,7 +204,8 @@ MigrationHandlerMain ( // Don't import a page that covers the mailbox or pagetables. // if ((params->gpa >= mailbox_start && params->gpa < mailbox_end) || - (params->gpa >= pagetable_start && params->gpa < pagetable_end)) { + (params->gpa >= pagetable_start && params->gpa < pagetable_end) || + (params->gpa >= stack_start && params->gpa < stack_end)) { } else { CopyMem((VOID *)params->gpa, page_va, 4096); -- 2.20.1