From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.120]) by mx.groups.io with SMTP id smtpd.web09.22623.1574335803165996952 for ; Thu, 21 Nov 2019 03:30:03 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=edHzBweR; spf=pass (domain: redhat.com, ip: 207.211.31.120, mailfrom: lersek@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1574335802; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ClVtEs41tQtfCZnHmEuBgFvCF87tPGOYVant3B9EeH8=; b=edHzBweRCUH2MAmR9yD2ZkjMF4WBpGGoXRu6m2LAzpsuBL/GQkz3xzQ7KJ0Wujs/T/UscI Ox+URV03nUSr0j486l4tUNKKacJ6OAb/qe4qkjmhnuRUS8Bi8ddM6iK9sVW3pcP9gZNXgV VNXVbfb//FpCs2I/j7Slozf4PWulj90= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-267-bB1hBrfgPZSajfjnWa0kTw-1; Thu, 21 Nov 2019 06:29:58 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C561F107ACC7; Thu, 21 Nov 2019 11:29:56 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-197.ams2.redhat.com [10.36.116.197]) by smtp.corp.redhat.com (Postfix) with ESMTP id B25E560C2C; Thu, 21 Nov 2019 11:29:54 +0000 (UTC) Subject: Re: [edk2-devel] [RFC PATCH v3 26/43] OvmfPkg: Create a GHCB page for use during Sec phase To: devel@edk2.groups.io, thomas.lendacky@amd.com Cc: Jordan Justen , Ard Biesheuvel , Michael D Kinney , Liming Gao , Eric Dong , Ray Ni , Brijesh Singh References: <8122f72ab770e689e2679ce478125311b4681beb.1574280425.git.thomas.lendacky@amd.com> From: "Laszlo Ersek" Message-ID: <2b937a3a-0765-7eeb-28de-f1bc51fc264b@redhat.com> Date: Thu, 21 Nov 2019 12:29:53 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <8122f72ab770e689e2679ce478125311b4681beb.1574280425.git.thomas.lendacky@amd.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: bB1hBrfgPZSajfjnWa0kTw-1 X-Mimecast-Spam-Score: 0 Content-Language: en-US Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable On 11/20/19 21:06, Lendacky, Thomas wrote: > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2198 >=20 > A GHCB page is needed during the Sec phase, so this new page must be > created. Since the #VC exception handler routines assume that a per-CPU > variable area is immediately after the GHCB, this per-CPU variable area > must also be created. Since the GHCB must be marked as an un-encrypted, > or shared, page, an additional pagetable page is required to break down > the 2MB region where the GHCB page lives into 4K pagetable entries. >=20 > Create a new entry in the OVMF memory layout for the new page table > page and for the SEC GHCB and per-CPU variable pages. After breaking down > the 2MB page, update the GHCB page table entry to remove the encryption > mask. >=20 > The GHCB page will be used by the SEC #VC exception handler. The #VC > exception handler will fill in the necessary fields of the GHCB and exit > to the hypervisor using the VMGEXIT instruction. The hypervisor then > accesses the GHCB in order to perform the requested function. >=20 > Cc: Jordan Justen > Cc: Laszlo Ersek > Cc: Ard Biesheuvel > Signed-off-by: Tom Lendacky > --- > OvmfPkg/OvmfPkg.dec | 5 ++ > OvmfPkg/OvmfPkgX64.fdf | 6 ++ > OvmfPkg/ResetVector/ResetVector.inf | 5 ++ > OvmfPkg/ResetVector/Ia32/PageTables64.asm | 76 +++++++++++++++++++++++ > OvmfPkg/ResetVector/ResetVector.nasmb | 16 +++++ > 5 files changed, 108 insertions(+) >=20 > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec > index d5fee805ef4a..19723786d729 100644 > --- a/OvmfPkg/OvmfPkg.dec > +++ b/OvmfPkg/OvmfPkg.dec > @@ -228,6 +228,11 @@ [PcdsFixedAtBuild] > ## Number of page frames to use for storing grant table entries. > gUefiOvmfPkgTokenSpaceGuid.PcdXenGrantFrames|4|UINT32|0x33 > =20 > + ## Specify the extra page table needed to mark the GHCB as unencrypted= . > + # The value should be a multiple of 4KB for each. > + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|0x0|UINT32|0x34 > + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize|0x0|UINT32|0x35 > + > [PcdsDynamic, PcdsDynamicEx] > gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0= x10 > diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf > index e49adc425fce..973b19fdbf19 100644 > --- a/OvmfPkg/OvmfPkgX64.fdf > +++ b/OvmfPkg/OvmfPkgX64.fdf > @@ -76,6 +76,12 @@ [FD.MEMFD] > 0x007000|0x001000 > gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPk= gTokenSpaceGuid.PcdGuidedExtractHandlerTableSize > =20 > +0x008000|0x001000 > +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|gUefiOvmfPkgToken= SpaceGuid.PcdOvmfSecGhcbPageTableSize > + > +0x009000|0x002000 > +gEfiMdeModulePkgTokenSpaceGuid.PcdSecGhcbBase|gEfiMdeModulePkgTokenSpace= Guid.PcdSecGhcbSize > + > 0x010000|0x010000 > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpa= ceGuid.PcdOvmfSecPeiTempRamSize > =20 > diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/Re= setVector.inf > index 960b47cd0797..266c5fc5c8b3 100644 > --- a/OvmfPkg/ResetVector/ResetVector.inf > +++ b/OvmfPkg/ResetVector/ResetVector.inf > @@ -26,6 +26,7 @@ [Sources] > [Packages] > OvmfPkg/OvmfPkg.dec > MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > UefiCpuPkg/UefiCpuPkg.dec > =20 > [BuildOptions] > @@ -33,7 +34,11 @@ [BuildOptions] > *_*_X64_NASMB_FLAGS =3D -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/ > =20 > [Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdSecGhcbBase > + gEfiMdeModulePkgTokenSpaceGuid.PcdSecGhcbSize > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase > gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize > + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase > + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize > diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVec= tor/Ia32/PageTables64.asm > index c902fa68d556..b064ca65b88d 100644 > --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm > +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm > @@ -21,6 +21,11 @@ BITS 32 > %define PAGE_2M_MBO 0x080 > %define PAGE_2M_PAT 0x01000 > =20 > +%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \ > + PAGE_DIRTY + \ > + PAGE_READ_WRITE + \ > + PAGE_PRESENT) > + > %define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \ > PAGE_ACCESSED + \ > PAGE_DIRTY + \ > @@ -123,6 +128,37 @@ SevExit: > =20 > OneTimeCallRet CheckSevFeature > =20 > +; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) fe= ature > +; is enabled. > +; > +; Modified: EAX, EBX, ECX > +; > +; If SEV-ES is enabled then EAX will be non-zero. > +; If SEV-ES is disabled then EAX will be zero. > +; > +CheckSevEsFeature: > + xor eax, eax > + > + ; SEV-ES can't be enabled if SEV isn't, so first check the encryptio= n > + ; mask. > + test edx, edx > + jz NoSevEs > + > + ; Save current value of encryption mask > + mov ebx, edx > + > + ; Check if SEV-ES is enabled > + ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled) > + mov ecx, 0xc0010131 > + rdmsr > + and eax, 2 > + > + ; Restore encryption mask > + mov edx, ebx > + > +NoSevEs: > + OneTimeCallRet CheckSevEsFeature > + > ; > ; Modified: EAX, EBX, ECX, EDX > ; > @@ -187,6 +223,46 @@ pageTableEntriesLoop: > mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx > loop pageTableEntriesLoop > =20 > + OneTimeCall CheckSevEsFeature > + test eax, eax > + jz SetCr3 > + > + ; > + ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypt= ed. > + ; This requires the 2MB page for this range be broken down into 512 = 4KB > + ; pages. All will be marked encrypted, except for the GHCB. > + ; > + mov ecx, (GHCB_BASE >> 21) > + mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR > + mov [ecx * 8 + PT_ADDR (0x2000)], eax > + > + ; > + ; Page Table Entries (512 * 4KB entries =3D> 2MB) > + ; > + mov ecx, 512 > +pageTableEntries4kLoop: > + mov eax, ecx > + dec eax > + shl eax, 12 > + add eax, GHCB_BASE & 0xFFE0_0000 > + add eax, PAGE_4K_PDE_ATTR > + mov [ecx * 8 + GHCB_PT_ADDR - 8], eax > + mov [(ecx * 8 + GHCB_PT_ADDR - 8) + 4], edx > + loop pageTableEntries4kLoop > + > + ; > + ; Clear the encryption bit from the GHCB entry > + ; > + mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12 > + mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0 > + > + mov ecx, GHCB_SIZE / 4 > + xor eax, eax > +clearGhcbMemoryLoop: > + mov dword[ecx * 4 + GHCB_BASE - 4], eax > + loop clearGhcbMemoryLoop > + > +SetCr3: > ; > ; Set CR3 now that the paging structures are available > ; > diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/= ResetVector.nasmb > index 579c75f5ba0c..708bbda6208f 100644 > --- a/OvmfPkg/ResetVector/ResetVector.nasmb > +++ b/OvmfPkg/ResetVector/ResetVector.nasmb > @@ -53,9 +53,25 @@ > %error "This implementation inherently depends on PcdOvmfSecPageTabl= esSize" > %endif > =20 > + %if (FixedPcdGet32 (PcdOvmfSecGhcbPageTableSize) !=3D 0x1000) > + %error "This implementation inherently depends on PcdOvmfSecGhcbPage= TableSize" > + %endif > + > + %if (FixedPcdGet32 (PcdSecGhcbSize) !=3D 0x2000) > + %error "This implementation inherently depends on PcdSecGhcbSize" > + %endif > + > + %if ((FixedPcdGet32 (PcdSecGhcbBase) >> 21) !=3D \ > + ((FixedPcdGet32 (PcdSecGhcbBase) + FixedPcdGet32 (PcdSecGhcbSize)= - 1) >> 21)) > + %error "This implementation inherently depends on PcdSecGhcbBase not= straddling a 2MB boundary" > + %endif > + > %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (O= ffset)) > %include "Ia32/Flat32ToFlat64.asm" > =20 > + %define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase)) > + %define GHCB_BASE (FixedPcdGet32 (PcdSecGhcbBase)) > + %define GHCB_SIZE (FixedPcdGet32 (PcdSecGhcbSize)) > %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBas= e) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) > %include "Ia32/PageTables64.asm" > %endif >=20 Reviewed-by: Laszlo Ersek