From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com []) by mx.groups.io with SMTP id smtpd.web12.670.1583190509745452410 for ; Mon, 02 Mar 2020 15:08:30 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=K4PS8rUI; spf=none, err=SPF record not found (domain: amd.com, ip: , mailfrom: thomas.lendacky@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=friGZDUTAdyU3F95PIbz191T6qS5c77UCFOjTIVcAWLibuuhiqTqcp9Otf0PUlIhbS9PMV3KGJ2PCyOYwO2VU0QL8fAWDB37jUdBJt0MYu6Xj8qW70WUFmgjraw+XXZn9vFRlUBKaekUtfqGixRZLbTbgb04uMqaqzVa8sYEe7QCqPyeYOuOx8pLK+BQ8chMIC/yLCd+IXbGkGUR8SyxqOxB4/Gdi0IdwW+al0nkUjIpzFzrmFhsRNwgObv79LtLc+SQmZ7wmbKdk+SulCiTKu3ic6pZbfiN47rH2zb251rjCGvKPv4ZCIw0BQfEjuvlMpakCnxt/vF2Jgt0HqEiBg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=taVdxhPXXkd6V3bZJdxY/DjHZW5tCJUifxUUMskatTs=; b=ThhYTOvb0p5pKLg2gKsWrC1tz+kfy7ls5QOsLBPmDPu12jFmvVQ1T92DWwdWN4NjGjkOgK7/vwGn2Vm2D6YbEN4Vypp0oJeAmc7R1/UA8w6P899ccoMvbcJ5YRbCXwORJSSuRLGf7DLVfUNw2ppPMamfuRgmRi4F22dHsdxYpMM3FWXjBg+W7rogS30alGSP1MbKA85SWQvxMmFwSS9pA48ovhrxB4+lTKhMBmsDU6OlUAhi/1jifpMfhsoPcG2y1bcqTZlaHKxWDe1RRpIMqoQ6RPm+QKtqBJ9G0PPt4/1cJkUw+RaK4CUguBl0UNCYo3Tfl+k7J/HdaLjWX/uoUQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector2-amdcloud-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=taVdxhPXXkd6V3bZJdxY/DjHZW5tCJUifxUUMskatTs=; b=K4PS8rUI5UlHARJTA2UXp9MpOGD1MbXmc+mj/EY6S+E9hUzlKHD4Wa2jtunQf8WhRxGcqfiBsYF+Aovi7VUaFfT0xY200qFjOn91hSl0gyU/kJDr9zkkc+lzPD3SHFUxO/k2XXYlq9yd6N2NWLaBuri5UsaLKX+ab5yVvQAfSqM= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Thomas.Lendacky@amd.com; Received: from DM6PR12MB3163.namprd12.prod.outlook.com (2603:10b6:5:15e::26) by DM6PR12MB4201.namprd12.prod.outlook.com (2603:10b6:5:216::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2772.18; Mon, 2 Mar 2020 23:08:28 +0000 Received: from DM6PR12MB3163.namprd12.prod.outlook.com ([fe80::f0f9:a88f:f840:2733]) by DM6PR12MB3163.namprd12.prod.outlook.com ([fe80::f0f9:a88f:f840:2733%7]) with mapi id 15.20.2772.019; Mon, 2 Mar 2020 23:08:28 +0000 From: "Lendacky, Thomas" To: devel@edk2.groups.io Cc: Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Michael D Kinney , Liming Gao , Eric Dong , Ray Ni , Brijesh Singh Subject: [PATCH v5 34/42] OvmfPkg/Sec: Add #VC exception handling for Sec phase Date: Mon, 2 Mar 2020 17:07:05 -0600 Message-Id: <555d15ee95133cce0617edbd5500c05785847a4c.1583190432.git.thomas.lendacky@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: X-ClientProxiedBy: DM5PR2001CA0013.namprd20.prod.outlook.com (2603:10b6:4:16::23) To DM6PR12MB3163.namprd12.prod.outlook.com (2603:10b6:5:15e::26) Return-Path: thomas.lendacky@amd.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from tlendack-t1.amd.com (165.204.77.1) by DM5PR2001CA0013.namprd20.prod.outlook.com (2603:10b6:4:16::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2772.16 via Frontend Transport; Mon, 2 Mar 2020 23:07:59 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [165.204.77.1] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 45f07a71-aa9c-4068-e47c-08d7befe8d7e X-MS-TrafficTypeDiagnostic: DM6PR12MB4201:|DM6PR12MB4201: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-Forefront-PRVS: 033054F29A X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4636009)(376002)(366004)(136003)(346002)(396003)(39860400002)(199004)(189003)(66946007)(8936002)(54906003)(316002)(81156014)(81166006)(6486002)(6916009)(6666004)(66556008)(8676002)(4326008)(66476007)(52116002)(7696005)(2616005)(5660300002)(2906002)(36756003)(186003)(966005)(86362001)(478600001)(16526019)(26005)(956004);DIR:OUT;SFP:1101;SCL:1;SRVR:DM6PR12MB4201;H:DM6PR12MB3163.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;MX:1; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: c3A1RquNsP5lZ5LqMHezNnhj6qgF/T6GTc2EOy1k6PUDl+MlAib9td6EvCx9vauLzG1qrWryKHfqvlEb2XAMBo1DJgP1BW78O1osudHzf68CRKKAbm6GmLe2ChmYQ7RYHaVGVAiYL1bxJ2zPSdQvlqEUY1j0yDgOGqx8nCpOYoc+qnY0HNH/IsQ8FwDm2a5bd69ys6WYww9qO3IP8z1IXOmAkvgR3XgrlqaxE8GE+5fWiwwf0nUqg8U5TScUOxAB4fhh6xEg1iUiv3lyBcEsDBL3LH+a0/k8JldAPzNk3+/KAUXHGzUUFtkWZoh1rLBmv7vZzpvvoPQBn4ptsbuk0cVo3COG1EHRSSgCaB7zLmbjBB7V6vmJFRnHNgxU0a54AtUCnwUna/fgJ2a5/NsZamfVFDVSZOVdLxWjpOBmDOky09aHJExu1Q9qy7m5c2++bm8vWs9+AihHXsjEewdL+hLfB1IXt1muyDQrlCOfnhiq1fFpXVqAm5GTr3l86GT68Ma0VXWjLaePLI3Ah3ousw== X-MS-Exchange-AntiSpam-MessageData: s5WAyz5gnA28NENPyzLxDre2prqoJMFoGyqLEaXG+hab/HYubO6xtcejfJbc5lYcBV8a6Gz79TMO9hwhavOuSPlEHKtcWumL00S7ZdBPm7cuQ2pCtYq/XSQxk1aMhdmbAAN73pvMFohuxI/yKkkyrA== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 45f07a71-aa9c-4068-e47c-08d7befe8d7e X-MS-Exchange-CrossTenant-OriginalArrivalTime: 02 Mar 2020 23:08:00.2847 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 6zbss+HCNJhqsHjcF2+DwWnYtSLGiPh+GH9CTmf0AJmYx9AOg0tZEkeLI5XiFROfFwPVf3QVuVJx/nIeojSAGg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4201 Content-Type: text/plain BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198 An SEV-ES guest will generate a #VC exception when it encounters a non-automatic exit (NAE) event. It is expected that the #VC exception handler will communicate with the hypervisor using the GHCB to handle the NAE event. NAE events can occur during the Sec phase, so initialize exception handling early in the OVMF Sec support. Cc: Jordan Justen Cc: Laszlo Ersek Cc: Ard Biesheuvel Reviewed-by: Laszlo Ersek Signed-off-by: Tom Lendacky --- OvmfPkg/Sec/SecMain.inf | 4 ++ OvmfPkg/Sec/SecMain.c | 151 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 142 insertions(+), 13 deletions(-) diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index 63ba4cb555fb..7f78dcee2772 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -50,15 +50,19 @@ [LibraryClasses] PeCoffExtraActionLib ExtractGuidedSectionLib LocalApicLib + CpuExceptionHandlerLib [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED [Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index bae9764577f0..577596a949f9 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include @@ -34,6 +37,10 @@ typedef struct _SEC_IDT_TABLE { IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; } SEC_IDT_TABLE; +typedef struct _SEC_SEV_ES_WORK_AREA { + UINT8 SevEsEnabled; +} SEC_SEV_ES_WORK_AREA; + VOID EFIAPI SecStartupPhase2 ( @@ -712,6 +719,90 @@ FindAndReportEntryPoints ( return; } +STATIC +VOID +SevEsProtocolFailure ( + IN UINT8 ReasonCode + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + + // + // Use the GHCB MSR Protocol to request termination by the hypervisor + // + Msr.GhcbPhysicalAddress = 0; + Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST; + Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB; + Msr.GhcbTerminate.ReasonCode = ReasonCode; + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + AsmVmgExit (); + + ASSERT (0); + CpuDeadLoop (); +} + +STATIC +VOID +SevEsProtocolCheck ( + VOID + ) +{ + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + + // + // Use the GHCB MSR Protocol to obtain the GHCB SEV-ES Information for + // protocol checking + // + Msr.GhcbPhysicalAddress = 0; + Msr.GhcbInfo.Function = GHCB_INFO_SEV_INFO_GET; + AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + AsmVmgExit (); + + Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); + + if (Msr.GhcbInfo.Function != GHCB_INFO_SEV_INFO) { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL); + } + + if (Msr.GhcbProtocol.SevEsProtocolMin > Msr.GhcbProtocol.SevEsProtocolMax) { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); + } + + if ((Msr.GhcbProtocol.SevEsProtocolMin > GHCB_VERSION_MAX) || + (Msr.GhcbProtocol.SevEsProtocolMax < GHCB_VERSION_MIN)) { + SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL); + } + + // + // SEV-ES protocol checking succeeded, set the initial GHCB address + // + Msr.GhcbPhysicalAddress = FixedPcdGet32 (PcdOvmfSecGhcbBase); + AsmWriteMsr64(MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + Ghcb = Msr.Ghcb; + SetMem (Ghcb, sizeof (*Ghcb), 0); + + /* Set the version to the maximum that can be supported */ + Ghcb->ProtocolVersion = MIN (Msr.GhcbProtocol.SevEsProtocolMax, GHCB_VERSION_MAX); + Ghcb->GhcbUsage = GHCB_STANDARD_USAGE; +} + +STATIC +BOOLEAN +SevEsIsEnabled ( + VOID + ) +{ + SEC_SEV_ES_WORK_AREA *SevEsWorkArea; + + SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase); + + return ((SevEsWorkArea != NULL) && (SevEsWorkArea->SevEsEnabled != 0)); +} + VOID EFIAPI SecCoreStartupWithStack ( @@ -737,8 +828,55 @@ SecCoreStartupWithStack ( 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 ++) { + UINT8 *Src, *Dst; + UINTN Byte; + + Src = (UINT8 *) &mIdtEntryTemplate; + Dst = (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); + + if (SevEsIsEnabled ()) { + SevEsProtocolCheck (); + + // + // For SEV-ES guests, the exception handler is needed before calling + // ProcessLibraryConstructorList() because some of the library constructors + // perform some functions that result in #VC exceptions being generated. + // + // Due to this code executing before library constructors, *all* library + // API calls are theoretically interface contract violations. However, + // because this is SEC (executing in flash), those constructors cannot + // write variables with static storage duration anyway. Furthermore, only + // a small, restricted set of APIs, such as AsmWriteIdtr() and + // InitializeCpuExceptionHandlers(), are called, where we require that the + // underlying library not require constructors to have been invoked and + // that the library instance not trigger any #VC exceptions. + // + AsmWriteIdtr (&IdtDescriptor); + InitializeCpuExceptionHandlers (NULL); + } + ProcessLibraryConstructorList (NULL, NULL); + if (!SevEsIsEnabled ()) { + // + // For non SEV-ES guests, just load the IDTR. + // + AsmWriteIdtr (&IdtDescriptor); + } + DEBUG ((EFI_D_INFO, "SecCoreStartupWithStack(0x%x, 0x%x)\n", (UINT32)(UINTN)BootFv, @@ -751,19 +889,6 @@ SecCoreStartupWithStack ( // InitializeFloatingPointUnits (); - // - // Initialize IDT - // - IdtTableInStack.PeiService = NULL; - for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { - CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); - } - - IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; - IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); - - AsmWriteIdtr (&IdtDescriptor); - #if defined (MDE_CPU_X64) // // ASSERT that the Page Tables were set by the reset vector code to -- 2.17.1