From mboxrd@z Thu Jan  1 00:00:00 1970
Authentication-Results: mx.groups.io;
 dkim=pass header.i=@amdcloud.onmicrosoft.com header.s=selector2-amdcloud-onmicrosoft-com header.b=TkeZa/SU;
 spf=none, err=SPF record not found (domain: amd.com, ip: 40.107.73.51, mailfrom: thomas.lendacky@amd.com)
Received: from NAM05-DM3-obe.outbound.protection.outlook.com (NAM05-DM3-obe.outbound.protection.outlook.com [40.107.73.51])
 by groups.io with SMTP; Mon, 19 Aug 2019 14:35:51 -0700
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=acg9+XvNGRUvrMkji6jDck0jRaD22mLGkAtRNxMeWhup/WH1PMDiBMMv7wcROLFBZj0Y/Qw5sikyxk/FNvxYpFlT0BLi7btz9g5nujc51fEx8T+3n5tYYRZGkhDPjakneV1J80L3S17cJKlch2kfdCBFNTlnfEXL2OXzZOMI3CJ6hBG/bGpQoafJLsda3kvs6mtSzz3522Q64hjFzLllCtHwetd5i43cxlddjm4AkOmo/LhwyYSGBQeMh841Es585HJwRW0djdPvm6WhJLWMPABbXUcyWhDdyzIBabFpWSZVq14sCtqUOZHdOUo/BMOPChRSAk1o9F6kNrBYdmO8Pg==
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=HQvt2NGk6ajETxiUyoKUajkSvrEb+/fJ5WAvYmJBiRs=;
 b=Onm8EH01d1hZwURDe2/H2xauIE+aDyAossdIl3rwZO6YG5NRJjAa3utGDF+rKvRn1qy69bEBP+fHsGN9IGyJxJIlr1B7ca62AFqBD1/vfrtG9SEtPtU6Qf7dwwaTH3dabRdPG+lv6QjkvZO0nu7GLX1r4LFJAQD7xYP/a1qd1gcytlmrQq+FGHIYXKvCxuuoISguIcPtIryiPZmjErgSuWYk99ACDR0YUMBZLTEYlqXiJLsHvIStAkrRfVrzNav/o8nEXZ/FO3apbhfeZ1XuVGDtQ3epRlZGw8NbWrkcqyHwEYhXgAAN48TrPEpkGu/Wl+Ss2X8PeF3jvdtgMvoLuw==
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=HQvt2NGk6ajETxiUyoKUajkSvrEb+/fJ5WAvYmJBiRs=;
 b=TkeZa/SUWJV+vB9I2EuugFFiDI9IV6S2OnzpR5V+Ae1tYOAbvJWxLHaryduSqDc5yQb2pPH49JynQBUhEwPLqfT2BvkV5XBeqkT0ui131tvbDou5g+Tdnx+SwLoyfLIMNQm5Jf2oqS1/ng/2unUyiirqEVh0tW57g8Ad/pmQKjU=
Received: from BYAPR12MB3158.namprd12.prod.outlook.com (20.179.92.19) by
 BYAPR12MB3112.namprd12.prod.outlook.com (20.178.54.205) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.2157.20; Mon, 19 Aug 2019 21:35:49 +0000
Received: from BYAPR12MB3158.namprd12.prod.outlook.com
 ([fe80::39b9:76bd:a491:1f27]) by BYAPR12MB3158.namprd12.prod.outlook.com
 ([fe80::39b9:76bd:a491:1f27%6]) with mapi id 15.20.2157.022; Mon, 19 Aug 2019
 21:35:49 +0000
From: "Lendacky, Thomas" <thomas.lendacky@amd.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>
CC: Jordan Justen <jordan.l.justen@intel.com>, Laszlo Ersek
	<lersek@redhat.com>, Ard Biesheuvel <ard.biesheuvel@linaro.org>, Michael D
 Kinney <michael.d.kinney@intel.com>, Liming Gao <liming.gao@intel.com>, Eric
 Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>, "Singh, Brijesh"
	<brijesh.singh@amd.com>
Subject: [RFC PATCH 02/28] OvmfPkg/ResetVector: Add support for a 32-bit SEV check
Thread-Topic: [RFC PATCH 02/28] OvmfPkg/ResetVector: Add support for a 32-bit
 SEV check
Thread-Index: AQHVVtYRe7UyK6z5KUGPu1fyMOEv/Q==
Date: Mon, 19 Aug 2019 21:35:49 +0000
Message-ID: 
 <91782da0444dc5238d4623e96bfa1ab203586390.1566250534.git.thomas.lendacky@amd.com>
References: <cover.1566250534.git.thomas.lendacky@amd.com>
In-Reply-To: <cover.1566250534.git.thomas.lendacky@amd.com>
Accept-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-mailer: git-send-email 2.17.1
x-clientproxiedby: SN2PR01CA0031.prod.exchangelabs.com (2603:10b6:804:2::41)
 To BYAPR12MB3158.namprd12.prod.outlook.com (2603:10b6:a03:132::19)
authentication-results: spf=none (sender IP is )
 smtp.mailfrom=Thomas.Lendacky@amd.com; 
x-ms-exchange-messagesentrepresentingtype: 1
x-originating-ip: [165.204.77.1]
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: 95c7682f-c74a-46a5-1008-08d724ed33a9
x-ms-office365-filtering-ht: Tenant
x-microsoft-antispam: 
 BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(5600148)(711020)(4605104)(1401327)(4618075)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7193020);SRVR:BYAPR12MB3112;
x-ms-traffictypediagnostic: BYAPR12MB3112:
x-ms-exchange-transport-forked: True
x-microsoft-antispam-prvs: 
 <BYAPR12MB3112226EBF906432195A21A3ECA80@BYAPR12MB3112.namprd12.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:7691;
x-forefront-prvs: 0134AD334F
x-forefront-antispam-report: 
 SFV:NSPM;SFS:(10009020)(4636009)(39860400002)(346002)(376002)(366004)(396003)(136003)(189003)(199004)(66556008)(66476007)(5660300002)(52116002)(76176011)(186003)(86362001)(305945005)(7736002)(6116002)(66446008)(6916009)(5640700003)(36756003)(6436002)(6486002)(102836004)(6506007)(386003)(26005)(2351001)(476003)(2501003)(2616005)(486006)(11346002)(66066001)(118296001)(25786009)(446003)(54906003)(2906002)(19627235002)(4326008)(6512007)(99286004)(71200400001)(8936002)(50226002)(71190400001)(316002)(14444005)(8676002)(478600001)(256004)(53936002)(3846002)(81166006)(1730700003)(81156014)(66946007)(64756008)(14454004);DIR:OUT;SFP:1101;SCL:1;SRVR:BYAPR12MB3112;H:BYAPR12MB3158.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;MX:1;A:1;
received-spf: None (protection.outlook.com: amd.com does not designate
 permitted sender hosts)
x-ms-exchange-senderadcheck: 1
x-microsoft-antispam-message-info: 
 O/4ao9kRkY4g/Fngb0FIwa+Dbfrma6XteqAlz9WL+nc1H0o1x14+UdfFcpNkKEHF7AJHInh6znej3cMWhac6Z/5M9YgGwShys8EXd/08iCBQ/cCmUxG/mes3nEmvYNyX1YvSEjLxWneFV3uoyMiX8FfFJl9Jj5vtSHyKkAHFndt95o3wvPY/UnXm1tIh1YH06DvabuYb0iVZlMD0sewqbCjQonEEGoA45SeWjiQRXB8KN9IRIrE0gwgkPPPf9rL5SMuuiz8RV5YTf1YnA4ANzNi8+u7XqZ8y+LMzMIUwMtgVwCwn+pllJ/CKkFbwIUyNanpLEUKuKXYjruvBTsXmunNOuVBaQsVOfgFCV3Ryj9fAaL/42xdC8E1agR6V8aRSFrrJN0Ju2owlMnk4/6uWH5QnwXWwdM+qOe1R1UtTkzA=
MIME-Version: 1.0
X-OriginatorOrg: amd.com
X-MS-Exchange-CrossTenant-Network-Message-Id: 95c7682f-c74a-46a5-1008-08d724ed33a9
X-MS-Exchange-CrossTenant-originalarrivaltime: 19 Aug 2019 21:35:49.2079
 (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: wMHxAF5d5xGVDtzMf/p3SaSN985AWGJPtzuAk+NoUIYEjBi/GhuRvZR3THaVWI0cRMKnUmSHQBG0rZzX4y+Hww==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: BYAPR12MB3112
Content-Language: en-US
Content-Type: text/plain; charset="us-ascii"
Content-ID: <E35C8502A7149D489F954A216677B2DC@namprd12.prod.outlook.com>
Content-Transfer-Encoding: quoted-printable

From: Tom Lendacky <thomas.lendacky@amd.com>

When running as an SEV-ES guest in 32-bit mode, it is not possible to
perform a CPUID instruction because it will require communicating with
the hypervisor using the GHCB.  However, writes to the GHCB when in
32-bit mode will be will be encrypted and thus not able to be read
by the hypervisor.

To get around this, add an IDT entry for the #VC exception.  The #VC
handler will use the GHCB CPUID request/response protocol to obtain
the requested CPUID function values and provide these to the guest.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 OvmfPkg/ResetVector/ResetVector.inf       |   2 +
 OvmfPkg/ResetVector/Ia32/PageTables64.asm | 173 ++++++++++++++++++++++
 OvmfPkg/ResetVector/ResetVector.nasmb     |   1 +
 3 files changed, 176 insertions(+)

diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/Rese=
tVector.inf
index b0ddfa5832a2..960b47cd0797 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -35,3 +35,5 @@ [BuildOptions]
 [Pcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVecto=
r/Ia32/PageTables64.asm
index abad009f20f5..c6071fe934de 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -37,6 +37,15 @@ BITS    32
 ; If SEV is disabled then EAX will be zero.
 ;
 CheckSevFeature:
+    ;
+    ; Set up exception handlers to check for SEV-ES
+    ;   Load temporary RAM stack based on PCDs
+    ;   Establish exception handlers
+    ;
+    mov       esp, SEV_TOP_OF_STACK
+    mov       eax, ADDR_OF(idtr)
+    lidt      [cs:eax]
+
     ; Check if we have a valid (0x8000_001F) CPUID leaf
     mov       eax, 0x80000000
     cpuid
@@ -73,6 +82,15 @@ NoSev:
     xor       eax, eax
=20
 SevExit:
+    ;
+    ; Clear exception handlers and stack
+    ;
+    push      eax
+    mov       eax, ADDR_OF(idtr_clear)
+    lidt      [cs:eax]
+    pop       eax
+    mov       esp, 0
+
     OneTimeCallRet CheckSevFeature
=20
 ;
@@ -146,3 +164,158 @@ pageTableEntriesLoop:
     mov     cr3, eax
=20
     OneTimeCallRet SetCr3ForPageTables64
+
+SevEsIdtCommon:
+    hlt
+    jmp     SevEsIdtCommon
+    iret
+
+SevEsIdtVmmComm:
+    ;
+    ; If we're here, then we are an SEV-ES guest and this
+    ; was triggered by a CPUID instruction
+    ;
+    pop     ecx                     ; Error code
+    cmp     ecx, 0x72               ; Be sure it was CPUID
+    jne     SevEsIdtCommon
+
+    ;
+    ; Set up local variable room on the stack
+    ;   CPUID function      : + 28
+    ;   CPUID register      : + 24
+    ;   GHCB MSR (EAX)      : + 20
+    ;   GHCB MSR (EDX)      : + 16
+    ;   CPUID result (EDX)  : + 12
+    ;   CPUID result (ECX)  : + 8
+    ;   CPUID result (EBX)  : + 4
+    ;   CPUID result (EAX)  : + 0
+    sub     esp, 32
+
+    ; Save CPUID function and initial register request
+    mov     [esp + 28], eax
+    xor     eax, eax
+    mov     [esp + 24], eax
+
+    ; Save current GHCB MSR value
+    mov     ecx, 0xc0010130
+    rdmsr
+    mov     [esp + 20], eax
+    mov     [esp + 16], edx
+
+NextReg:
+    ;
+    ; Setup GHCB MSR
+    ;   GHCB_MSR[63:32] =3D CPUID function
+    ;   GHCB_MSR[31:30] =3D CPUID register
+    ;   GHCB_MSR[11:0]  =3D CPUID request protocol
+    ;
+    mov     eax, [esp + 24]
+    cmp     eax, 4
+    jge     VmmDone
+
+    shl     eax, 30
+    or      eax, 0x004
+    mov     edx, [esp + 28]
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    ; Issue VMGEXIT (rep; vmmcall)
+    db      0xf3
+    db      0x0f
+    db      0x01
+    db      0xd9
+
+    ;
+    ; Read GHCB MSR
+    ;   GHCB_MSR[63:32] =3D CPUID register value
+    ;   GHCB_MSR[31:30] =3D CPUID register
+    ;   GHCB_MSR[11:0]  =3D CPUID response protocol
+    ;
+    mov     ecx, 0xc0010130
+    rdmsr
+    mov     ecx, eax
+    and     ecx, 0xfff
+    cmp     ecx, 0x005
+    jne     SevEsIdtCommon
+
+    ; Save returned value
+    shr     eax, 30
+    and     eax, 0x3
+    shl     eax, 2
+    mov     ecx, esp
+    add     ecx, eax
+    mov     [ecx], edx
+
+    ; Next register
+    inc     word [esp + 24]
+
+    jmp     NextReg
+
+VmmDone:
+    ;
+    ; At this point we have all CPUID register values. Restore the GHCB MS=
R,
+    ; set the return register values and return.
+    ;
+    mov     eax, [esp + 20]
+    mov     edx, [esp + 16]
+    mov     ecx, 0xc0010130
+    wrmsr
+
+    mov     eax, [esp + 0]
+    mov     ebx, [esp + 4]
+    mov     ecx, [esp + 8]
+    mov     edx, [esp + 12]
+
+    add     esp, 32
+    add     word [esp], 2           ; Skip over the CPUID instruction
+    iret
+
+ALIGN   2
+
+idtr:
+    dw      IDT_END - IDT_BASE - 1  ; Limit
+    dd      ADDR_OF(IDT_BASE)       ; Base
+
+idtr_clear:
+    dw      0                       ; Limit
+    dd      0                       ; Base
+
+ALIGN   16
+
+;
+; The Interrupt Descriptor Table (IDT)
+;   This will be used to determine if SEV-ES is enabled.  Upon execution
+;   of the CPUID instruction, a VMM Communication Exception will occur.
+;   This will tell us if SEV-ES is enabled.  We can use the current value
+;   of the GHCB MSR to determine the SEV attributes.
+;
+IDT_BASE:
+;
+; Vectors 0 - 28
+;
+%rep 29
+    dw      (ADDR_OF(SevEsIdtCommon) & 0xffff)   ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GAT=
E_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtCommon) >> 16)      ; Offset high bits 31..16
+%endrep
+;
+; Vector 29 (VMM Communication Exception)
+;
+    dw      (ADDR_OF(SevEsIdtVmmComm) & 0xffff)  ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GAT=
E_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtVmmComm) >> 16)     ; Offset high bits 31..16
+;
+; Vectors 30 - 31
+;
+%rep 2
+    dw      (ADDR_OF(SevEsIdtCommon) & 0xffff)   ; Offset low bits 15..0
+    dw      0x10                                 ; Selector
+    db      0                                    ; Reserved
+    db      0x8E                                 ; Gate Type (IA32_IDT_GAT=
E_TYPE_INTERRUPT_32)
+    dw      (ADDR_OF(SevEsIdtCommon) >> 16)      ; Offset high bits 31..16
+%endrep
+IDT_END:
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/Re=
setVector.nasmb
index 75cfe16654b1..3b213cd05ab2 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -55,6 +55,7 @@
=20
   %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Off=
set))
 %include "Ia32/Flat32ToFlat64.asm"
+  %define SEV_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + Fix=
edPcdGet32 (PcdOvmfSecPeiTempRamSize))
 %include "Ia32/PageTables64.asm"
 %endif
=20
--=20
2.17.1