From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81473+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81473+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405208; cv=none; d=zohomail.com; s=zohoarc; b=ULz5DMjuxTk5kpWActeKdW69DNU47qLRPw2QXO9uxZUoD7A3TOguBfd7GhJquLMNla74s4ew7mLAvrJL0ZohB4V/GGJEgiUq9fX+j6HDWwbVVEcYWYEXPUX2sB3u29iEoLU2KeWBRmq8LT7imnMa7p85dRh9LbqVxOl2iypw21I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405208; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=/3k0LknmLshL+OajY8U64dvataCCSXnliYM8DKTqnf4=; b=Qi4Bp0XFO75IOusVCrVfCrNwj7F6EsoGy5lFT37BpALYBX0HxVwymMtQU3g/6S57ZnIWWLcmSYw+oQzCfKTuoU+JNRUEuifwrwBP0r4Pm2+pWoMeGc4RznCYT+NIBHmXxzbyQMuHphbYF70yY6qIpZlIs89/e4Hx3ob+nbYYfwk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81473+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405208227812.39876186345; Mon, 4 Oct 2021 20:40:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id oIiyYY1788612xiSIDLFSsnc; Mon, 04 Oct 2021 20:40:07 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web10.20841.1633405206053665988 for ; Mon, 04 Oct 2021 20:40:07 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958018" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958018" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:05 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828408" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:04 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu Subject: [edk2-devel] [PATCH V2 01/28] OvmfPkg: Copy Main.asm from UefiCpuPkg to OvmfPkg's ResetVector Date: Tue, 5 Oct 2021 11:39:12 +0800 Message-Id: <70b957fb3ffa545aecf3108c8ac3e4b57d9d4034.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: XDQTRkTuTvg4rp4WM5DvLUPmx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405207; bh=rvLF3I4uHbtk/ZqE1Rorvxlpd4slB4k6ex05LD7kNRo=; h=Cc:Date:From:Reply-To:Subject:To; b=Rx3BbP/z6GHfhxyTyZvQa5833MRRvmXefl9Ri086JSJPg2UsWYJlZ0J2gSbPiUv8Oh1 IPID8TOhOzfitvQNEOynluZ+FsNG46qeqJ4Xs0VxH10gHz6/RR9RSNRqvoxHXcTOZ32U1 eKBGchwTytxdkyRHNmjTIFXMiqtCl1+dB6c= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405209545100001 Content-Type: text/plain; charset="utf-8" Signed-off-by: Min Xu --- OvmfPkg/ResetVector/Main.asm | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 OvmfPkg/ResetVector/Main.asm diff --git a/OvmfPkg/ResetVector/Main.asm b/OvmfPkg/ResetVector/Main.asm new file mode 100644 index 000000000000..ae90a148fce7 --- /dev/null +++ b/OvmfPkg/ResetVector/Main.asm @@ -0,0 +1,103 @@ +;-------------------------------------------------------------------------= ----- +; @file +; Main routine of the pre-SEC code up through the jump into SEC +; +; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;-------------------------------------------------------------------------= ----- + + +BITS 16 + +; +; Modified: EBX, ECX, EDX, EBP +; +; @param[in,out] RAX/EAX Initial value of the EAX register +; (BIST: Built-in Self Test) +; @param[in,out] DI 'BP': boot-strap processor, or +; 'AP': application processor +; @param[out] RBP/EBP Address of Boot Firmware Volume (BFV) +; @param[out] DS Selector allowing flat access to all addresses +; @param[out] ES Selector allowing flat access to all addresses +; @param[out] FS Selector allowing flat access to all addresses +; @param[out] GS Selector allowing flat access to all addresses +; @param[out] SS Selector allowing flat access to all addresses +; +; @return None This routine jumps to SEC and does not return +; +Main16: + OneTimeCall EarlyInit16 + + ; + ; Transition the processor from 16-bit real mode to 32-bit flat mode + ; + OneTimeCall TransitionFromReal16To32BitFlat + +BITS 32 + + ; + ; Search for the Boot Firmware Volume (BFV) + ; + OneTimeCall Flat32SearchForBfvBase + + ; + ; EBP - Start of BFV + ; + + ; + ; Search for the SEC entry point + ; + OneTimeCall Flat32SearchForSecEntryPoint + + ; + ; ESI - SEC Core entry point + ; EBP - Start of BFV + ; + +%ifdef ARCH_IA32 + + ; + ; Restore initial EAX value into the EAX register + ; + mov eax, esp + + ; + ; Jump to the 32-bit SEC entry point + ; + jmp esi + +%else + + ; + ; Transition the processor from 32-bit flat mode to 64-bit flat mode + ; + OneTimeCall Transition32FlatTo64Flat + +BITS 64 + + ; + ; Some values were calculated in 32-bit mode. Make sure the upper + ; 32-bits of 64-bit registers are zero for these values. + ; + mov rax, 0x00000000ffffffff + and rsi, rax + and rbp, rax + and rsp, rax + + ; + ; RSI - SEC Core entry point + ; RBP - Start of BFV + ; + + ; + ; Restore initial EAX value into the RAX register + ; + mov rax, rsp + + ; + ; Jump to the 64-bit SEC entry point + ; + jmp rsi + +%endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81473): https://edk2.groups.io/g/devel/message/81473 Mute This Topic: https://groups.io/mt/86085721/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81474+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81474+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405208; cv=none; d=zohomail.com; s=zohoarc; b=BRmX3E0ATtKF9fGQ4BBBsQy00THgD6XV7riS7xRna6UlAaQVEWnf0Ki8T+oq8n+JDne3u2fmuLrpSgEyOl5HCTJYunnzRnZyNNP871vwfjJ0n9kcPXfJKTLj0T9NTwDGwR3ikL4QdVmvM4qs86W25Ie49PYe7480hRyTOLYVj8Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405208; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=GuqTuPsTq+IWLXHH+DS+HoiSfemKDvtN8fKpfuNVgtQ=; b=bfypWEVg78vaROimNnSH/B76hshWeGOuHJp30LIV//OcxbMtK1HxdRl6tfTOrqBbjRAfW4m6vYZE3WCavX+ftVYf0AZrR6tcXES/ypMK3XvMZYmMajCELEJ8OzzOCrVaumfsZYtykfSh46sfz79uM3kL6y6IaNGpycofMcxR8O8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81474+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405208921574.4856785356201; Mon, 4 Oct 2021 20:40:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id feSfYY1788612xAKIvnyjylB; Mon, 04 Oct 2021 20:40:08 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web10.20841.1633405206053665988 for ; Mon, 04 Oct 2021 20:40:08 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958020" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958020" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:06 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828419" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:05 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu Subject: [edk2-devel] [PATCH V2 02/28] OvmfPkg: Enable TDX in ResetVector Date: Tue, 5 Oct 2021 11:39:13 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: Jgx1MJ8G4jMI2TJbFOZFOzanx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405208; bh=RLqfzdqhVF4j+daXj660NplxEVx3jswIKNC188Kimz0=; h=Cc:Date:From:Reply-To:Subject:To; b=XhChvS+5hlFzmpUmWN2Bp+2n7krEww75jTmEEm4tdraNMsCmca1W3eItXzXl6B6ckIS yvj5uTrmlD1PwKU7S9Zdi6iSM1hVqcuPub/45LA3u/1XpHZfX6NvGFEWjM3k4doUqSP0x sb/Tv5i6OR8j7XWLrAOwUprAJ01FTT2qGNg= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405209640100005 Content-Type: text/plain; charset="utf-8" Signed-off-by: Min Xu --- OvmfPkg/OvmfPkg.dec | 9 + OvmfPkg/OvmfPkgDefines.fdf.inc | 9 + OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm | 39 +++ OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm | 11 + OvmfPkg/ResetVector/Ia32/IntelTdx.asm | 235 +++++++++++++++++++ OvmfPkg/ResetVector/Ia32/PageTables64.asm | 21 +- OvmfPkg/ResetVector/Main.asm | 16 ++ OvmfPkg/ResetVector/ResetVector.inf | 9 + OvmfPkg/ResetVector/ResetVector.nasmb | 40 +++- OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm | 102 ++++++++ 10 files changed, 484 insertions(+), 7 deletions(-) create mode 100644 OvmfPkg/ResetVector/Ia32/IntelTdx.asm create mode 100644 OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 1be8d5dccbc7..340d83f794d0 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -340,6 +340,15 @@ # header definition. gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentialComputingWorkAreaHeader|4|= UINT32|0x51 =20 + ## The base address and size of the TDX Cfv base and size. + gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase|0|UINT32|0x52 + gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataOffset|0|UINT32|0x53 + gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize|0|UINT32|0x54 + + ## The base address and size of the TDX Bfv base and size. + gUefiOvmfPkgTokenSpaceGuid.PcdBfvBase|0|UINT32|0x55 + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset|0|UINT32|0x56 + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize|0|UINT32|0x57 =20 [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 diff --git a/OvmfPkg/OvmfPkgDefines.fdf.inc b/OvmfPkg/OvmfPkgDefines.fdf.inc index 3b5e45253916..6170c5993ce5 100644 --- a/OvmfPkg/OvmfPkgDefines.fdf.inc +++ b/OvmfPkg/OvmfPkgDefines.fdf.inc @@ -9,6 +9,7 @@ ## =20 DEFINE BLOCK_SIZE =3D 0x1000 +DEFINE VARS_OFFSET =3D 0 =20 # # A firmware binary built with FD_SIZE_IN_KB=3D1024, and a firmware binary= built @@ -88,6 +89,14 @@ SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwS= pareSize =3D $(VARS_SPARE_ # Computing Work Area header defined in the Include/WorkArea.h SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentialComputingWorkAreaHeader = =3D 4 =20 +SET gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase =3D $(FW_BASE_ADDRESS) +SET gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataOffset =3D $(VARS_OFFSET) +SET gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize =3D $(VARS_SIZE) + +SET gUefiOvmfPkgTokenSpaceGuid.PcdBfvBase =3D $(CODE_BASE_ADDRES= S) +SET gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset =3D $(VARS_SIZE) +SET gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize =3D $(CODE_SIZE) + !if $(SMM_REQUIRE) =3D=3D TRUE SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 =3D gUe= fiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase =3D gUe= fiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase diff --git a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/OvmfPkg/ResetVe= ctor/Ia16/ResetVectorVtf0.asm index 7ec3c6e980c3..76bc3aa00735 100644 --- a/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm +++ b/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm @@ -47,6 +47,25 @@ TIMES (15 - ((guidedStructureEnd - guidedStructureStart = + 15) % 16)) DB 0 ; guidedStructureStart: =20 +%ifdef ARCH_X64 +; +; TDX Metadata offset block +; +; TdxMetadata.asm is included in ARCH_X64 because Inte TDX is only +; available in ARCH_X64. Below block describes the offset of +; TdxMetadata block in Ovmf image +; +; GUID : e47a6535-984a-4798-865e-4685a7bf8ec2 +; +tdxMetadataOffsetStart: + DD tdxMetadataOffsetStart - TdxMetadataGuid - 16 + DW tdxMetadataOffsetEnd - tdxMetadataOffsetStart + DB 0x35, 0x65, 0x7a, 0xe4, 0x4a, 0x98, 0x98, 0x47 + DB 0x86, 0x5e, 0x46, 0x85, 0xa7, 0xbf, 0x8e, 0xc2 +tdxMetadataOffsetEnd: + +%endif + ; SEV Hash Table Block ; ; This describes the guest ram area where the hypervisor should @@ -158,10 +177,30 @@ resetVector: ; ; This is where the processor will begin execution ; +; In IA32 we follow the standard reset vector flow. While in X64, Td guest +; may be supported. Td guest requires the startup mode to be 32-bit +; protected mode but the legacy VM startup mode is 16-bit real mode. +; To make NASM generate such shared entry code that behaves correctly in +; both 16-bit and 32-bit mode, more BITS directives are added. +; +%ifdef ARCH_IA32 nop nop jmp EarlyBspInitReal16 =20 +%else + + mov eax, cr0 + test al, 1 + jz .Real +BITS 32 + jmp Main32 +BITS 16 +.Real: + jmp EarlyBspInitReal16 + +%endif + ALIGN 16 =20 fourGigabytes: diff --git a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/ResetVec= tor/Ia32/Flat32ToFlat64.asm index c6d0d898bcd1..eb3546668ef8 100644 --- a/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm +++ b/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm @@ -21,6 +21,17 @@ Transition32FlatTo64Flat: bts eax, 5 ; enable PAE mov cr4, eax =20 + ; + ; In TDX LME has already been set. So we're done and jump to enable + ; paging directly if Tdx is enabled. + ; EBX is cleared because in the later it will be used to check if + ; the second step of the SEV-ES mitigation is to be performed. + ; + xor ebx, ebx + OneTimeCall IsTdxEnabled + test eax, eax + jnz EnablePaging + mov ecx, 0xc0000080 rdmsr bts eax, 8 ; set LME diff --git a/OvmfPkg/ResetVector/Ia32/IntelTdx.asm b/OvmfPkg/ResetVector/Ia= 32/IntelTdx.asm new file mode 100644 index 000000000000..f67b1bcf0b2e --- /dev/null +++ b/OvmfPkg/ResetVector/Ia32/IntelTdx.asm @@ -0,0 +1,235 @@ +;-------------------------------------------------------------------------= ----- +; @file +; Intel TDX routines +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;-------------------------------------------------------------------------= ----- + +%define SEC_DEFAULT_CR0 0x00000023 +%define SEC_DEFAULT_CR4 0x640 +%define VM_GUEST_TDX 2 + +BITS 32 + +; +; Check if it is Intel Tdx +; +; Modified: EAX, EBX, ECX, EDX +; +; If it is Intel Tdx, EAX is 1 +; If it is not Intel Tdx, EAX is 0 +; +IsTdx: + ; + ; CPUID (0) + ; + mov eax, 0 + cpuid + cmp ebx, 0x756e6547 ; "Genu" + jne IsNotTdx + cmp edx, 0x49656e69 ; "ineI" + jne IsNotTdx + cmp ecx, 0x6c65746e ; "ntel" + jne IsNotTdx + + ; + ; CPUID (1) + ; + mov eax, 1 + cpuid + test ecx, 0x80000000 + jz IsNotTdx + + ; + ; CPUID[0].EAX >=3D 0x21? + ; + mov eax, 0 + cpuid + cmp eax, 0x21 + jl IsNotTdx + + ; + ; CPUID (0x21,0) + ; + mov eax, 0x21 + mov ecx, 0 + cpuid + + cmp ebx, 0x65746E49 ; "Inte" + jne IsNotTdx + cmp edx, 0x5844546C ; "lTDX" + jne IsNotTdx + cmp ecx, 0x20202020 ; " " + jne IsNotTdx + + mov eax, 1 + jmp ExitIsTdx + +IsNotTdx: + xor eax, eax + +ExitIsTdx: + + OneTimeCallRet IsTdx + +; +; Initialize work area if it is Tdx guest. Detailed definition is in +; OvmfPkg/Include/WorkArea.h. +; BSP and APs all go here. Only BSP initialize this work area. +; +; Param[in] EBP[5:0] CPU Supported GPAW (48 or 52) +; Param[in] ESI[31:0] vCPU ID (BSP is 0, others are AP) +; +; Modified: EBP +; +InitTdxWorkarea: + + ; + ; First check if it is Tdx + ; + OneTimeCall IsTdx + + test eax, eax + jz ExitInitTdxWorkarea + + cmp esi, 0 + je TdxBspEntry + + ; + ; In Td guest, BSP/AP shares the same entry point + ; BSP builds up the page table, while APs shouldn't do the same task. + ; Instead, APs just leverage the page table which is built by BSP. + ; APs will wait until the page table is ready. + ; +TdxApWait: + cmp byte[TDX_WORK_AREA_PGTBL_READY], 0 + je TdxApWait + jmp ExitInitTdxWorkarea + +TdxBspEntry: + ; + ; Set Type of WORK_AREA_GUEST_TYPE so that the following code can use + ; these information. + ; + mov byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX + + ; + ; EBP[5:0] CPU supported GPA width + ; + and ebp, 0x3f + mov DWORD[TDX_WORK_AREA_GPAW], ebp + +ExitInitTdxWorkarea: + OneTimeCallRet InitTdxWorkarea + +; +; Load the GDT and set the CR0. +; +; Modified: EAX, EBX, CR0, CR4, DS, ES, FS, GS, SS, CS +; +ReloadFlat32: + + cli + mov ebx, ADDR_OF(gdtr) + lgdt [ebx] + + mov eax, SEC_DEFAULT_CR0 + mov cr0, eax + + jmp LINEAR_CODE_SEL:dword ADDR_OF(jumpToFlat32BitAndLandHere) + +jumpToFlat32BitAndLandHere: + + mov eax, SEC_DEFAULT_CR4 + mov cr4, eax + + debugShowPostCode POSTCODE_32BIT_MODE + + mov ax, LINEAR_SEL + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + OneTimeCallRet ReloadFlat32 + +; +; Tdx initialization after entering into ResetVector +; +; Modified: EAX, EBX, ECX, EDX, EBP, EDI, ESP +; +InitTdx: + ; + ; Save EBX in EBP because EBX will be changed in ReloadFlat32 + ; + mov ebp, ebx + + ; + ; First load the GDT and jump to Flat32 mode + ; + OneTimeCall ReloadFlat32 + + ; + ; Initialization of Tdx work area + ; + OneTimeCall InitTdxWorkarea + + OneTimeCallRet InitTdx + +; +; Check TDX features, TDX or TDX-BSP or TDX-APs? +; +; By design TDX BSP is reponsible for initializing the PageTables. +; After PageTables are ready, byte[TDX_WORK_AREA_PGTBL_READY] is set to 1. +; APs will spin when byte[TDX_WORK_AREA_PGTBL_READY] is 0 until it is set = to 1. +; +; When this routine is run on TDX BSP, byte[TDX_WORK_AREA_PGTBL_READY] sho= uld be 0. +; When this routine is run on TDX APs, byte[TDX_WORK_AREA_PGTBL_READY] sho= uld be 1. +; +; +; Modified: EAX, EDX +; +; 0-NonTdx, 1-TdxBsp, 2-TdxAps +; +CheckTdxFeaturesBeforeBuildPagetables: + xor eax, eax + cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX + jne NotTdx + + xor edx, edx + mov al, byte[TDX_WORK_AREA_PGTBL_READY] + inc eax + +NotTdx: + OneTimeCallRet CheckTdxFeaturesBeforeBuildPagetables + +; +; Set byte[TDX_WORK_AREA_PGTBL_READY] to 1 +; +TdxPostBuildPageTables: + cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX + jne ExitTdxPostBuildPageTables + mov byte[TDX_WORK_AREA_PGTBL_READY], 1 + +ExitTdxPostBuildPageTables: + OneTimeCallRet TdxPostBuildPageTables + +; +; Check if TDX is enabled +; +; Modified: EAX +; +; If TDX is enabled then EAX will be 1 +; If TDX is disabled then EAX will be 0. +; +IsTdxEnabled: + xor eax, eax + cmp byte[WORK_AREA_GUEST_TYPE], VM_GUEST_TDX + jne TdxNotEnabled + mov eax, 1 + +TdxNotEnabled: + OneTimeCallRet IsTdxEnabled diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVecto= r/Ia32/PageTables64.asm index 07b6ca070909..dc640dd2bf58 100644 --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm @@ -37,14 +37,23 @@ BITS 32 PAGE_READ_WRITE + \ PAGE_PRESENT) =20 +%define TDX_BSP 1 +%define TDX_AP 2 + ; ; Modified: EAX, EBX, ECX, EDX ; SetCr3ForPageTables64: - - ; Clear the WorkArea header. The SEV probe routines will populate the - ; work area when detected. - mov byte[WORK_AREA_GUEST_TYPE], 0 + ; Check the TDX features. + ; If it is TDX APs, then jump to SetCr3 directly. + ; In TD guest the initialization is done by BSP, including building + ; the page tables. APs will spin on until byte[TDX_WORK_AREA_PGTBL_REA= DY] + ; is set. + OneTimeCall CheckTdxFeaturesBeforeBuildPagetables + cmp eax, TDX_BSP + je ClearOvmfPageTables + cmp eax, TDX_AP + je SetCr3 =20 ; Check whether the SEV is active and populate the SevEsWorkArea OneTimeCall CheckSevFeatures @@ -54,6 +63,7 @@ SetCr3ForPageTables64: ; the page table build below. OneTimeCall GetSevCBitMaskAbove31 =20 +ClearOvmfPageTables: ; ; For OVMF, build some initial page tables at ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000). @@ -105,6 +115,9 @@ pageTableEntriesLoop: ; Clear the C-bit from the GHCB page if the SEV-ES is enabled. OneTimeCall SevClearPageEncMaskForGhcbPage =20 + ; Set byte[TDX_WORK_AREA_PGTBL_READY] if TDX is enabled. + OneTimeCall TdxPostBuildPageTables + SetCr3: ; ; Set CR3 now that the paging structures are available diff --git a/OvmfPkg/ResetVector/Main.asm b/OvmfPkg/ResetVector/Main.asm index ae90a148fce7..2a7efbc48a2a 100644 --- a/OvmfPkg/ResetVector/Main.asm +++ b/OvmfPkg/ResetVector/Main.asm @@ -35,7 +35,23 @@ Main16: OneTimeCall TransitionFromReal16To32BitFlat =20 BITS 32 +%ifdef ARCH_X64 =20 + ; Clear the WorkArea header. The SEV probe routines will populate the + ; work area when detected. + mov byte[WORK_AREA_GUEST_TYPE], 0 + + jmp SearchBfv + +; +; Entry point of Main32 +; +Main32: + OneTimeCall InitTdx + +SearchBfv: + +%endif ; ; Search for the Boot Firmware Volume (BFV) ; diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/Rese= tVector.inf index a2520dde5508..320e5f2c6527 100644 --- a/OvmfPkg/ResetVector/ResetVector.inf +++ b/OvmfPkg/ResetVector/ResetVector.inf @@ -44,6 +44,15 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize + gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase + gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataOffset + gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize + gUefiOvmfPkgTokenSpaceGuid.PcdBfvBase + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset + gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize =20 [FixedPcd] gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/Re= setVector.nasmb index d1d800c56745..5f30d099a7f1 100644 --- a/OvmfPkg/ResetVector/ResetVector.nasmb +++ b/OvmfPkg/ResetVector/ResetVector.nasmb @@ -67,8 +67,39 @@ %error "This implementation inherently depends on PcdOvmfSecGhcbBase n= ot straddling a 2MB boundary" %endif =20 + %define TDX_BFV_RAW_DATA_OFFSET FixedPcdGet32 (PcdBfvRawDataOffset) + %define TDX_BFV_RAW_DATA_SIZE FixedPcdGet32 (PcdBfvRawDataSize) + %define TDX_BFV_MEMORY_BASE FixedPcdGet32 (PcdBfvBase) + %define TDX_BFV_MEMORY_SIZE FixedPcdGet32 (PcdBfvRawDataSize) + + %define TDX_CFV_RAW_DATA_OFFSET FixedPcdGet32 (PcdCfvRawDataOffset) + %define TDX_CFV_RAW_DATA_SIZE FixedPcdGet32 (PcdCfvRawDataSize) + %define TDX_CFV_MEMORY_BASE FixedPcdGet32 (PcdCfvBase), + %define TDX_CFV_MEMORY_SIZE FixedPcdGet32 (PcdCfvRawDataSize), + + %define TDX_HEAP_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecPeiTempRamBas= e) + %define TDX_HEAP_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecPeiTempRamSiz= e) / 2 + + %define TDX_STACK_MEMORY_BASE (TDX_HEAP_MEMORY_BASE + TDX_HEAP_MEMOR= Y_SIZE) + %define TDX_STACK_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecPeiTempRamSiz= e) / 2 + + %define TDX_HOB_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecGhcbBase) + %define TDX_HOB_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecGhcbSize) + + %define TDX_MAILBOX_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecGhcbBackupBas= e) + %define TDX_MAILBOX_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecGhcbBackupSiz= e) + + %define OVMF_PAGE_TABLE_BASE FixedPcdGet32 (PcdOvmfSecPageTablesBas= e) + %define OVMF_PAGE_TABLE_SIZE FixedPcdGet32 (PcdOvmfSecPageTablesSiz= e) + + %define TDX_WORK_AREA_PGTBL_READY (FixedPcdGet32 (PcdOvmfWorkAreaBase) += 4) + %define TDX_WORK_AREA_GPAW (FixedPcdGet32 (PcdOvmfWorkAreaBase) += 8) + %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Off= set)) =20 + %define OVMF_WORK_AREA_BASE (FixedPcdGet32 (PcdOvmfWorkAreaBase)) + %define OVMF_WORK_AREA_SIZE (FixedPcdGet32 (PcdOvmfWorkAreaSize)) + %define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase)) %define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase)) %define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize)) @@ -77,9 +108,12 @@ %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + = 8) %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) = + 16) %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase)= + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) -%include "Ia32/Flat32ToFlat64.asm" -%include "Ia32/AmdSev.asm" -%include "Ia32/PageTables64.asm" + + %include "X64/IntelTdxMetadata.asm" + %include "Ia32/Flat32ToFlat64.asm" + %include "Ia32/AmdSev.asm" + %include "Ia32/PageTables64.asm" + %include "Ia32/IntelTdx.asm" %endif =20 %include "Ia16/Real16ToFlat32.asm" diff --git a/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm b/OvmfPkg/ResetVe= ctor/X64/IntelTdxMetadata.asm new file mode 100644 index 000000000000..18e10931bbc2 --- /dev/null +++ b/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm @@ -0,0 +1,102 @@ +;-------------------------------------------------------------------------= ----- +; @file +; Tdx Virtual Firmware metadata +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;-------------------------------------------------------------------------= ----- + +BITS 64 + +%define TDX_METADATA_SECTION_TYPE_BFV 0 +%define TDX_METADATA_SECTION_TYPE_CFV 1 +%define TDX_METADATA_SECTION_TYPE_TD_HOB 2 +%define TDX_METADATA_SECTION_TYPE_TEMP_MEM 3 +%define TDX_METADATA_VERSION 1 +%define TDX_METADATA_ATTRIBUTES_EXTENDMR 0x00000001 + +ALIGN 16 +TIMES (15 - ((TdxGuidedStructureEnd - TdxGuidedStructureStart + 15) % 16))= DB 0 + +TdxGuidedStructureStart: + +; +; TDVF meta data +; +TdxMetadataGuid: + DB 0xf3, 0xf9, 0xea, 0xe9, 0x8e, 0x16, 0xd5, 0x44 + DB 0xa8, 0xeb, 0x7f, 0x4d, 0x87, 0x38, 0xf6, 0xae + +_Descriptor: + DB 'T','D','V','F' ; Signature + DD TdxGuidedStructureEnd - _Descriptor ; Length + DD TDX_METADATA_VERSION ; Version + DD (TdxGuidedStructureEnd - _Descriptor - 16)/32 ; Number of sections + +_Bfv: + DD TDX_BFV_RAW_DATA_OFFSET + DD TDX_BFV_RAW_DATA_SIZE + DQ TDX_BFV_MEMORY_BASE + DQ TDX_BFV_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_BFV + DD TDX_METADATA_ATTRIBUTES_EXTENDMR + +_Cfv: + DD TDX_CFV_RAW_DATA_OFFSET + DD TDX_CFV_RAW_DATA_SIZE + DQ TDX_CFV_MEMORY_BASE + DQ TDX_CFV_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_CFV + DD 0 + +_Stack: + DD 0 + DD 0 + DQ TDX_STACK_MEMORY_BASE + DQ TDX_STACK_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_TEMP_MEM + DD 0 + +_Heap: + DD 0 + DD 0 + DQ TDX_HEAP_MEMORY_BASE + DQ TDX_HEAP_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_TEMP_MEM + DD 0 + +_MailBox: + DD 0 + DD 0 + DQ TDX_MAILBOX_MEMORY_BASE + DQ TDX_MAILBOX_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_TEMP_MEM + DD 0 + +_OvmfWorkarea: + DD 0 + DD 0 + DQ OVMF_WORK_AREA_BASE + DQ OVMF_WORK_AREA_SIZE + DD TDX_METADATA_SECTION_TYPE_TEMP_MEM + DD 0 + +_TdHob: + DD 0 + DD 0 + DQ TDX_HOB_MEMORY_BASE + DQ TDX_HOB_MEMORY_SIZE + DD TDX_METADATA_SECTION_TYPE_TD_HOB + DD 0 + +_OvmfPageTable: + DD 0 + DD 0 + DQ OVMF_PAGE_TABLE_BASE + DQ OVMF_PAGE_TABLE_SIZE + DD TDX_METADATA_SECTION_TYPE_TEMP_MEM + DD 0 + +TdxGuidedStructureEnd: +ALIGN 16 --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81474): https://edk2.groups.io/g/devel/message/81474 Mute This Topic: https://groups.io/mt/86085722/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81475+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81475+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405209; cv=none; d=zohomail.com; s=zohoarc; b=bpBtvZ9PwUYiciNSJTyASTDmY7gmKnexWSXzYG59++rxRcBVV/Mt2r7+x/X4pvq1/EKy6jkv5RWXUHHjTsNXRMe15QTjQtXS4p4PzOCMmLGrBO39dKWETZUTtZX/tLRCrYLck5aHIJHTA8wqi/Wj49suG+QrLnGqr5DdRthdc1o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405209; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=uOe+S0HjaPtcitWOMu91S31viguGCiYEBSM7gvDNJhI=; b=M3Ddbq0tkgfgfUlupquMPm/asNLJu8/k7hOV6kl36m81gE9VlLRvIWXN0S2/s1u457vkttqI+wO3Wt/HXq6zjktdySp7Ojj1vys8dnLH69neythr0sxVPpwk62L6pY4x164bk8Ycbnuyse+A9x5R6k7hwQ6v5H1NjuqiBDKITzo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81475+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405209837346.85734039223496; Mon, 4 Oct 2021 20:40:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id I92UYY1788612xEvQvOwcQ16; Mon, 04 Oct 2021 20:40:09 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20666.1633405208299274124 for ; Mon, 04 Oct 2021 20:40:08 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958025" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958025" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:07 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828428" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:06 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu Subject: [edk2-devel] [PATCH V2 03/28] OvmfPkg: Merge TEMP_MEM entries in Tdx metadata Date: Tue, 5 Oct 2021 11:39:14 +0800 Message-Id: <7cdee1fdfeef9c154b64d7834cfdec724985252a.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: tSeN95axDe5IAZ9vZDoWgZ15x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405209; bh=sS6mRNZsjs3MCyxsuaCH2nkWnPyz3CVGHw6YaAbwo9I=; h=Cc:Date:From:Reply-To:Subject:To; b=UUmUBaEz1buh9/QZftaJUwbn1QU7G5gMCazqdb18LvciqJdbdBtqB53M+NMhqQoHzQ+ HXVNy+/GzJE3lUe7KONPGtsK1G+npU86tiE5kwXENa5VL4hm7V90I5tQZ0G5q8RhpZLH0 +eN/zUCClqTp2Z5xM/wv0aWx58TMTEkhc0Q= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405211662100014 Content-Type: text/plain; charset="utf-8" Signed-off-by: Min Xu --- OvmfPkg/ResetVector/ResetVector.nasmb | 13 ++++----- OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm | 28 +++++--------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/Re= setVector.nasmb index 5f30d099a7f1..bf1ed8228133 100644 --- a/OvmfPkg/ResetVector/ResetVector.nasmb +++ b/OvmfPkg/ResetVector/ResetVector.nasmb @@ -77,21 +77,18 @@ %define TDX_CFV_MEMORY_BASE FixedPcdGet32 (PcdCfvBase), %define TDX_CFV_MEMORY_SIZE FixedPcdGet32 (PcdCfvRawDataSize), =20 - %define TDX_HEAP_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecPeiTempRamBas= e) - %define TDX_HEAP_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecPeiTempRamSiz= e) / 2 - - %define TDX_STACK_MEMORY_BASE (TDX_HEAP_MEMORY_BASE + TDX_HEAP_MEMOR= Y_SIZE) - %define TDX_STACK_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecPeiTempRamSiz= e) / 2 + %define TDX_HEAP_STACK_BASE FixedPcdGet32 (PcdOvmfSecPeiTempRamBas= e) + %define TDX_HEAP_STACK_SIZE FixedPcdGet32 (PcdOvmfSecPeiTempRamSiz= e) =20 %define TDX_HOB_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecGhcbBase) %define TDX_HOB_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecGhcbSize) =20 - %define TDX_MAILBOX_MEMORY_BASE FixedPcdGet32 (PcdOvmfSecGhcbBackupBas= e) - %define TDX_MAILBOX_MEMORY_SIZE FixedPcdGet32 (PcdOvmfSecGhcbBackupSiz= e) - %define OVMF_PAGE_TABLE_BASE FixedPcdGet32 (PcdOvmfSecPageTablesBas= e) %define OVMF_PAGE_TABLE_SIZE FixedPcdGet32 (PcdOvmfSecPageTablesSiz= e) =20 + %define TDX_INIT_MEMORY_BASE FixedPcdGet32 (PcdOvmfWorkAreaBase) + %define TDX_INIT_MEMORY_SIZE (FixedPcdGet32 (PcdOvmfWorkAreaSize) += FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) + %define TDX_WORK_AREA_PGTBL_READY (FixedPcdGet32 (PcdOvmfWorkAreaBase) += 4) %define TDX_WORK_AREA_GPAW (FixedPcdGet32 (PcdOvmfWorkAreaBase) += 8) =20 diff --git a/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm b/OvmfPkg/ResetVe= ctor/X64/IntelTdxMetadata.asm index 18e10931bbc2..dd66b468c5c6 100644 --- a/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm +++ b/OvmfPkg/ResetVector/X64/IntelTdxMetadata.asm @@ -50,35 +50,19 @@ _Cfv: DD TDX_METADATA_SECTION_TYPE_CFV DD 0 =20 -_Stack: +_TdxHeapStack: DD 0 DD 0 - DQ TDX_STACK_MEMORY_BASE - DQ TDX_STACK_MEMORY_SIZE + DQ TDX_HEAP_STACK_BASE + DQ TDX_HEAP_STACK_SIZE DD TDX_METADATA_SECTION_TYPE_TEMP_MEM DD 0 =20 -_Heap: +_TdxInitMem: DD 0 DD 0 - DQ TDX_HEAP_MEMORY_BASE - DQ TDX_HEAP_MEMORY_SIZE - DD TDX_METADATA_SECTION_TYPE_TEMP_MEM - DD 0 - -_MailBox: - DD 0 - DD 0 - DQ TDX_MAILBOX_MEMORY_BASE - DQ TDX_MAILBOX_MEMORY_SIZE - DD TDX_METADATA_SECTION_TYPE_TEMP_MEM - DD 0 - -_OvmfWorkarea: - DD 0 - DD 0 - DQ OVMF_WORK_AREA_BASE - DQ OVMF_WORK_AREA_SIZE + DQ TDX_INIT_MEMORY_BASE + DQ TDX_INIT_MEMORY_SIZE DD TDX_METADATA_SECTION_TYPE_TEMP_MEM DD 0 =20 --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81475): https://edk2.groups.io/g/devel/message/81475 Mute This Topic: https://groups.io/mt/86085724/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81476+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81476+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405210; cv=none; d=zohomail.com; s=zohoarc; b=aT9pabFv1z9ezdaKjbG3kCCXK197Vq7c8JRN1lvVyyjMZkEB0Dgq/4h5QytTPl2l6i+tEzQORR9gslOTTWkV07Hoh4wd3pzHQctgKeccsxyvAjYS7WYI4l4DbZub9flAW5imPwlrrh2ns2B7JpxWRDHHWICwFfzDbVaRU2vUIPU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405210; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=X0uPPi/KC+FJR7hZrzqx2ON9cdghppp33G0je8Ro5lE=; b=HfWCDIOyd2pUDOfC3IDLYb2N3Ztqao16+YWAQ7TAy/5xaYX0ZeFFk4KuXFNmPgsfIu2G9ATF/Q/wMICoKlv3kWGLyKvIgz7qh4aNiAlWpRv75B/mqigLwBcizIiZGp6sCC5dbv+QSLHKg3Wc20r+xe+2SgI7795+r4F6xRMee4U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81476+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 163340521084377.04049362570754; Mon, 4 Oct 2021 20:40:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id QqfSYY1788612xHYSpuWz6Vv; Mon, 04 Oct 2021 20:40:10 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:10 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958045" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958045" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:09 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828439" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:07 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Michael D Kinney , Liming Gao , Zhiguang Liu , Jiewen Yao Subject: [edk2-devel] [PATCH V2 04/28] MdePkg: Add Tdx.h Date: Tue, 5 Oct 2021 11:39:15 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 2xMk6LYXzZnG729845UoYYO8x1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405210; bh=sZjm8DBoOm+OluAUELndXO1toWk0LpK4R4sMqIA31Lg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=fMka5LxWSIxMXzNqp9hMBUAUEL7MQaPjGFwtZKhpuNeq1Cy2poyjVyqWihX5jMTXhKa PJvNDSvUrK0yKqsUQpdB3aMMso7tOunPpDjdIyRY1pnmYCAqRitWDPLnNu3FLPbaqIQfP wmZH80mnAxzISkyQxymBZr9zndqELSwsoNE= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405211702100015 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Tdx.h includes the Intel Trust Domain Extension definitions. Detailed information can be found in below document: https://software.intel.com/content/dam/develop/external/us/en/ documents/tdx-module-1eas-v0.85.039.pdf Cc: Michael D Kinney Cc: Liming Gao Cc: Zhiguang Liu Cc: Jiewen Yao Signed-off-by: Min Xu Acked-by: Gerd Hoffmann --- MdePkg/Include/IndustryStandard/Tdx.h | 203 ++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 MdePkg/Include/IndustryStandard/Tdx.h diff --git a/MdePkg/Include/IndustryStandard/Tdx.h b/MdePkg/Include/Industr= yStandard/Tdx.h new file mode 100644 index 000000000000..11b3d3345de3 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/Tdx.h @@ -0,0 +1,203 @@ +/** @file + Intel Trust Domain Extension definitions + Detailed information is in below document: + https://software.intel.com/content/dam/develop/external/us/en/documents + /tdx-module-1eas-v0.85.039.pdf + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef MDE_PKG_TDX_H_ +#define MDE_PKG_TDX_H_ + +#define EXIT_REASON_EXTERNAL_INTERRUPT 1 +#define EXIT_REASON_TRIPLE_FAULT 2 + +#define EXIT_REASON_PENDING_INTERRUPT 7 +#define EXIT_REASON_NMI_WINDOW 8 +#define EXIT_REASON_TASK_SWITCH 9 +#define EXIT_REASON_CPUID 10 +#define EXIT_REASON_HLT 12 +#define EXIT_REASON_INVD 13 +#define EXIT_REASON_INVLPG 14 +#define EXIT_REASON_RDPMC 15 +#define EXIT_REASON_RDTSC 16 +#define EXIT_REASON_VMCALL 18 +#define EXIT_REASON_VMCLEAR 19 +#define EXIT_REASON_VMLAUNCH 20 +#define EXIT_REASON_VMPTRLD 21 +#define EXIT_REASON_VMPTRST 22 +#define EXIT_REASON_VMREAD 23 +#define EXIT_REASON_VMRESUME 24 +#define EXIT_REASON_VMWRITE 25 +#define EXIT_REASON_VMOFF 26 +#define EXIT_REASON_VMON 27 +#define EXIT_REASON_CR_ACCESS 28 +#define EXIT_REASON_DR_ACCESS 29 +#define EXIT_REASON_IO_INSTRUCTION 30 +#define EXIT_REASON_MSR_READ 31 +#define EXIT_REASON_MSR_WRITE 32 +#define EXIT_REASON_INVALID_STATE 33 +#define EXIT_REASON_MSR_LOAD_FAIL 34 +#define EXIT_REASON_MWAIT_INSTRUCTION 36 +#define EXIT_REASON_MONITOR_TRAP_FLAG 37 +#define EXIT_REASON_MONITOR_INSTRUCTION 39 +#define EXIT_REASON_PAUSE_INSTRUCTION 40 +#define EXIT_REASON_MCE_DURING_VMENTRY 41 +#define EXIT_REASON_TPR_BELOW_THRESHOLD 43 +#define EXIT_REASON_APIC_ACCESS 44 +#define EXIT_REASON_EOI_INDUCED 45 +#define EXIT_REASON_GDTR_IDTR 46 +#define EXIT_REASON_LDTR_TR 47 +#define EXIT_REASON_EPT_VIOLATION 48 +#define EXIT_REASON_EPT_MISCONFIG 49 +#define EXIT_REASON_INVEPT 50 +#define EXIT_REASON_RDTSCP 51 +#define EXIT_REASON_PREEMPTION_TIMER 52 +#define EXIT_REASON_INVVPID 53 +#define EXIT_REASON_WBINVD 54 +#define EXIT_REASON_XSETBV 55 +#define EXIT_REASON_APIC_WRITE 56 +#define EXIT_REASON_RDRAND 57 +#define EXIT_REASON_INVPCID 58 +#define EXIT_REASON_VMFUNC 59 +#define EXIT_REASON_ENCLS 60 +#define EXIT_REASON_RDSEED 61 +#define EXIT_REASON_PML_FULL 62 +#define EXIT_REASON_XSAVES 63 +#define EXIT_REASON_XRSTORS 64 + +// TDCALL API Function Completion Status Codes +#define TDX_EXIT_REASON_SUCCESS 0x0000000000000000 +#define TDX_EXIT_REASON_PAGE_ALREADY_ACCEPTED 0x00000B0A00000000 +#define TDX_EXIT_REASON_PAGE_SIZE_MISMATCH 0xC0000B0B00000000 +#define TDX_EXIT_REASON_OPERAND_INVALID 0xC000010000000000 +#define TDX_EXIT_REASON_OPERAND_BUSY 0x8000020000000000 + +// TDCALL [TDG.MEM.PAGE.ACCEPT] page size +#define TDCALL_ACCEPT_PAGE_SIZE_4K 0 +#define TDCALL_ACCEPT_PAGE_SIZE_2M 1 +#define TDCALL_ACCEPT_PAGE_SIZE_1G 2 + +#define TDCALL_TDVMCALL 0 +#define TDCALL_TDINFO 1 +#define TDCALL_TDEXTENDRTMR 2 +#define TDCALL_TDGETVEINFO 3 +#define TDCALL_TDREPORT 4 +#define TDCALL_TDSETCPUIDVE 5 +#define TDCALL_TDACCEPTPAGE 6 + +#define TDVMCALL_CPUID 0x0000a +#define TDVMCALL_HALT 0x0000c +#define TDVMCALL_IO 0x0001e +#define TDVMCALL_RDMSR 0x0001f +#define TDVMCALL_WRMSR 0x00020 +#define TDVMCALL_MMIO 0x00030 +#define TDVMCALL_PCONFIG 0x00041 + +#define TDVMCALL_GET_TDVMCALL_INFO 0x10000 +#define TDVMCALL_MAPGPA 0x10001 +#define TDVMCALL_GET_QUOTE 0x10002 +#define TDVMCALL_REPORT_FATAL_ERR 0x10003 +#define TDVMCALL_SETUP_EVENT_NOTIFY 0x10004 + +#pragma pack(1) +typedef struct { + UINT64 Data[6]; +} TDCALL_GENERIC_RETURN_DATA; + +typedef struct { + UINT64 Gpaw; + UINT64 Attributes; + UINT32 MaxVcpus; + UINT32 NumVcpus; + UINT64 Resv[3]; +} TDCALL_INFO_RETURN_DATA; + +typedef union { + UINT64 Val; + struct { + UINT32 Size:3; + UINT32 Direction:1; + UINT32 String:1; + UINT32 Rep:1; + UINT32 Encoding:1; + UINT32 Resv:9; + UINT32 Port:16; + UINT32 Resv2; + } Io; +} VMX_EXIT_QUALIFICATION; + +typedef struct { + UINT32 ExitReason; + UINT32 Resv; + VMX_EXIT_QUALIFICATION ExitQualification; + UINT64 GuestLA; + UINT64 GuestPA; + UINT32 ExitInstructionLength; + UINT32 ExitInstructionInfo; + UINT32 Resv1; +} TDCALL_VEINFO_RETURN_DATA; + +typedef union { + TDCALL_GENERIC_RETURN_DATA Generic; + TDCALL_INFO_RETURN_DATA TdInfo; + TDCALL_VEINFO_RETURN_DATA VeInfo; +} TD_RETURN_DATA; + +/* data structure used in TDREPORT_STRUCT */ +typedef struct { + UINT8 Type; + UINT8 Subtype; + UINT8 Version; + UINT8 Rsvd; +} TD_REPORT_TYPE; + +typedef struct { + TD_REPORT_TYPE ReportType; + UINT8 Rsvd1[12]; + UINT8 CpuSvn[16]; + UINT8 TeeTcbInfoHash[48]; + UINT8 TeeInfoHash[48]; + UINT8 ReportData[64]; + UINT8 Rsvd2[32]; + UINT8 Mac[32]; +} REPORTMACSTRUCT; + +typedef struct { + UINT8 Seam[2]; + UINT8 Rsvd[14]; +} TEE_TCB_SVN; + +typedef struct { + UINT8 Valid[8]; + TEE_TCB_SVN TeeTcbSvn; + UINT8 Mrseam[48]; + UINT8 Mrsignerseam[48]; + UINT8 Attributes[8]; + UINT8 Rsvd[111]; +} TEE_TCB_INFO; + +typedef struct { + UINT8 Attributes[8]; + UINT8 Xfam[8]; + UINT8 Mrtd[48]; + UINT8 Mrconfigid[48]; + UINT8 Mrowner[48]; + UINT8 Mrownerconfig[48]; + UINT8 Rtmrs[4][48]; + UINT8 Rsvd[112]; +} TDINFO; + +typedef struct { + REPORTMACSTRUCT ReportMacStruct; + TEE_TCB_INFO TeeTcbInfo; + UINT8 Rsvd[17]; + TDINFO Tdinfo; +} TDREPORT_STRUCT; + +#pragma pack() + +#endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81476): https://edk2.groups.io/g/devel/message/81476 Mute This Topic: https://groups.io/mt/86085726/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81477+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81477+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405214; cv=none; d=zohomail.com; s=zohoarc; b=S3OaZVmeeS94WSs/XE84n5l0VzLWpv+Cl624R2Nw95zg4TLzQku6bCHRPWQZ1vQvCQgUj0G7cLGz9/jRpYNbJF2FmbUQMNZi1X1VAfaNp5lcVpxRl4avnK/OEfINH4z32PKkFruOGQmCFY3FX3Xdark/aZmJGwHo3BMsfmgSPXg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405214; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=hy0s4qIHE/rXH5zOFi8F5bGYl74Jqxh2g0im1nf9hTg=; b=bvQZZdh6psgwQtKPYz/ASNGLsqQPStdHIL2ugsLgPnrtB9LA9WFcU6WFr1WotoDQ5FVo6svxWEqxS97RObfpOhD7ivNaCSa9COFYOsFzkcIS8ibN0GAMSV2ywsFBlw2CX9scAjxxiNgrVwmTFIUL8tO/OChKn/h9Bf0kJhE7gkw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81477+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 163340521432531.720120256425048; Mon, 4 Oct 2021 20:40:14 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id rbPqYY1788612xNMTaoFBIA2; Mon, 04 Oct 2021 20:40:14 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:13 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958067" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958067" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:12 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828464" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:09 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Michael D Kinney , Liming Gao , Zhiguang Liu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 05/28] MdePkg: Add TdxLib to wrap Tdx operations Date: Tue, 5 Oct 2021 11:39:16 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: DYFQwTPfSD1QLW5r281Tb387x1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405214; bh=g4BxnY0uIWFd12ZJz+DaWCOEwkRgEqFlRm8p5825wTw=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=M3wEn5itMAvBkja5Inmughncfhycs1D/lq0liw1dNW6tzS2m0f6I9M7CdhKWBDfGu0j kSAnKvt+C+vAAJdWUrtQzeLEc2Luw7q16LNLhiNCmAmlqeRiWCDFghhqCxc+4ECRcQho8 01aZwky4jJLf9anRZR2GQTkVvjghsdFSwc4= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405215934100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 TdxLib is created with functions to perform the related Tdx operation. This includes functions for: - TdCall : Cause a VM exit to the Intel TDX module. - TdVmCall : It helps invoke services from the host VMM to pass/ receive information. - TdVmCallCpuid : Enable the TD guest to request VMM to emulate CPUID - TdAcceptPages : Accept pending private pages and initialize the pages to all-0 using the TD ephemeral private key. - TdExtendRtmr : Extend measurement to one of the RTMR registers. - TdSharedPageMask: Get the Td guest shared page mask which indicates it is a Shared or Private page. - TdMaxVCpuNum : Get the maximum number of virtual CPUs. - TdVCpuNum : Get the number of virtual CPUs. Cc: Michael D Kinney Cc: Liming Gao Cc: Zhiguang Liu Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- MdePkg/Include/Library/TdxLib.h | 167 +++++++++++++++++++ MdePkg/Library/TdxLib/AcceptPages.c | 136 ++++++++++++++++ MdePkg/Library/TdxLib/Rtmr.c | 118 ++++++++++++++ MdePkg/Library/TdxLib/TdInfo.c | 103 ++++++++++++ MdePkg/Library/TdxLib/TdxLib.inf | 39 +++++ MdePkg/Library/TdxLib/TdxLibNull.c | 192 ++++++++++++++++++++++ MdePkg/Library/TdxLib/X64/Tdcall.nasm | 85 ++++++++++ MdePkg/Library/TdxLib/X64/Tdvmcall.nasm | 207 ++++++++++++++++++++++++ MdePkg/MdePkg.dec | 3 + MdePkg/MdePkg.dsc | 1 + 10 files changed, 1051 insertions(+) create mode 100644 MdePkg/Include/Library/TdxLib.h create mode 100644 MdePkg/Library/TdxLib/AcceptPages.c create mode 100644 MdePkg/Library/TdxLib/Rtmr.c create mode 100644 MdePkg/Library/TdxLib/TdInfo.c create mode 100644 MdePkg/Library/TdxLib/TdxLib.inf create mode 100644 MdePkg/Library/TdxLib/TdxLibNull.c create mode 100644 MdePkg/Library/TdxLib/X64/Tdcall.nasm create mode 100644 MdePkg/Library/TdxLib/X64/Tdvmcall.nasm diff --git a/MdePkg/Include/Library/TdxLib.h b/MdePkg/Include/Library/TdxLi= b.h new file mode 100644 index 000000000000..43a7d709657e --- /dev/null +++ b/MdePkg/Include/Library/TdxLib.h @@ -0,0 +1,167 @@ +/** @file + TdxLib definitions + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef TDX_LIB_H_ +#define TDX_LIB_H_ + +#include +#include +#include +#include + +/** + This function accepts a pending private page, and initialize the page to + all-0 using the TD ephemeral private key. + + @param[in] StartAddress Guest physical address of the private page + to accept. + @param[in] NumberOfPages Number of the pages to be accepted. + @param[in] PageSize GPA page size. Accept 2M/4K page size. + + @return EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +TdAcceptPages ( + IN UINT64 StartAddress, + IN UINT64 NumberOfPages, + IN UINT64 PageSize + ); + +/** + This function extends one of the RTMR measurement register + in TDCS with the provided extension data in memory. + RTMR extending supports SHA384 which length is 48 bytes. + + @param[in] Data Point to the data to be extended + @param[in] DataLen Length of the data. Must be 48 + @param[in] Index RTMR index + + @return EFI_SUCCESS + @return EFI_INVALID_PARAMETER + @return EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +TdExtendRtmr ( + IN UINT32 *Data, + IN UINT32 DataLen, + IN UINT8 Index + ); + + +/** + This function gets the Td guest shared page mask. + + The guest indicates if a page is shared using the Guest Physical Address + (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47. + If the GPAW is 52, the S-bit is bit-51. + + @return Shared page bit mask +**/ +UINT64 +EFIAPI +TdSharedPageMask ( + VOID + ); + +/** + This function gets the maximum number of Virtual CPUs that are usable for + Td Guest. + + @return maximum Virtual CPUs number +**/ +UINT32 +EFIAPI +TdMaxVCpuNum ( + VOID + ); + +/** + This function gets the number of Virtual CPUs that are usable for Td + Guest. + + @return Virtual CPUs number +**/ +UINT32 +EFIAPI +TdVCpuNum ( + VOID + ); + + +/** + The TDCALL instruction causes a VM exit to the Intel TDX module. It is + used to call guest-side Intel TDX functions, either local or a TD exit + to the host VMM, as selected by Leaf. + + @param[in] Leaf Leaf number of TDCALL instruction + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in,out] Results Returned result of the Leaf function + + @return EFI_SUCCESS + @return Other See individual leaf functions +**/ +EFI_STATUS +EFIAPI +TdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ); + +/** + TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from t= he + host VMM to pass/receive information. + + @param[in] Leaf Number of sub-functions + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in] Arg4 Arg4 + @param[in,out] Results Returned result of the sub-function + + @return EFI_SUCCESS + @return Other See individual sub-functions + +**/ +EFI_STATUS +EFIAPI +TdVmCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN OUT VOID *Results + ); + +/** + This function enable the TD guest to request the VMM to emulate CPUID + operation, especially for non-architectural, CPUID leaves. + + @param[in] Eax Main leaf of the CPUID + @param[in] Ecx Sub-leaf of the CPUID + @param[out] Results Returned result of CPUID operation + + @return EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +TdVmCallCpuid ( + IN UINT64 Eax, + IN UINT64 Ecx, + OUT VOID *Results + ); + +#endif diff --git a/MdePkg/Library/TdxLib/AcceptPages.c b/MdePkg/Library/TdxLib/Ac= ceptPages.c new file mode 100644 index 000000000000..8941dc05b114 --- /dev/null +++ b/MdePkg/Library/TdxLib/AcceptPages.c @@ -0,0 +1,136 @@ +/** @file + + Unaccepted memory is a special type of private memory. In Td guest + TDCALL [TDG.MEM.PAGE.ACCEPT] is invoked to accept the unaccepted + memory before use it. + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +UINT64 mNumberOfDuplicatedAcceptedPages; + +// PageSize is mapped to PageLevel like below: +// 4KB - 0, 2MB - 1 +UINT64 mTdxAcceptPageLevelMap[2] =3D { + SIZE_4KB, + SIZE_2MB +}; + +/** + This function gets the PageLevel according to the input page size. + + @param[in] PageSize Page size + + @return UINTN The mapped page level +**/ +UINTN +GetGpaPageLevel ( + UINT64 PageSize + ) +{ + UINTN Index; + + for (Index =3D 0; Index < sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdx= AcceptPageLevelMap[0]); Index++) { + if (mTdxAcceptPageLevelMap[Index] =3D=3D PageSize) { + break; + } + } + + return Index; +} + +/** + This function accept a pending private page, and initialize the page to + all-0 using the TD ephemeral private key. + + Sometimes TDCALL [TDG.MEM.PAGE.ACCEPT] may return + TDX_EXIT_REASON_PAGE_SIZE_MISMATCH. It indicates the input PageLevel is + not workable. In this case we need to try to fallback to a smaller + PageLevel if possible. + + @param[in] StartAddress Guest physical address of the private + page to accept. + @param[in] NumberOfPages Number of the pages to be accepted. + @param[in] PageSize GPA page size. Only accept 1G/2M/4K size. + + @return EFI_SUCCESS Accept successfully + @return others Indicate other errors +**/ +EFI_STATUS +EFIAPI +TdAcceptPages ( + IN UINT64 StartAddress, + IN UINT64 NumberOfPages, + IN UINT64 PageSize + ) +{ + EFI_STATUS Status; + UINT64 Address; + UINT64 TdxStatus; + UINT64 Index; + UINT64 GpaPageLevel; + UINT64 PageSize2; + + Address =3D StartAddress; + + GpaPageLevel =3D (UINT64) GetGpaPageLevel (PageSize); + if (GpaPageLevel > sizeof (mTdxAcceptPageLevelMap) / sizeof (mTdxAcceptP= ageLevelMap[0])) { + DEBUG ((DEBUG_ERROR, "Accept page size must be 4K/2M. Invalid page siz= e - 0x%llx\n", PageSize)); + return EFI_INVALID_PARAMETER; + } + + Status =3D EFI_SUCCESS; + for (Index =3D 0; Index < NumberOfPages; Index++) { + TdxStatus =3D TdCall (TDCALL_TDACCEPTPAGE, Address | GpaPageLevel, 0, = 0, 0); + if (TdxStatus !=3D TDX_EXIT_REASON_SUCCESS) { + if ((TdxStatus & ~0xFFFFULL) =3D=3D TDX_EXIT_REASON_PAGE_ALREADY_A= CCEPTED) { + // + // Already accepted + // + mNumberOfDuplicatedAcceptedPages++; + } else if ((TdxStatus & ~0xFFFFULL) =3D=3D TDX_EXIT_REASON_PAGE_SI= ZE_MISMATCH) { + // + // GpaPageLevel is mismatch, fall back to a smaller GpaPageLevel= if possible + // + DEBUG ((DEBUG_VERBOSE, "Address %llx cannot be accepted in PageL= evel of %d\n", Address, GpaPageLevel)); + + if (GpaPageLevel =3D=3D 0) { + // + // Cannot fall back to smaller page level + // + DEBUG ((DEBUG_ERROR, "AcceptPage cannot fallback from PageLeve= l %d\n", GpaPageLevel)); + Status =3D EFI_INVALID_PARAMETER; + break; + } else { + // + // Fall back to a smaller page size + // + PageSize2 =3D mTdxAcceptPageLevelMap [GpaPageLevel - 1]; + Status =3D TdAcceptPages(Address, 512, PageSize2); + if (EFI_ERROR (Status)) { + break; + } + } + }else { + + // + // Other errors + // + DEBUG ((DEBUG_ERROR, "Address %llx (%d) failed to be accepted. E= rror =3D 0x%llx\n", + Address, Index, TdxStatus)); + Status =3D EFI_INVALID_PARAMETER; + break; + } + } + Address +=3D PageSize; + } + return Status; +} diff --git a/MdePkg/Library/TdxLib/Rtmr.c b/MdePkg/Library/TdxLib/Rtmr.c new file mode 100644 index 000000000000..c86902ae21bc --- /dev/null +++ b/MdePkg/Library/TdxLib/Rtmr.c @@ -0,0 +1,118 @@ +/** @file + + Extends one of the RTMR measurement registers in TDCS with the provided + extension data in memory. + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#define RTMR_COUNT 4 +#define TD_EXTEND_BUFFER_LEN (64 + 64) +#define EXTEND_BUFFER_ADDRESS_MASK 0x3f + + +#pragma pack(16) +typedef struct { + UINT8 Buffer[TD_EXTEND_BUFFER_LEN]; +} TDX_EXTEND_BUFFER; +#pragma pack() + +UINT8 *mExtendBufferAddress =3D NULL; +TDX_EXTEND_BUFFER mExtendBuffer; + +/** + TD.RTMR.EXTEND requires 64B-aligned guest physical address of + 48B-extension data. In runtime we walk thru the Buffer to find + out a 64B-aligned start address. + + @return Start address of the extend buffer + +**/ +UINT8 * +EFIAPI +GetExtendBuffer ( + VOID + ) +{ + UINT8 *ExtendBufferAddress; + UINT64 Gap; + + if (mExtendBufferAddress !=3D NULL) { + return mExtendBufferAddress; + } + + ExtendBufferAddress =3D mExtendBuffer.Buffer; + + Gap =3D 0x40 - ((UINT64)(UINTN)ExtendBufferAddress & EXTEND_BUFFER_ADDRE= SS_MASK); + mExtendBufferAddress =3D (UINT8*)((UINT64)(UINTN)ExtendBufferAddress + G= ap); + + DEBUG ((DEBUG_VERBOSE, "ExtendBufferAddress: 0x%p, Gap: 0x%x\n", ExtendB= ufferAddress, Gap)); + DEBUG ((DEBUG_VERBOSE, "mExtendBufferAddress: 0x%p\n", mExtendBufferAddr= ess)); + + ASSERT (mExtendBufferAddress + 64 <=3D ExtendBufferAddress + TD_EXTEND_B= UFFER_LEN); + + return mExtendBufferAddress; +} + + +/** + This function extends one of the RTMR measurement register + in TDCS with the provided extension data in memory. + RTMR extending supports SHA384 which length is 48 bytes. + + @param[in] Data Point to the data to be extended + @param[in] DataLen Length of the data. Must be 48 + @param[in] Index RTMR index + + @return EFI_SUCCESS + @return EFI_INVALID_PARAMETER + @return EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +TdExtendRtmr ( + IN UINT32 *Data, + IN UINT32 DataLen, + IN UINT8 Index + ) +{ + EFI_STATUS Status; + UINT64 TdCallStatus; + UINT8 *ExtendBuffer; + + Status =3D EFI_SUCCESS; + + ASSERT (Index >=3D 0 && Index < RTMR_COUNT); + ASSERT (DataLen =3D=3D SHA384_DIGEST_SIZE); + + ExtendBuffer =3D GetExtendBuffer(); + ASSERT (ExtendBuffer !=3D NULL); + ZeroMem (ExtendBuffer, SHA384_DIGEST_SIZE); + CopyMem (ExtendBuffer, Data, SHA384_DIGEST_SIZE); + + TdCallStatus =3D TdCall (TDCALL_TDEXTENDRTMR, (UINT64)(UINTN)ExtendBuffe= r, Index, 0, 0); + + if (TdCallStatus =3D=3D TDX_EXIT_REASON_SUCCESS) { + Status =3D EFI_SUCCESS; + } else if (TdCallStatus =3D=3D TDX_EXIT_REASON_OPERAND_INVALID) { + Status =3D EFI_INVALID_PARAMETER; + } else { + Status =3D EFI_DEVICE_ERROR; + } + + if (Status !=3D EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Error returned from TdExtendRtmr call - 0x%lx\n"= , TdCallStatus)); + } + + return Status; +} diff --git a/MdePkg/Library/TdxLib/TdInfo.c b/MdePkg/Library/TdxLib/TdInfo.c new file mode 100644 index 000000000000..56c268e70c8d --- /dev/null +++ b/MdePkg/Library/TdxLib/TdInfo.c @@ -0,0 +1,103 @@ +/** @file + + Fetch the Tdx info. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +UINT64 mTdSharedPageMask =3D 0; +UINT32 mTdMaxVCpuNum =3D 0; +UINT32 mTdVCpuNum =3D 0; + +/** + This function gets the Td guest shared page mask. + + The guest indicates if a page is shared using the Guest Physical Address + (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47. + If the GPAW is 52, the S-bit is bit-51. + + @return Shared page bit mask +**/ +UINT64 +EFIAPI +TdSharedPageMask ( + VOID + ) +{ + UINT64 Status; + UINT8 Gpaw; + TD_RETURN_DATA TdReturnData; + + if (mTdSharedPageMask !=3D 0) { + return mTdSharedPageMask; + } + + Status =3D TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT (Status =3D=3D TDX_EXIT_REASON_SUCCESS); + + Gpaw =3D (UINT8)(TdReturnData.TdInfo.Gpaw & 0x3f); + ASSERT(Gpaw =3D=3D 48 || Gpaw =3D=3D 52); + mTdSharedPageMask =3D 1ULL << (Gpaw - 1); + return mTdSharedPageMask; +} + +/** + This function gets the maximum number of Virtual CPUs that are usable for + Td Guest. + + @return maximum Virtual CPUs number +**/ +UINT32 +EFIAPI +TdMaxVCpuNum ( + VOID + ) +{ + UINT64 Status; + TD_RETURN_DATA TdReturnData; + + if (mTdMaxVCpuNum !=3D 0) { + return mTdMaxVCpuNum; + } + + Status =3D TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT (Status =3D=3D TDX_EXIT_REASON_SUCCESS); + + mTdMaxVCpuNum =3D TdReturnData.TdInfo.MaxVcpus; + + return mTdMaxVCpuNum; +} + +/** + This function gets the number of Virtual CPUs that are usable for Td + Guest. + + @return Virtual CPUs number +**/ +UINT32 +EFIAPI +TdVCpuNum ( + VOID + ) +{ + UINT64 Status; + TD_RETURN_DATA TdReturnData; + + if (mTdVCpuNum !=3D 0) { + return mTdVCpuNum; + } + + Status =3D TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT (Status =3D=3D TDX_EXIT_REASON_SUCCESS); + + mTdVCpuNum =3D TdReturnData.TdInfo.NumVcpus; + return mTdVCpuNum; +} diff --git a/MdePkg/Library/TdxLib/TdxLib.inf b/MdePkg/Library/TdxLib/TdxLi= b.inf new file mode 100644 index 000000000000..772abcc49d8b --- /dev/null +++ b/MdePkg/Library/TdxLib/TdxLib.inf @@ -0,0 +1,39 @@ +## @file +# Tdx library +# +# Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D TdxLib + FILE_GUID =3D 032A8E0D-0C27-40C0-9CAA-23B731C1B223 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D TdxLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources.IA32] + TdxLibNull.c + +[Sources.X64] + AcceptPages.c + Rtmr.c + TdInfo.c + X64/Tdcall.nasm + X64/Tdvmcall.nasm + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib diff --git a/MdePkg/Library/TdxLib/TdxLibNull.c b/MdePkg/Library/TdxLib/Tdx= LibNull.c new file mode 100644 index 000000000000..5a8f19c6d8d2 --- /dev/null +++ b/MdePkg/Library/TdxLib/TdxLibNull.c @@ -0,0 +1,192 @@ +/** @file + + Null stub of TdxLib + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + This function accepts a pending private page, and initialize the page to + all-0 using the TD ephemeral private key. + + @param[in] StartAddress Guest physical address of the private page + to accept. + @param[in] NumberOfPages Number of the pages to be accepted. + @param[in] PageSize GPA page size. Accept 1G/2M/4K page size. + + @return EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +TdAcceptPages ( + IN UINT64 StartAddress, + IN UINT64 NumberOfPages, + IN UINT64 PageSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function extends one of the RTMR measurement register + in TDCS with the provided extension data in memory. + RTMR extending supports SHA384 which length is 48 bytes. + + @param[in] Data Point to the data to be extended + @param[in] DataLen Length of the data. Must be 48 + @param[in] Index RTMR index + + @return EFI_SUCCESS + @return EFI_INVALID_PARAMETER + @return EFI_DEVICE_ERROR + +**/ +EFI_STATUS +EFIAPI +TdExtendRtmr ( + IN UINT32 *Data, + IN UINT32 DataLen, + IN UINT8 Index + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + This function gets the Td guest shared page mask. + + The guest indicates if a page is shared using the Guest Physical Address + (GPA) Shared (S) bit. If the GPA Width(GPAW) is 48, the S-bit is bit-47. + If the GPAW is 52, the S-bit is bit-51. + + @return Shared page bit mask +**/ +UINT64 +EFIAPI +TdSharedPageMask ( + VOID + ) +{ + return 0; +} + + +/** + This function gets the maximum number of Virtual CPUs that are usable for + Td Guest. + + @return maximum Virtual CPUs number +**/ +UINT32 +EFIAPI +TdMaxVCpuNum ( + VOID + ) +{ + return 0; +} + + +/** + This function gets the number of Virtual CPUs that are usable for Td + Guest. + + @return Virtual CPUs number +**/ +UINT32 +EFIAPI +TdVCpuNum ( + VOID + ) +{ + return 0; +} + + +/** + The TDCALL instruction causes a VM exit to the Intel TDX module. It is + used to call guest-side Intel TDX functions, either local or a TD exit + to the host VMM, as selected by Leaf. + Leaf functions are described at + + @param[in] Leaf Leaf number of TDCALL instruction + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in,out] Results Returned result of the Leaf function + + @return EFI_SUCCESS + @return Other See individual leaf functions +**/ +EFI_STATUS +EFIAPI +TdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + TDVMALL is a leaf function 0 for TDCALL. It helps invoke services from t= he + host VMM to pass/receive information. + + @param[in] Leaf Number of sub-functions + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in] Arg4 Arg4 + @param[in,out] Results Returned result of the sub-function + + @return EFI_SUCCESS + @return Other See individual sub-functions + +**/ +EFI_STATUS +EFIAPI +TdVmCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN OUT VOID *Results + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + This function enable the TD guest to request the VMM to emulate CPUID + operation, especially for non-architectural, CPUID leaves. + + @param[in] Eax Main leaf of the CPUID + @param[in] Ecx Sub-leaf of the CPUID + @param[out] Results Returned result of CPUID operation + + @return EFI_SUCCESS +**/ +EFI_STATUS +EFIAPI +TdVmCallCpuid ( + IN UINT64 Eax, + IN UINT64 Ecx, + OUT VOID *Results + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/MdePkg/Library/TdxLib/X64/Tdcall.nasm b/MdePkg/Library/TdxLib/= X64/Tdcall.nasm new file mode 100644 index 000000000000..e8a094b0eb3f --- /dev/null +++ b/MdePkg/Library/TdxLib/X64/Tdcall.nasm @@ -0,0 +1,85 @@ +;-------------------------------------------------------------------------= ----- +;* +;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+;* SPDX-License-Identifier: BSD-2-Clause-Patent +;* +;* +;-------------------------------------------------------------------------= ----- + +DEFAULT REL +SECTION .text + +%macro tdcall 0 + db 0x66,0x0f,0x01,0xcc +%endmacro + +%macro tdcall_push_regs 0 + push rbp + mov rbp, rsp + push r15 + push r14 + push r13 + push r12 + push rbx + push rsi + push rdi +%endmacro + +%macro tdcall_pop_regs 0 + pop rdi + pop rsi + pop rbx + pop r12 + pop r13 + pop r14 + pop r15 + pop rbp +%endmacro + +%define number_of_regs_pushed 8 +%define number_of_parameters 4 + +; +; Keep these in sync for push_regs/pop_regs, code below +; uses them to find 5th or greater parameters +; +%define first_variable_on_stack_offset \ + ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8) +%define second_variable_on_stack_offset \ + ((first_variable_on_stack_offset) + 8) + +; TdCall ( +; UINT64 Leaf, // Rcx +; UINT64 P1, // Rdx +; UINT64 P2, // R8 +; UINT64 P3, // R9 +; UINT64 Results, // rsp + 0x28 +; ) +global ASM_PFX(TdCall) +ASM_PFX(TdCall): + tdcall_push_regs + + mov rax, rcx + mov rcx, rdx + mov rdx, r8 + mov r8, r9 + + tdcall + + ; exit if tdcall reports failure. + test rax, rax + jnz .exit + + ; test if caller wanted results + mov r12, [rsp + first_variable_on_stack_offset ] + test r12, r12 + jz .exit + mov [r12 + 0 ], rcx + mov [r12 + 8 ], rdx + mov [r12 + 16], r8 + mov [r12 + 24], r9 + mov [r12 + 32], r10 + mov [r12 + 40], r11 +.exit: + tdcall_pop_regs + ret diff --git a/MdePkg/Library/TdxLib/X64/Tdvmcall.nasm b/MdePkg/Library/TdxLi= b/X64/Tdvmcall.nasm new file mode 100644 index 000000000000..eb1cb967dc29 --- /dev/null +++ b/MdePkg/Library/TdxLib/X64/Tdvmcall.nasm @@ -0,0 +1,207 @@ +;-------------------------------------------------------------------------= ----- +;* +;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+;* SPDX-License-Identifier: BSD-2-Clause-Patent +;* +;* +;-------------------------------------------------------------------------= ----- + +DEFAULT REL +SECTION .text + +%define TDVMCALL_EXPOSE_REGS_MASK 0xffec +%define TDVMCALL 0x0 +%define EXIT_REASON_CPUID 0xa + +%macro tdcall 0 + db 0x66,0x0f,0x01,0xcc +%endmacro + +%macro tdcall_push_regs 0 + push rbp + mov rbp, rsp + push r15 + push r14 + push r13 + push r12 + push rbx + push rsi + push rdi +%endmacro + +%macro tdcall_pop_regs 0 + pop rdi + pop rsi + pop rbx + pop r12 + pop r13 + pop r14 + pop r15 + pop rbp +%endmacro + +%define number_of_regs_pushed 8 +%define number_of_parameters 4 + +; +; Keep these in sync for push_regs/pop_regs, code below +; uses them to find 5th or greater parameters +; +%define first_variable_on_stack_offset \ + ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8) +%define second_variable_on_stack_offset \ + ((first_variable_on_stack_offset) + 8) + +%macro tdcall_regs_preamble 2 + mov rax, %1 + + xor rcx, rcx + mov ecx, %2 + + ; R10 =3D 0 (standard TDVMCALL) + + xor r10d, r10d + + ; Zero out unused (for standard TDVMCALL) registers to avoid leaking + ; secrets to the VMM. + + xor ebx, ebx + xor esi, esi + xor edi, edi + + xor edx, edx + xor ebp, ebp + xor r8d, r8d + xor r9d, r9d +%endmacro + +%macro tdcall_regs_postamble 0 + xor ebx, ebx + xor esi, esi + xor edi, edi + + xor ecx, ecx + xor edx, edx + xor r8d, r8d + xor r9d, r9d + xor r10d, r10d + xor r11d, r11d +%endmacro + +;-------------------------------------------------------------------------= ----- +; 0 =3D> RAX =3D TDCALL leaf +; M =3D> RCX =3D TDVMCALL register behavior +; 1 =3D> R10 =3D standard vs. vendor +; RDI =3D> R11 =3D TDVMCALL function / nr +; RSI =3D R12 =3D p1 +; RDX =3D> R13 =3D p2 +; RCX =3D> R14 =3D p3 +; R8 =3D> R15 =3D p4 + +; UINT64 +; EFIAPI +; TdVmCall ( +; UINT64 Leaf, // Rcx +; UINT64 P1, // Rdx +; UINT64 P2, // R8 +; UINT64 P3, // R9 +; UINT64 P4, // rsp + 0x28 +; UINT64 *Val // rsp + 0x30 +; ) +global ASM_PFX(TdVmCall) +ASM_PFX(TdVmCall): + tdcall_push_regs + + mov r11, rcx + mov r12, rdx + mov r13, r8 + mov r14, r9 + mov r15, [rsp + first_variable_on_stack_offset ] + + tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK + + tdcall + + ; ignore return dataif TDCALL reports failure. + test rax, rax + jnz .no_return_data + + ; Propagate TDVMCALL success/failure to return value. + mov rax, r10 + + ; Retrieve the Val pointer. + mov r9, [rsp + second_variable_on_stack_offset ] + test r9, r9 + jz .no_return_data + + ; On success, propagate TDVMCALL output value to output param + test rax, rax + jnz .no_return_data + mov [r9], r11 +.no_return_data: + tdcall_regs_postamble + + tdcall_pop_regs + + ret + +;-------------------------------------------------------------------------= ----- +; 0 =3D> RAX =3D TDCALL leaf +; M =3D> RCX =3D TDVMCALL register behavior +; 1 =3D> R10 =3D standard vs. vendor +; RDI =3D> R11 =3D TDVMCALL function / nr +; RSI =3D R12 =3D p1 +; RDX =3D> R13 =3D p2 +; RCX =3D> R14 =3D p3 +; R8 =3D> R15 =3D p4 + +; UINT64 +; EFIAPI +; TdVmCallCpuid ( +; UINT64 EaxIn, // Rcx +; UINT64 EcxIn, // Rdx +; UINT64 *Results // R8 +; ) +global ASM_PFX(TdVmCallCpuid) +ASM_PFX(TdVmCallCpuid): + tdcall_push_regs + + mov r11, EXIT_REASON_CPUID + mov r12, rcx + mov r13, rdx + + ; Save *results pointers + push r8 + + tdcall_regs_preamble TDVMCALL, TDVMCALL_EXPOSE_REGS_MASK + + tdcall + + ; Panic if TDCALL reports failure. + test rax, rax + jnz .no_return_data + + ; Propagate TDVMCALL success/failure to return value. + mov rax, r10 + test rax, rax + jnz .no_return_data + + ; Retrieve *Results + pop r8 + test r8, r8 + jz .no_return_data + ; Caller pass in buffer so store results r12-r15 contains eax-edx + mov [r8 + 0], r12 + mov [r8 + 8], r13 + mov [r8 + 16], r14 + mov [r8 + 24], r15 + +.no_return_data: + tdcall_regs_postamble + + tdcall_pop_regs + + ret + +.panic: + ud2 diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 9cdc915ebae9..8b85f59e6dfb 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -296,6 +296,9 @@ ## @libraryclass Provides services to log the SMI handler registration. SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h =20 + ## @libraryclass Provides function to support TDX processing. + TdxLib|Include/Library/TdxLib.h + [Guids] # # GUID defined in UEFI2.1/UEFI2.0/EFI1.1 diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc index a94959169b2f..d6a7af412be7 100644 --- a/MdePkg/MdePkg.dsc +++ b/MdePkg/MdePkg.dsc @@ -175,6 +175,7 @@ MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf + MdePkg/Library/TdxLib/TdxLib.inf =20 [Components.EBC] MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81477): https://edk2.groups.io/g/devel/message/81477 Mute This Topic: https://groups.io/mt/86085729/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81478+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81478+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405216; cv=none; d=zohomail.com; s=zohoarc; b=V3VAs6AVLnH3AmK9cEYATiLhMdq1rU5qdZEsXuc4Q5hhIZBjx3gEYxuC3hNU4oQcdgKBVLXbJo4633xtnI0iZduWJn5fAfdhmHzZKzVA9pAKI377LyAct5RDHazotDD/LaWiUrGoQIVN8zVfPL1VYfBcspBBnQ7yaoWuDDZUtnE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405216; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ArW/6oPmVkCXKJ2XJnViOxQv5M9YMo41T9Hq4SyJc1o=; b=O29SQx0Ms0lS07/zmjfnmIDuE4hSJPk/wIfhcdzycrBrTZrjj2Du7NzUpN2uzSMaAsk+H02WWnIVibNjV965pOVJrtHF/5l2H5pZTOXSUP5aEOf5uiUJMtNZHpvsXgHiZK8SmVDkRaeiZIRZgNaqumLALgJaaoIoVExA73d6A0M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81478+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405216717260.41073724340094; Mon, 4 Oct 2021 20:40:16 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id K7rkYY1788612xfWgVm3v0rT; Mon, 04 Oct 2021 20:40:16 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:15 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958087" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958087" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:15 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828504" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:12 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Michael D Kinney , Liming Gao , Zhiguang Liu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 06/28] MdePkg: Update BaseIoLibIntrinsicSev to support Tdx Date: Tue, 5 Oct 2021 11:39:17 +0800 Message-Id: <78bc0164be0e6adb1edf4454bdc3aaf1d55a2771.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: dXW5xDO3Qs5jlT8a8SSg1ff5x1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405216; bh=4oq09KwatvgphKAp5K2VRanIjae3cNSTWLRf2EUIvf0=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=aHrt9/p6IdeJg71fhfzknwTwZn1BjNd+1EasYib5xsqYh7u3nJYy+t/hH/15fgl3xqr fxSp8tht+vL1PSmZJzdiwhbrBTjAgZgWm83+cKua4EDQbOStMB8NZVV16+YasuyLc99nP mescQxSlbOd603ZZO1NcpFjzYMfXfCDmzM8= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405218284100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Intel TDX architecture does not prescribe a specific software convention to perform I/O from the guest TD. Guest TD providers have many choices to provide I/O to the guest. The common I/O models are emulated devices, para-virtualized devices, SRIOV devices and Direct Device assignments. TDVF chooses para-virtualized I/O (Choice-A) which use the TDG.VP.VMCALL function to invoke the funtions provided by the host VMM to perform I/O. Another choice (Choice-B) is the emulation performed by the #VE handler. There are 2 benefits of para-virtualized I/O: 1. Performance. VMEXIT/VMENTRY is skipped so that the performance is better than #VE handler. 2. De-couple with #VE handler. Choice-B depends on the #VE handler which means I/O is not available until #VE handler is installed. For example, in PEI phase #VE handler is installed in CpuMpPei, while communication with Qemu (via I/O port) happen earlier than it. BaseIoLibIntrinsicSev.inf is the IoLib used by OvmfPkg. TDVF updates BaseIoLibIntrinsicSev to support I/O in Td guest. Below files are updated to support I/O in Td guest. - IoLib.c - IoLibGcc.c - IoLibMsc.c - X64/IoFifoSev.nasm In the I/O functions of above files, if IsTdxGuest() returns TRUE, then Td I/O routine is called, otherwise the legacy I/O routine is called. Td I/O routines are declared in IoLibTdx.h and implemented in IoLibInternalTdx.c. BaseIoLibIntrinsic.inf is the IoLib used by other packages. It will not support I/O in Td guest. But some files are shared between BaseIoLibIntrinsic and BaseIoLibIntrinsicSev (IoLib.c is the example). So IoLibInternalTdxNull.c is created which holds the null stub of the Td I/O routines. IoLibInternalTdxNull.c is included in BaseIoLibIntrinsic.inf. BaseIoLibIntrinsic.inf doesn't import TdxLib so that the Pkgs which include BaseIoLibIntrinsic.inf need not include TdxLib. BaseIoLibIntrinsicArmVirt.inf is not touched because it shares no files with BaseIoLibIntrinsicSev. Cc: Michael D Kinney Cc: Liming Gao Cc: Zhiguang Liu Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- .../BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf | 2 + .../BaseIoLibIntrinsicSev.inf | 7 +- MdePkg/Library/BaseIoLibIntrinsic/IoLib.c | 97 ++- MdePkg/Library/BaseIoLibIntrinsic/IoLibFifo.c | 216 +++++ MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c | 49 +- .../BaseIoLibIntrinsic/IoLibInternalTdx.c | 735 ++++++++++++++++++ .../BaseIoLibIntrinsic/IoLibInternalTdxNull.c | 499 ++++++++++++ MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c | 73 +- MdePkg/Library/BaseIoLibIntrinsic/IoLibSev.h | 166 ++++ MdePkg/Library/BaseIoLibIntrinsic/IoLibTdx.h | 411 ++++++++++ .../BaseIoLibIntrinsic/X64/IoFifoSev.nasm | 34 +- 11 files changed, 2223 insertions(+), 66 deletions(-) create mode 100644 MdePkg/Library/BaseIoLibIntrinsic/IoLibFifo.c create mode 100644 MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdx.c create mode 100644 MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdxNull.c create mode 100644 MdePkg/Library/BaseIoLibIntrinsic/IoLibSev.h create mode 100644 MdePkg/Library/BaseIoLibIntrinsic/IoLibTdx.h diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/Mde= Pkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf index 97eeada0656e..27b15d9ae256 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf @@ -34,6 +34,8 @@ IoLibMmioBuffer.c BaseIoLibIntrinsicInternal.h IoHighLevel.c + IoLibInternalTdxNull.c + IoLibTdx.h =20 [Sources.IA32] IoLibGcc.c | GCC diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf b/= MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf index 34f9d1d1062f..7e94be5a794f 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf @@ -30,17 +30,22 @@ IoLibMmioBuffer.c BaseIoLibIntrinsicInternal.h IoHighLevel.c + IoLibSev.h + IoLibTdx.h =20 [Sources.IA32] IoLibGcc.c | GCC IoLibMsc.c | MSFT IoLib.c + IoLibInternalTdxNull.c Ia32/IoFifoSev.nasm =20 [Sources.X64] IoLibGcc.c | GCC IoLibMsc.c | MSFT IoLib.c + IoLibFifo.c + IoLibInternalTdx.c X64/IoFifoSev.nasm =20 [Packages] @@ -50,4 +55,4 @@ DebugLib BaseLib RegisterFilterLib - + TdxLib diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c b/MdePkg/Library/Bas= eIoLibIntrinsic/IoLib.c index d0d7044f0901..68298749ee56 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c @@ -7,6 +7,7 @@ **/ =20 #include "BaseIoLibIntrinsicInternal.h" +#include "IoLibTdx.h" =20 /** Reads a 64-bit I/O port. @@ -70,6 +71,8 @@ IoWrite64 ( =20 If 8-bit MMIO register operations are not supported, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to read MMIO registers. + @param Address The MMIO register to read. =20 @return The value read. @@ -86,9 +89,13 @@ MmioRead8 ( =20 Flag =3D FilterBeforeMmIoRead (FilterWidth8, Address, &Value); if (Flag) { - MemoryFence (); - Value =3D *(volatile UINT8*)Address; - MemoryFence (); + if (IsTdxGuest ()) { + Value =3D TdMmioRead8 (Address); + } else { + MemoryFence (); + Value =3D *(volatile UINT8*)Address; + MemoryFence (); + } } FilterAfterMmIoRead (FilterWidth8, Address, &Value); =20 @@ -104,6 +111,8 @@ MmioRead8 ( =20 If 8-bit MMIO register operations are not supported, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to write MMIO registers. + @param Address The MMIO register to write. @param Value The value to write to the MMIO register. =20 @@ -121,9 +130,13 @@ MmioWrite8 ( =20 Flag =3D FilterBeforeMmIoWrite (FilterWidth8, Address, &Value); if (Flag) { - MemoryFence (); - *(volatile UINT8*)Address =3D Value; - MemoryFence (); + if (IsTdxGuest ()) { + TdMmioWrite8 (Address, Value); + } else { + MemoryFence (); + *(volatile UINT8*)Address =3D Value; + MemoryFence (); + } } FilterAfterMmIoWrite (FilterWidth8, Address, &Value); =20 @@ -140,6 +153,8 @@ MmioWrite8 ( If 16-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to read MMIO registers. + @param Address The MMIO register to read. =20 @return The value read. @@ -157,9 +172,13 @@ MmioRead16 ( ASSERT ((Address & 1) =3D=3D 0); Flag =3D FilterBeforeMmIoRead (FilterWidth16, Address, &Value); if (Flag) { - MemoryFence (); - Value =3D *(volatile UINT16*)Address; - MemoryFence (); + if (IsTdxGuest ()) { + Value =3D TdMmioRead16 (Address); + } else { + MemoryFence (); + Value =3D *(volatile UINT16*)Address; + MemoryFence (); + } } FilterAfterMmIoRead (FilterWidth16, Address, &Value); =20 @@ -176,6 +195,8 @@ MmioRead16 ( If 16-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to write MMIO registers. + @param Address The MMIO register to write. @param Value The value to write to the MMIO register. =20 @@ -195,9 +216,13 @@ MmioWrite16 ( =20 Flag =3D FilterBeforeMmIoWrite (FilterWidth16, Address, &Value); if (Flag) { - MemoryFence (); - *(volatile UINT16*)Address =3D Value; - MemoryFence (); + if (IsTdxGuest ()) { + TdMmioWrite16 (Address, Value); + } else { + MemoryFence (); + *(volatile UINT16*)Address =3D Value; + MemoryFence (); + } } FilterAfterMmIoWrite (FilterWidth16, Address, &Value); =20 @@ -214,6 +239,8 @@ MmioWrite16 ( If 32-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to read MMIO registers. + @param Address The MMIO register to read. =20 @return The value read. @@ -232,9 +259,13 @@ MmioRead32 ( =20 Flag =3D FilterBeforeMmIoRead (FilterWidth32, Address, &Value); if (Flag) { - MemoryFence (); - Value =3D *(volatile UINT32*)Address; - MemoryFence (); + if (IsTdxGuest ()) { + Value =3D TdMmioRead32 (Address); + } else { + MemoryFence (); + Value =3D *(volatile UINT32*)Address; + MemoryFence (); + } } FilterAfterMmIoRead (FilterWidth32, Address, &Value); =20 @@ -251,6 +282,8 @@ MmioRead32 ( If 32-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to write MMIO registers. + @param Address The MMIO register to write. @param Value The value to write to the MMIO register. =20 @@ -270,9 +303,13 @@ MmioWrite32 ( =20 Flag =3D FilterBeforeMmIoWrite (FilterWidth32, Address, &Value); if (Flag) { - MemoryFence (); - *(volatile UINT32*)Address =3D Value; - MemoryFence (); + if (IsTdxGuest ()) { + TdMmioWrite32 (Address, Value); + } else { + MemoryFence (); + *(volatile UINT32*)Address =3D Value; + MemoryFence (); + } } FilterAfterMmIoWrite (FilterWidth32, Address, &Value); =20 @@ -289,6 +326,8 @@ MmioWrite32 ( If 64-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 64-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to read MMIO registers. + @param Address The MMIO register to read. =20 @return The value read. @@ -307,9 +346,13 @@ MmioRead64 ( =20 Flag =3D FilterBeforeMmIoRead (FilterWidth64, Address, &Value); if (Flag) { - MemoryFence (); - Value =3D *(volatile UINT64*)Address; - MemoryFence (); + if (IsTdxGuest ()) { + Value =3D TdMmioRead64 (Address); + } else { + MemoryFence (); + Value =3D *(volatile UINT64*)Address; + MemoryFence (); + } } FilterAfterMmIoRead (FilterWidth64, Address, &Value); =20 @@ -326,6 +369,8 @@ MmioRead64 ( If 64-bit MMIO register operations are not supported, then ASSERT(). If Address is not aligned on a 64-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_MMIO is invoked to write MMIO registers. + @param Address The MMIO register to write. @param Value The value to write to the MMIO register. =20 @@ -343,9 +388,13 @@ MmioWrite64 ( =20 Flag =3D FilterBeforeMmIoWrite (FilterWidth64, Address, &Value); if (Flag) { - MemoryFence (); - *(volatile UINT64*)Address =3D Value; - MemoryFence (); + if (IsTdxGuest ()) { + TdMmioWrite64 (Address, Value); + } else { + MemoryFence (); + *(volatile UINT64*)Address =3D Value; + MemoryFence (); + } } FilterAfterMmIoWrite (FilterWidth64, Address, &Value); =20 diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibFifo.c b/MdePkg/Library= /BaseIoLibIntrinsic/IoLibFifo.c new file mode 100644 index 000000000000..9e243543cfe2 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibFifo.c @@ -0,0 +1,216 @@ +/** @file + IoFifo read/write routines. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BaseIoLibIntrinsicInternal.h" +#include "IoLibSev.h" +#include "IoLibTdx.h" +#include + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead8 is invoked to read the I/O port fifo. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoReadFifo8 (Port, Count, Buffer); + } else { + SevIoReadFifo8 (Port, Count, Buffer); + } +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite8 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoWriteFifo8 (Port, Count, Buffer); + } else { + SevIoWriteFifo8 (Port, Count, Buffer); + } +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead16 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoReadFifo16 (Port, Count, Buffer); + } else { + SevIoReadFifo16 (Port, Count, Buffer); + } +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite16 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoWriteFifo16 (Port, Count, Buffer); + } else { + SevIoWriteFifo16 (Port, Count, Buffer); + } +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead32 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +IoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoReadFifo32 (Port, Count, Buffer); + } else { + SevIoReadFifo32 (Port, Count, Buffer); + } +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite32 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +IoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + if (IsTdxGuest ()) { + TdIoWriteFifo32 (Port, Count, Buffer); + } else { + SevIoWriteFifo32 (Port, Count, Buffer); + } +} diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c b/MdePkg/Library/= BaseIoLibIntrinsic/IoLibGcc.c index ecf9ed61911f..42b5d5743a4f 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c @@ -17,6 +17,7 @@ =20 =20 #include "BaseIoLibIntrinsicInternal.h" +#include "IoLibTdx.h" =20 /** Reads an 8-bit I/O port. @@ -25,7 +26,9 @@ This function must guarantee that all I/O read and write operations are serialized. =20 - If 8-bit I/O port operations are not supported, then ASSERT(). + If 8-bit I/O port operations are not supported, then ASSERT() + + For Td guest TDVMCALL_IO is invoked to read I/O port. =20 @param Port The I/O port to read. =20 @@ -43,7 +46,11 @@ IoRead8 ( =20 Flag =3D FilterBeforeIoRead (FilterWidth8, Port, &Data); if (Flag) { - __asm__ __volatile__ ("inb %w1,%b0" : "=3Da" (Data) : "d" ((UINT16)Por= t)); + if (IsTdxGuest ()) { + Data =3D TdIoRead8 (Port); + } else { + __asm__ __volatile__ ("inb %w1,%b0" : "=3Da" (Data) : "d" ((UINT16)P= ort)); + } } FilterAfterIoRead (FilterWidth8, Port, &Data); =20 @@ -59,6 +66,8 @@ IoRead8 ( =20 If 8-bit I/O port operations are not supported, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -76,7 +85,11 @@ IoWrite8 ( =20 Flag =3D FilterBeforeIoWrite (FilterWidth8, Port, &Value); if (Flag) { - __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Por= t)); + if (IsTdxGuest ()) { + TdIoWrite8 (Port, Value); + } else { + __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)P= ort)); + } } FilterAfterIoWrite (FilterWidth8, Port, &Value); =20 @@ -93,6 +106,8 @@ IoWrite8 ( If 16-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to read I/O port. + @param Port The I/O port to read. =20 @return The value read. @@ -111,7 +126,11 @@ IoRead16 ( =20 Flag =3D FilterBeforeIoRead (FilterWidth16, Port, &Data); if (Flag) { + if (IsTdxGuest ()) { + Data =3D TdIoRead16 (Port); + } else { __asm__ __volatile__ ("inw %w1,%w0" : "=3Da" (Data) : "d" ((UINT16)Po= rt)); + } } FilterAfterIoRead (FilterWidth16, Port, &Data); =20 @@ -128,6 +147,8 @@ IoRead16 ( If 16-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -148,7 +169,11 @@ IoWrite16 ( =20 Flag =3D FilterBeforeIoWrite (FilterWidth16, Port, &Value); if (Flag) { - __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Por= t)); + if (IsTdxGuest ()) { + TdIoWrite16 (Port, Value); + } else { + __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)P= ort)); + } } FilterAfterIoWrite (FilterWidth16, Port, &Value); =20 @@ -165,6 +190,8 @@ IoWrite16 ( If 32-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to read I/O port. + @param Port The I/O port to read. =20 @return The value read. @@ -183,7 +210,11 @@ IoRead32 ( =20 Flag =3D FilterBeforeIoRead (FilterWidth32, Port, &Data); if (Flag) { - __asm__ __volatile__ ("inl %w1,%0" : "=3Da" (Data) : "d" ((UINT16)Port= )); + if (IsTdxGuest ()) { + Data =3D TdIoRead32 (Port); + } else { + __asm__ __volatile__ ("inl %w1,%0" : "=3Da" (Data) : "d" ((UINT16)Po= rt)); + } } FilterAfterIoRead (FilterWidth32, Port, &Data); =20 @@ -200,6 +231,8 @@ IoRead32 ( If 32-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -219,7 +252,11 @@ IoWrite32 ( =20 Flag =3D FilterBeforeIoWrite (FilterWidth32, Port, &Value); if (Flag) { - __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port= )); + if (IsTdxGuest ()) { + TdIoWrite32 (Port, Value); + } else { + __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Po= rt)); + } } FilterAfterIoWrite (FilterWidth32, Port, &Value); =20 diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdx.c b/MdePkg/= Library/BaseIoLibIntrinsic/IoLibInternalTdx.c new file mode 100644 index 000000000000..d321cc9f00be --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdx.c @@ -0,0 +1,735 @@ +/** @file + TDX I/O Library routines. + + Copyright (c) 2020-2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include "BaseIoLibIntrinsicInternal.h" +#include +#include +#include +#include +#include "IoLibTdx.h" + +// Size of TDVMCALL Access, including IO and MMIO +#define TDVMCALL_ACCESS_SIZE_1 1 +#define TDVMCALL_ACCESS_SIZE_2 2 +#define TDVMCALL_ACCESS_SIZE_4 4 +#define TDVMCALL_ACCESS_SIZE_8 8 + +// Direction of TDVMCALL Access, including IO and MMIO +#define TDVMCALL_ACCESS_READ 0 +#define TDVMCALL_ACCESS_WRITE 1 + +BOOLEAN mTdxEnabled =3D FALSE; +BOOLEAN mTdxProbed =3D FALSE; + +/** + Check if it is Tdx guest. + + @return TRUE It is Tdx guest + @return FALSE It is not Tdx guest + +**/ +BOOLEAN +EFIAPI +IsTdxGuest ( + VOID + ) +{ + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; + UINT32 LargestEax; + + if (mTdxProbed) { + return mTdxEnabled; + } + + mTdxEnabled =3D FALSE; + + do { + AsmCpuid (0, &LargestEax, &Ebx, &Ecx, &Edx); + + if (Ebx !=3D SIGNATURE_32 ('G', 'e', 'n', 'u') + || Edx !=3D SIGNATURE_32 ('i', 'n', 'e', 'I') + || Ecx !=3D SIGNATURE_32 ('n', 't', 'e', 'l')) { + break; + } + + AsmCpuid (1, NULL, NULL, &Ecx, NULL); + if ((Ecx & BIT31) =3D=3D 0) { + break; + } + + if (LargestEax < 0x21) { + break; + } + + AsmCpuidEx (0x21, 0, &Eax, &Ebx, &Ecx, &Edx); + if (Ebx !=3D SIGNATURE_32 ('I', 'n', 't', 'e') + || Edx !=3D SIGNATURE_32 ('l', 'T', 'D', 'X') + || Ecx !=3D SIGNATURE_32 (' ', ' ', ' ', ' ')) { + break; + } + + mTdxEnabled =3D TRUE; + }while (FALSE); + + mTdxProbed =3D TRUE; + + return mTdxEnabled; +} + + +/** + Reads an 8-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdIoRead8 ( + IN UINTN Port + ) +{ + UINT64 Status; + UINT64 Val; + + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCES= S_READ, Port, 0, &Val); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return (UINT8) Val; +} + +/** + Reads a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdIoRead16 ( + IN UINTN Port + ) +{ + UINT64 Status; + UINT64 Val; + + ASSERT ((Port & 1) =3D=3D 0); + + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCES= S_READ, Port, 0, &Val); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return (UINT16) Val; +} + +/** + Reads a 32-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdIoRead32 ( + IN UINTN Port + ) +{ + UINT64 Status; + UINT64 Val; + + ASSERT ((Port & 3) =3D=3D 0); + + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCES= S_READ, Port, 0, &Val); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return (UINT32) Val; +} + +/** + Writes an 8-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +TdIoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + UINT64 Status; + UINT64 Val; + + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCES= S_WRITE, Port, Val, 0); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return Value; +} + +/** + Writes a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +TdIoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + UINT64 Status; + UINT64 Val; + + ASSERT ((Port & 1) =3D=3D 0); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCES= S_WRITE, Port, Val, 0); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return Value; +} + +/** + Writes a 32-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +TdIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + UINT64 Status; + UINT64 Val; + + ASSERT ((Port & 3) =3D=3D 0); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCES= S_WRITE, Port, Val, 0); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + return Value; +} + +/** + Reads an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdMmioRead8 ( + IN UINTN Address + ) +{ + UINT64 Value; + UINT64 Status; + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACC= ESS_READ, Address, 0, &Value); + if (Status !=3D 0) { + Value =3D *(volatile UINT64*) Address; + } + MemoryFence (); + + return (UINT8) Value; +} + +/** + Writes an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read write registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT8 +EFIAPI +TdMmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + UINT64 Val; + UINT64 Status; + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACC= ESS_WRITE, Address, Val, 0); + if (Status !=3D 0) { + *(volatile UINT8*) Address =3D Value; + } + MemoryFence (); + + return Value; +} + +/** + Reads a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdMmioRead16 ( + IN UINTN Address + ) +{ + UINT64 Value; + UINT64 Status; + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACC= ESS_READ, Address, 0, &Value); + if (Status !=3D 0) { + Value =3D *(volatile UINT64*) Address; + } + MemoryFence (); + + return (UINT16) Value; +} + +/** + Writes a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT16 +EFIAPI +TdMmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + UINT64 Val; + UINT64 Status; + + ASSERT ((Address & 1) =3D=3D 0); + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACC= ESS_WRITE, Address, Val, 0); + if (Status !=3D 0) { + *(volatile UINT16*) Address =3D Value; + } + MemoryFence (); + + return Value; +} + +/** + Reads a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdMmioRead32 ( + IN UINTN Address + ) +{ + UINT64 Value; + UINT64 Status; + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACC= ESS_READ, Address, 0, &Value); + if (Status !=3D 0) { + Value =3D *(volatile UINT64*)Address; + } + MemoryFence (); + + return (UINT32)Value; +} + +/** + Writes a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT32 +EFIAPI +TdMmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + UINT64 Val; + UINT64 Status; + + ASSERT ((Address & 3) =3D=3D 0); + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACC= ESS_WRITE, Address, Val, 0); + if (Status !=3D 0) { + *(volatile UINT32*)Address =3D Value; + } + MemoryFence (); + + return Value; +} + +/** + Reads a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +TdMmioRead64 ( + IN UINTN Address + ) +{ + UINT64 Value; + UINT64 Status; + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_8, TDVMCALL_ACC= ESS_READ, Address, 0, &Value); + if (Status !=3D 0) { + Value =3D *(volatile UINT64*)Address; + } + MemoryFence (); + + return Value; +} + +/** + Writes a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +TdMmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + UINT64 Status; + UINT64 Val; + + ASSERT ((Address & 7) =3D=3D 0); + + Address |=3D TdSharedPageMask (); + + MemoryFence (); + Val =3D Value; + Status =3D TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_8, TDVMCALL_ACC= ESS_WRITE, Address, Val, 0); + if (Status !=3D 0) { + *(volatile UINT64*)Address =3D Value; + } + MemoryFence (); + return Value; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead8 is invoked to read the I/O port fifo. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT8 *Buf8; + UINTN Index; + + Buf8 =3D (UINT8 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + Buf8[Index] =3D TdIoRead8 (Port); + } +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite8 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT8 *Buf8; + UINTN Index; + + Buf8 =3D (UINT8 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + TdIoWrite8 (Port, Buf8[Index]); + } +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead16 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT16 *Buf16; + UINTN Index; + + Buf16 =3D (UINT16 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + Buf16[Index] =3D TdIoRead16 (Port); + } +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite16 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT16 *Buf16; + UINTN Index; + + Buf16 =3D (UINT16 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + TdIoWrite16 (Port, Buf16[Index]); + } +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead32 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + UINT32 *Buf32; + UINTN Index; + + Buf32 =3D (UINT32 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + Buf32[Index] =3D TdIoRead32 (Port); + } +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite32 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + UINT32 *Buf32; + UINTN Index; + + Buf32 =3D (UINT32 *) Buffer; + for (Index =3D 0; Index < Count; Index++) { + TdIoWrite32 (Port, Buf32[Index]); + } +} diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdxNull.c b/Mde= Pkg/Library/BaseIoLibIntrinsic/IoLibInternalTdxNull.c new file mode 100644 index 000000000000..f518d8ffd825 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdxNull.c @@ -0,0 +1,499 @@ +/** @file + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include +#include "BaseIoLibIntrinsicInternal.h" +#include "IoLibTdx.h" + +/** + Check if it is Tdx guest. + + @return TRUE It is Tdx guest + @return FALSE It is not Tdx guest + +**/ +BOOLEAN +EFIAPI +IsTdxGuest ( + VOID + ) +{ + return FALSE; +} + + +/** + Reads an 8-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdIoRead8 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdIoRead16 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 32-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdIoRead32 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes an 8-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +TdIoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +TdIoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 32-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +TdIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdMmioRead8 ( + IN UINTN Address + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read write registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT8 +EFIAPI +TdMmioWrite8 ( + IN UINTN Address, + IN UINT8 Val + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdMmioRead16 ( + IN UINTN Address + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT16 +EFIAPI +TdMmioWrite16 ( + IN UINTN Address, + IN UINT16 Val + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdMmioRead32 ( + IN UINTN Address + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT32 +EFIAPI +TdMmioWrite32 ( + IN UINTN Address, + IN UINT32 Val + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +TdMmioRead64 ( + IN UINTN Address + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +TdMmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead8 is invoked to read the I/O port fifo. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite8 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 16-bit I/O port fifo into a block of memory. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead16 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 16-bit I/O port fifo. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite16 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Reads a 32-bit I/O port fifo into a block of memory. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoRead32 is invoked to read data from the I/O port. + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ) +{ + ASSERT (FALSE); +} + +/** + Writes a block of memory into a 32-bit I/O port fifo. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + In TDX a serial of TdIoWrite32 is invoked to write data to the I/O port. + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ) +{ + ASSERT (FALSE); +} diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c b/MdePkg/Library/= BaseIoLibIntrinsic/IoLibMsc.c index d2bc5f527cf6..4d7945ae496f 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c @@ -16,6 +16,7 @@ =20 =20 #include "BaseIoLibIntrinsicInternal.h" +#include "IoLibTdx.h" =20 // // Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics. @@ -54,6 +55,8 @@ void _ReadWriteBarrier (void); =20 If 8-bit I/O port operations are not supported, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to read I/O port. + @param Port The I/O port to read. =20 @return The value read. @@ -70,9 +73,13 @@ IoRead8 ( =20 Flag =3D FilterBeforeIoRead (FilterWidth8, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - Value =3D (UINT8)_inp ((UINT16)Port); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + Value =3D TdIoRead8 (Port); + } else { + _ReadWriteBarrier (); + Value =3D (UINT8)_inp ((UINT16)Port); + _ReadWriteBarrier (); + } } FilterAfterIoRead (FilterWidth8, Port, &Value); =20 @@ -88,6 +95,8 @@ IoRead8 ( =20 If 8-bit I/O port operations are not supported, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -105,9 +114,13 @@ IoWrite8 ( =20 Flag =3D FilterBeforeIoWrite(FilterWidth8, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - (UINT8)_outp ((UINT16)Port, Value); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + TdIoWrite8 (Port, Value); + } else { + _ReadWriteBarrier (); + (UINT8)_outp ((UINT16)Port, Value); + _ReadWriteBarrier (); + } } FilterAfterIoWrite (FilterWidth8, Port, &Value); =20 @@ -124,6 +137,8 @@ IoWrite8 ( If 16-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to read I/O port. + @param Port The I/O port to read. =20 @return The value read. @@ -142,9 +157,13 @@ IoRead16 ( =20 Flag =3D FilterBeforeIoRead (FilterWidth16, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - Value =3D _inpw ((UINT16)Port); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + Value =3D TdIoRead16 (Port); + } else { + _ReadWriteBarrier (); + Value =3D _inpw ((UINT16)Port); + _ReadWriteBarrier (); + } } FilterBeforeIoRead (FilterWidth16, Port, &Value); =20 @@ -161,6 +180,8 @@ IoRead16 ( If 16-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 16-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -180,9 +201,13 @@ IoWrite16 ( =20 Flag =3D FilterBeforeIoWrite(FilterWidth16, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - _outpw ((UINT16)Port, Value); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + TdIoWrite16 (Port, Value); + } else { + _ReadWriteBarrier (); + _outpw ((UINT16)Port, Value); + _ReadWriteBarrier (); + } } FilterAfterIoWrite (FilterWidth16, Port, &Value); =20 @@ -199,6 +224,8 @@ IoWrite16 ( If 32-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to read I/O port. + @param Port The I/O port to read. =20 @return The value read. @@ -217,9 +244,13 @@ IoRead32 ( =20 Flag =3D FilterBeforeIoRead(FilterWidth32, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - Value =3D _inpd ((UINT16)Port); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + Value =3D TdIoRead32 (Port); + } else { + _ReadWriteBarrier (); + Value =3D _inpd ((UINT16)Port); + _ReadWriteBarrier (); + } } FilterAfterIoRead (FilterWidth32, Port, &Value); =20 @@ -236,6 +267,8 @@ IoRead32 ( If 32-bit I/O port operations are not supported, then ASSERT(). If Port is not aligned on a 32-bit boundary, then ASSERT(). =20 + For Td guest TDVMCALL_IO is invoked to write I/O port. + @param Port The I/O port to write. @param Value The value to write to the I/O port. =20 @@ -255,9 +288,13 @@ IoWrite32 ( =20 Flag =3D FilterBeforeIoWrite(FilterWidth32, Port, &Value); if (Flag) { - _ReadWriteBarrier (); - _outpd ((UINT16)Port, Value); - _ReadWriteBarrier (); + if (IsTdxGuest ()) { + TdIoWrite32 (Port, Value); + } else { + _ReadWriteBarrier (); + _outpd ((UINT16)Port, Value); + _ReadWriteBarrier (); + } } FilterAfterIoWrite (FilterWidth32, Port, &Value); =20 diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibSev.h b/MdePkg/Library/= BaseIoLibIntrinsic/IoLibSev.h new file mode 100644 index 000000000000..e219f8a36a47 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibSev.h @@ -0,0 +1,166 @@ +/** @file + Header file for SEV IO library. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef IOLIB_SEV_H_ +#define IOLIB_SEV_H_ + +#include + +#include +#include + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +SevIoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +SevIoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +SevIoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +SevIoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads an 8-bit I/O port fifo into a block of memory. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +SevIoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into an 8-bit I/O port fifo. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +SevIoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +#endif diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibTdx.h b/MdePkg/Library/= BaseIoLibIntrinsic/IoLibTdx.h new file mode 100644 index 000000000000..3aad197d3b39 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibTdx.h @@ -0,0 +1,411 @@ +/** @file + Header file for Tdx IO library. + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef IOLIB_TDX_H_ +#define IOLIB_TDX_H_ + +/** + Check if it is Tdx guest. + + @return TRUE It is Tdx guest + @return FALSE It is not Tdx guest + +**/ +BOOLEAN +EFIAPI +IsTdxGuest ( + VOID + ); + + +/** + Reads an 8-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdIoRead8 ( + IN UINTN Port + ); + +/** + Reads a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdIoRead16 ( + IN UINTN Port + ); + +/** + Reads a 32-bit I/O port. + + TDVMCALL_IO is invoked to read I/O port. + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdIoRead32 ( + IN UINTN Port + ); + +/** + Writes an 8-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +TdIoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ); + +/** + Writes a 16-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +TdIoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ); + +/** + Writes a 32-bit I/O port. + + TDVMCALL_IO is invoked to write I/O port. + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +TdIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ); + +/** + Reads an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +TdMmioRead8 ( + IN UINTN Address + ); + +/** + Writes an 8-bit MMIO register. + + TDVMCALL_MMIO is invoked to read write registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT8 +EFIAPI +TdMmioWrite8 ( + IN UINTN Address, + IN UINT8 Val + ); + +/** + Reads a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +TdMmioRead16 ( + IN UINTN Address + ); + +/** + Writes a 16-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT16 +EFIAPI +TdMmioWrite16 ( + IN UINTN Address, + IN UINT16 Val + ); + +/** + Reads a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +TdMmioRead32 ( + IN UINTN Address + ); + +/** + Writes a 32-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + + @return Value. + +**/ +UINT32 +EFIAPI +TdMmioWrite32 ( + IN UINTN Address, + IN UINT32 Val + ); + +/** + Reads a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to read MMIO registers. + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +TdMmioRead64 ( + IN UINTN Address + ); + +/** + Writes a 64-bit MMIO register. + + TDVMCALL_MMIO is invoked to write MMIO registers. + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +TdMmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ); + +/** + Reads an 8-bit I/O port fifo into a block of memory in Tdx. + + Reads the 8-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo8 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into an 8-bit I/O port fifo in Tdx. + + Writes the 8-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo8 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads a 16-bit I/O port fifo into a block of memory in Tdx. + + Reads the 16-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo16 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into a 16-bit I/O port fifo in Tdx. + + Writes the 16-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo16 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +/** + Reads a 32-bit I/O port fifo into a block of memory in Tdx. + + Reads the 32-bit I/O fifo port specified by Port. + The port is read Count times, and the read data is + stored in the provided Buffer. + + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + @param Count The number of times to read I/O port. + @param Buffer The buffer to store the read data into. + +**/ +VOID +EFIAPI +TdIoReadFifo32 ( + IN UINTN Port, + IN UINTN Count, + OUT VOID *Buffer + ); + +/** + Writes a block of memory into a 32-bit I/O port fifo in Tdx. + + Writes the 32-bit I/O fifo port specified by Port. + The port is written Count times, and the write data is + retrieved from the provided Buffer. + + This function must guarantee that all I/O write and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Count The number of times to write I/O port. + @param Buffer The buffer to retrieve the write data from. + +**/ +VOID +EFIAPI +TdIoWriteFifo32 ( + IN UINTN Port, + IN UINTN Count, + IN VOID *Buffer + ); + +#endif diff --git a/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm b/MdePkg/= Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm index 106f8881c55c..d02286b4d518 100644 --- a/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm +++ b/MdePkg/Library/BaseIoLibIntrinsic/X64/IoFifoSev.nasm @@ -67,14 +67,14 @@ ASM_PFX(SevNoRepIo): ;-------------------------------------------------------------------------= ----- ; VOID ; EFIAPI -; IoReadFifo8 ( +; SevIoReadFifo8 ( ; IN UINTN Port, // rcx ; IN UINTN Size, // rdx ; OUT VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoReadFifo8) -ASM_PFX(IoReadFifo8): +global ASM_PFX(SevIoReadFifo8) +ASM_PFX(SevIoReadFifo8): xchg rcx, rdx xchg rdi, r8 ; rdi: buffer address; r8: save rdi =20 @@ -103,14 +103,14 @@ ASM_PFX(IoReadFifo8): ;-------------------------------------------------------------------------= ----- ; VOID ; EFIAPI -; IoReadFifo16 ( +; SevIoReadFifo16 ( ; IN UINTN Port, // rcx ; IN UINTN Size, // rdx ; OUT VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoReadFifo16) -ASM_PFX(IoReadFifo16): +global ASM_PFX(SevIoReadFifo16) +ASM_PFX(SevIoReadFifo16): xchg rcx, rdx xchg rdi, r8 ; rdi: buffer address; r8: save rdi =20 @@ -139,14 +139,14 @@ ASM_PFX(IoReadFifo16): ;-------------------------------------------------------------------------= ----- ; VOID ; EFIAPI -; IoReadFifo32 ( +; SevIoReadFifo32 ( ; IN UINTN Port, // rcx ; IN UINTN Size, // rdx ; OUT VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoReadFifo32) -ASM_PFX(IoReadFifo32): +global ASM_PFX(SevIoReadFifo32) +ASM_PFX(SevIoReadFifo32): xchg rcx, rdx xchg rdi, r8 ; rdi: buffer address; r8: save rdi =20 @@ -181,8 +181,8 @@ ASM_PFX(IoReadFifo32): ; IN VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoWriteFifo8) -ASM_PFX(IoWriteFifo8): +global ASM_PFX(SevIoWriteFifo8) +ASM_PFX(SevIoWriteFifo8): xchg rcx, rdx xchg rsi, r8 ; rsi: buffer address; r8: save rsi =20 @@ -211,14 +211,14 @@ ASM_PFX(IoWriteFifo8): ;-------------------------------------------------------------------------= ----- ; VOID ; EFIAPI -; IoWriteFifo16 ( +; SevIoWriteFifo16 ( ; IN UINTN Port, // rcx ; IN UINTN Size, // rdx ; IN VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoWriteFifo16) -ASM_PFX(IoWriteFifo16): +global ASM_PFX(SevIoWriteFifo16) +ASM_PFX(SevIoWriteFifo16): xchg rcx, rdx xchg rsi, r8 ; rsi: buffer address; r8: save rsi =20 @@ -247,14 +247,14 @@ ASM_PFX(IoWriteFifo16): ;-------------------------------------------------------------------------= ----- ; VOID ; EFIAPI -; IoWriteFifo32 ( +; SevIoWriteFifo32 ( ; IN UINTN Port, // rcx ; IN UINTN Size, // rdx ; IN VOID *Buffer // r8 ; ); ;-------------------------------------------------------------------------= ----- -global ASM_PFX(IoWriteFifo32) -ASM_PFX(IoWriteFifo32): +global ASM_PFX(SevIoWriteFifo32) +ASM_PFX(SevIoWriteFifo32): xchg rcx, rdx xchg rsi, r8 ; rsi: buffer address; r8: save rsi =20 --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81478): https://edk2.groups.io/g/devel/message/81478 Mute This Topic: https://groups.io/mt/86085732/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81479+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81479+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405219; cv=none; d=zohomail.com; s=zohoarc; b=UjqNulQlkeBw1PMRMIZP23dGHsRclIfAL2dJFEXOTVIveWSGJiTZnXpYIwKNptObdMSkeDROeVYZ99O0p4m2CCyNb8a6v+WHN7+il4vh1doajEpzevFQpWFze1ZBOD0LxCA+L4gwG/O3dkcjDEjDPdlqM/V3FHRvm4vwWR06CEE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405219; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=iCWJKuVBblkWKUVEAqiOsvP2LG5+pkXM2rqB0rZtV0c=; b=DG2PyQZslpDZrC8FU4F69SF6pYPsXFlagOl4EOll7SKMvOkN+ESh3dnkPpTnV38LLm3t7qAx1fRlMPUjVgAQtHAM/3gjE1wbxV2AZ7zm0a1Obv8d5vhQpH8dZi4Uwu1X5P0mtMRjXdQk/KccExqjYVSU/yS6x4LFC/+qt3PC/Vg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81479+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405219428734.6303101032056; Mon, 4 Oct 2021 20:40:19 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id m9jxYY1788612x6N05DMc2on; Mon, 04 Oct 2021 20:40:19 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:18 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958102" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958102" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:17 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828529" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:15 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Eric Dong , Ray Ni , Rahul Kumar , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 07/28] UefiCpuPkg: Support TDX in BaseXApicX2ApicLib Date: Tue, 5 Oct 2021 11:39:18 +0800 Message-Id: <0dcb1ac3ad788cc7a4fd293fcf183b6ea9bdffb9.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 4nLwD0TyTl6ckrrIcPwgVZwPx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405219; bh=nDNo4T9LaCaNQcOcOIE2Nuk6M/6qkyUPxyUKkTo327o=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=s7b8g6ANa7fOILJbNohzEPAaAmAPpOmw4U6OJnMzmuef8yM6fdYZSXRsqOccYfHzVUX Xk1/+4qJYkfAx1OU9dpwPVnmvI3yMH/2Z2PnUljHSuusULfifZHIqUcKe9bMRlGGpRQsV BzNzo55RGZ7fkBYG9VOzpXYfEA0EcnggPXY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405221141100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 MSR is accessed in BaseXApicX2ApicLib. In TDX some MSRs are accessed directly from/to CPU. Some should be accessed via explicit requests from the host VMM using TDCALL(TDG.VP.VMCALL). This is done by the help of TdxLib. Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- .../BaseXApicX2ApicLib/BaseXApicX2ApicLib.c | 233 +++++++++++++++++- .../BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf | 1 + UefiCpuPkg/UefiCpuPkg.dsc | 1 + 3 files changed, 227 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/U= efiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c index cdcbca046191..eaa132ea30f4 100644 --- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c +++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c @@ -23,11 +23,227 @@ #include #include #include +#include +#include =20 // // Library internal functions // =20 +BOOLEAN mBaseXApicIsTdxEnabled =3D FALSE; +BOOLEAN mBaseXApicTdxProbed =3D FALSE; + +/** + Check if it is Tdx guest. + + @return TRUE It is Tdx guest + @return FALSE It is not Tdx guest + +**/ +BOOLEAN +EFIAPI +BaseXApicIsTdxGuest ( + VOID + ) +{ + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; + UINT32 LargestEax; + + if (mBaseXApicTdxProbed) { + return mBaseXApicIsTdxEnabled; + } + + mBaseXApicIsTdxEnabled =3D FALSE; + + do { + AsmCpuid (0, &LargestEax, &Ebx, &Ecx, &Edx); + + if (Ebx !=3D SIGNATURE_32 ('G', 'e', 'n', 'u') + || Edx !=3D SIGNATURE_32 ('i', 'n', 'e', 'I') + || Ecx !=3D SIGNATURE_32 ('n', 't', 'e', 'l')) { + break; + } + + AsmCpuid (1, NULL, NULL, &Ecx, NULL); + if ((Ecx & BIT31) =3D=3D 0) { + break; + } + + if (LargestEax < 0x21) { + break; + } + + AsmCpuidEx (0x21, 0, &Eax, &Ebx, &Ecx, &Edx); + if (Ebx !=3D SIGNATURE_32 ('I', 'n', 't', 'e') + || Edx !=3D SIGNATURE_32 ('l', 'T', 'D', 'X') + || Ecx !=3D SIGNATURE_32 (' ', ' ', ' ', ' ')) { + break; + } + + mBaseXApicIsTdxEnabled =3D TRUE; + }while (FALSE); + + mBaseXApicTdxProbed =3D TRUE; + + return mBaseXApicIsTdxEnabled; +} + + +/** + Some MSRs in TDX are directly read/write from/to CPU. + + @param MsrIndex Index of the MSR + @retval TRUE MSR direct read/write from/to CPU. + @retval FALSE MSR not direct read/write from/to CPU. + +**/ +BOOLEAN +EFIAPI +AccessMsrNative ( + IN UINT32 MsrIndex + ) +{ + switch (MsrIndex) { + case MSR_IA32_X2APIC_TPR: + case MSR_IA32_X2APIC_PPR: + case MSR_IA32_X2APIC_EOI: + case MSR_IA32_X2APIC_ISR0: + case MSR_IA32_X2APIC_ISR1: + case MSR_IA32_X2APIC_ISR2: + case MSR_IA32_X2APIC_ISR3: + case MSR_IA32_X2APIC_ISR4: + case MSR_IA32_X2APIC_ISR5: + case MSR_IA32_X2APIC_ISR6: + case MSR_IA32_X2APIC_ISR7: + case MSR_IA32_X2APIC_TMR0: + case MSR_IA32_X2APIC_TMR1: + case MSR_IA32_X2APIC_TMR2: + case MSR_IA32_X2APIC_TMR3: + case MSR_IA32_X2APIC_TMR4: + case MSR_IA32_X2APIC_TMR5: + case MSR_IA32_X2APIC_TMR6: + case MSR_IA32_X2APIC_TMR7: + case MSR_IA32_X2APIC_IRR0: + case MSR_IA32_X2APIC_IRR1: + case MSR_IA32_X2APIC_IRR2: + case MSR_IA32_X2APIC_IRR3: + case MSR_IA32_X2APIC_IRR4: + case MSR_IA32_X2APIC_IRR5: + case MSR_IA32_X2APIC_IRR6: + case MSR_IA32_X2APIC_IRR7: + return TRUE; + default: + break; + } + return FALSE; +} + +/** + Read MSR value. + + @param MsrIndex Index of the MSR to read + @retval 64-bit Value of MSR. + +**/ +UINT64 +EFIAPI +ReadMsrReg64 ( + IN UINT32 MsrIndex + ) +{ + UINT64 Val; + UINT64 Status; + if (!AccessMsrNative (MsrIndex) && BaseXApicIsTdxGuest ()) { + Status =3D TdVmCall (TDVMCALL_RDMSR, (UINT64) MsrIndex, 0, 0, 0, &Val); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + } else { + Val =3D AsmReadMsr64 (MsrIndex); + } + return Val; +} + +/** + Write to MSR. + + @param MsrIndex Index of the MSR to write to + @param Val Value to be written to the MSR + +**/ +VOID +EFIAPI +WriteMsrReg64 ( + IN UINT32 MsrIndex, + IN UINT64 Val + ) +{ + UINT64 Status; + if (!AccessMsrNative (MsrIndex) && BaseXApicIsTdxGuest ()) { + Status =3D TdVmCall (TDVMCALL_WRMSR, (UINT64) MsrIndex, Val, 0, 0, 0); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + } else { + AsmWriteMsr64 (MsrIndex, Val); + } +} + +/** + Read MSR value. + + @param MsrIndex Index of the MSR to read + @retval 32-bit Value of MSR. + +**/ +UINT32 +EFIAPI +ReadMsrReg32 ( + IN UINT32 MsrIndex + ) +{ + UINT64 Val; + UINT64 Status; + if (!AccessMsrNative (MsrIndex) && BaseXApicIsTdxGuest ()) { + Status =3D TdVmCall (TDVMCALL_RDMSR, (UINT64) MsrIndex, 0, 0, 0, &Val); + if (Status !=3D 0) { + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + } else { + Val =3D AsmReadMsr32 (MsrIndex); + } + return (UINT32)(UINTN) Val; +} + +/** + Write to MSR. + + @param MsrIndex Index of the MSR to write to + @param Val Value to be written to the MSR + +**/ +VOID +EFIAPI +WriteMsrReg32 ( + IN UINT32 MsrIndex, + IN UINT32 Val + ) +{ + UINT64 Status; + if (!AccessMsrNative (MsrIndex) && BaseXApicIsTdxGuest ()) { + Status =3D TdVmCall (TDVMCALL_WRMSR, (UINT64) MsrIndex, (UINT64) Val, = 0, 0, 0); + if (Status !=3D 0) { + DEBUG((DEBUG_ERROR, "WriteMsrReg32 returned failure. Status=3D0x%llx= \n", Status)); + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + } else { + AsmWriteMsr32 (MsrIndex, Val); + } +} + /** Determine if the CPU supports the Local APIC Base Address MSR. =20 @@ -77,7 +293,7 @@ GetLocalApicBaseAddress ( return PcdGet32 (PcdCpuLocalApicBaseAddress); } =20 - ApicBaseMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_APIC_BASE); + ApicBaseMsr.Uint64 =3D ReadMsrReg64 (MSR_IA32_APIC_BASE); =20 return (UINTN)(LShiftU64 ((UINT64) ApicBaseMsr.Bits.ApicBaseHi, 32)) + (((UINTN)ApicBaseMsr.Bits.ApicBase) << 12); @@ -108,12 +324,12 @@ SetLocalApicBaseAddress ( return; } =20 - ApicBaseMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_APIC_BASE); + ApicBaseMsr.Uint64 =3D ReadMsrReg64 (MSR_IA32_APIC_BASE); =20 ApicBaseMsr.Bits.ApicBase =3D (UINT32) (BaseAddress >> 12); ApicBaseMsr.Bits.ApicBaseHi =3D (UINT32) (RShiftU64((UINT64) BaseAddress= , 32)); =20 - AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); + WriteMsrReg64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); } =20 /** @@ -153,7 +369,7 @@ ReadLocalApicReg ( ASSERT (MmioOffset !=3D XAPIC_ICR_HIGH_OFFSET); =20 MsrIndex =3D (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS; - return AsmReadMsr32 (MsrIndex); + return ReadMsrReg32 (MsrIndex); } } =20 @@ -202,7 +418,7 @@ WriteLocalApicReg ( // Use memory fence here to force the serializing semantics to be cons= isent with xAPIC mode. // MemoryFence (); - AsmWriteMsr32 (MsrIndex, Value); + WriteMsrReg32 (MsrIndex, Value); } } =20 @@ -309,7 +525,7 @@ GetApicMode ( return LOCAL_APIC_MODE_XAPIC; } =20 - ApicBaseMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_APIC_BASE); + ApicBaseMsr.Uint64 =3D ReadMsrReg64 (MSR_IA32_APIC_BASE); // // Local APIC should have been enabled // @@ -350,13 +566,14 @@ SetApicMode ( =20 CurrentMode =3D GetApicMode (); if (CurrentMode =3D=3D LOCAL_APIC_MODE_XAPIC) { + switch (ApicMode) { case LOCAL_APIC_MODE_XAPIC: break; case LOCAL_APIC_MODE_X2APIC: - ApicBaseMsr.Uint64 =3D AsmReadMsr64 (MSR_IA32_APIC_BASE); + ApicBaseMsr.Uint64 =3D ReadMsrReg64 (MSR_IA32_APIC_BASE); ApicBaseMsr.Bits.EXTD =3D 1; - AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); + WriteMsrReg64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); break; default: ASSERT (FALSE); diff --git a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf b= /UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf index 1e2a4f8b790f..1276f6ec06d6 100644 --- a/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf +++ b/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf @@ -39,6 +39,7 @@ IoLib PcdLib UefiCpuLib + TdxLib =20 [Pcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES= _CONSUMES diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index 870b45284087..e5e6bf77c8e2 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -61,6 +61,7 @@ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem= entLibNull.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf =20 [LibraryClasses.common.SEC] PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.= inf --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81479): https://edk2.groups.io/g/devel/message/81479 Mute This Topic: https://groups.io/mt/86085736/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81480+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81480+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405221; cv=none; d=zohomail.com; s=zohoarc; b=C4LTsCR7tMTSoI4ajfboZagJZs/71Xod2mMzn2VWNc3FVRO2gn1jikmV5OknJd1jOZOw0e60uZq07Mj8n+GwDaLjxLT0usN75wuUyi1d63V0+ImLgL0ztoNZ1sJyBQhqTD0Gi764gCH4SQqWytUkl6DAZrbDUAAUhw9Fvfg/u2w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405221; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=w6uzQA3wDsZ4ze0FPoXF2yV/3Dm+799vfwqsFs1AFfg=; b=FdjWOEJyMDaQ6rXDrl65ffh9glxnDTjmKWV45TuDYsHID9WvfM5kx4HrZpxc1pLbEB81GM6iG+GSMxAAp4I2UIE8lfWYbyii9Z/8v/0YkvAlQoWONPQKxYnJ6eApCmX/iRuM8SNQ6dhibJSCX3+eRlrfCaFBOGe/nnstztwx+Ok= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81480+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405221795378.64497469576975; Mon, 4 Oct 2021 20:40:21 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id CxclYY1788612xwtY6HMPycD; Mon, 04 Oct 2021 20:40:21 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:21 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958116" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958116" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:20 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828539" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:18 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH V2 08/28] UefiCpuPkg: Add VmTdExitLibNull Date: Tue, 5 Oct 2021 11:39:19 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 50xNl9mAP1cByWXvWmJqTLTIx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405221; bh=NUSydC2oQwL19sxylUkhV0gX7aTC4b32/tN3H6g767k=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=oey5PHH/DpMuysHUswa1XpWryYGHy7Jdn29uD2xJzOxGwTo+YU1fDadxTd5uptQaLGF osZqO0a/d2aVRt5J5WAqyE0sUiW4FgqTDrbpchdN/dOwVGPRCBLk78kBeT+yMtf0Rgkaq Lw/MEUqwYELZ0WubmLFa3N2l+JtFW2lRc/s= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405223293100005 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 VmTdExitLib performs the necessary processing to handle a #VE exception. VmTdExitLibNull is a NULL instance of VmTdExitLib which provides a default limited interface. A full feature version of VmTdExitLib should be created later (for example in OvmfPkg). Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Signed-off-by: Min Xu --- UefiCpuPkg/Include/Library/VmTdExitLib.h | 47 +++++++++++++++++++ .../Library/VmTdExitLibNull/VmTdExitLibNull.c | 37 +++++++++++++++ .../VmTdExitLibNull/VmTdExitLibNull.inf | 34 ++++++++++++++ UefiCpuPkg/UefiCpuPkg.dec | 3 ++ UefiCpuPkg/UefiCpuPkg.dsc | 2 + 5 files changed, 123 insertions(+) create mode 100644 UefiCpuPkg/Include/Library/VmTdExitLib.h create mode 100644 UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.c create mode 100644 UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf diff --git a/UefiCpuPkg/Include/Library/VmTdExitLib.h b/UefiCpuPkg/Include/= Library/VmTdExitLib.h new file mode 100644 index 000000000000..a55a76dc7a30 --- /dev/null +++ b/UefiCpuPkg/Include/Library/VmTdExitLib.h @@ -0,0 +1,47 @@ +/** @file + Public header file for the VMTDEXIT Support library class. + + This library class defines some routines used when invoking the VMEXIT + instruction in support of VMX and TDX to handle #VE exceptions. + + Copyright (c) 2020 - 2021, Intel Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef VMTD_EXIT_LIB_H_ +#define VMTD_EXIT_LIB_H_ + +#include +#include +#include + +#define VE_EXCEPTION 20 + +/** + Handle a #VE exception. + + Performs the necessary processing to handle a #VE exception. + + The base library function returns an error equal to VE_EXCEPTION, + to be propagated to the standard exception handling stack. + + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VE not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VE handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +VmTdExitHandleVe ( + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +#endif diff --git a/UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.c b/UefiCpu= Pkg/Library/VmTdExitLibNull/VmTdExitLibNull.c new file mode 100644 index 000000000000..a632abfab498 --- /dev/null +++ b/UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.c @@ -0,0 +1,37 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include + +/** + Handle a #VE exception. + + Performs the necessary processing to handle a #VE exception. + + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VE not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VE handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +VmTdExitHandleVe ( + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + *ExceptionType =3D VE_EXCEPTION; + + return EFI_UNSUPPORTED; +} diff --git a/UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf b/UefiC= puPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf new file mode 100644 index 000000000000..ae9af1b7f56b --- /dev/null +++ b/UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf @@ -0,0 +1,34 @@ +## @file +# VMTDEXIT Support Library. +# +# Copyright (c) 2020, Intel Inc. All rights reserved.
+# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D VmTdExitLibNull + FILE_GUID =3D 79BD5323-6CF4-4ECF-A132-F7D31EEADC1E + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D VmTdExitLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 IA32 +# + +[Sources.common] + VmTdExitLibNull.c + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index 62acb291f309..439bfc86a112 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -62,6 +62,9 @@ ## @libraryclass Provides function for loading microcode. MicrocodeLib|Include/Library/MicrocodeLib.h =20 + ## @libraryclass Provides function to support VMTDEXIT processing. + VmgExitLib|Include/Library/VmTdExitLib.h + [Guids] gUefiCpuPkgTokenSpaceGuid =3D { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa,= 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }} gMsegSmramGuid =3D { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1,= 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }} diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index e5e6bf77c8e2..50bb49f95b17 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -60,6 +60,7 @@ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeC= offExtraActionLibNull.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurem= entLibNull.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf TdxLib|MdePkg/Library/TdxLib/TdxLib.inf =20 @@ -159,6 +160,7 @@ UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf UefiCpuPkg/SecCore/SecCore.inf --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81480): https://edk2.groups.io/g/devel/message/81480 Mute This Topic: https://groups.io/mt/86085737/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81481+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81481+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405223; cv=none; d=zohomail.com; s=zohoarc; b=CKYoY1mRLoWW65pVtfzgQNU4L8IR4eWIY9x20WOWr7KemneFLR8zKKUnWm/O6Tezh0OJynYqdWzLoA340HcO+9+AquytvHK7VBRXm3jZvtB9XS/yj7fjHVs2h14h6gWFka5Ic+LjFlm90+rhSkMC0IarqWuky25yr0FsZi7O2pQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405223; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=aGF+MdGgl4E5eFScxMa5OdZJj5+v8tKhuM2rT4gj4o0=; b=nFqlpzDjaW786z04v3czho/HX0nll5qhE1pQInbHkQ4bdGRye+Ec8oWtLz9M4nGs08K0nZdP/QbT/A1lFQa3q/AbCMSRp+KVV8UMgUoc3kLAqsuI2a7XifGNI4CTtbGsNjg7EpzGLOakRK5MnhorZ6ojt/qZ5zv6EDykNXpHRWk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81481+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405223443265.73950231203196; Mon, 4 Oct 2021 20:40:23 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id vRSTYY1788612xjMwdiu6vx5; Mon, 04 Oct 2021 20:40:23 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:22 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958129" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958129" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:22 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828544" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:21 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu Subject: [edk2-devel] [PATCH V2 09/28] UefiPayloadPkg: Prepare UefiPayloadPkg to use the VmTdExitLib library Date: Tue, 5 Oct 2021 11:39:20 +0800 Message-Id: <42c1350e465a222be93898a8e70ef5a5b16e62c4.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: QHkf7a9jrL3wiwEKK0UyFikmx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405223; bh=OPAV0Zy85azy+ryXR2VFO4t9wW62xmGlHvc4zkDstVE=; h=Cc:Date:From:Reply-To:Subject:To; b=PzIe5ivt0R+jIA39nVXE8opHgElQ2sWRf1YPJQLCxkhipr97ZDWsuIELIEUwJO3Kh/e X18Hbilj3DvzCdlLAfkC/BUWjuGrKy3+jXwK0Sv3fZ6NfY3EY9RY6XlzmE8l6EY8EpQwT Dr1Fn04HLCFxL/BmVss8fWYHNBPUVHN33oY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405225268100010 Content-Type: text/plain; charset="utf-8" RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Various CpuExceptionHandlerLib libraries will updated to use the new VmTdExitLib library. To prevent any build breakage, update the UefiPayloadPkg.dsc that use a form of the CpuExceptionHandlerLib library to include the VmTdExitLib library. Guo Dong Ray Ni Maurice Ma Benjamin You Jiewen Yao Signed-off-by: Min Xu --- UefiPayloadPkg/UefiPayloadPkg.dsc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayload= Pkg.dsc index 9319422efe4b..0522bbc52742 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -245,6 +245,7 @@ VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyL= ib.inf VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/Var= iablePolicyHelperLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf =20 [LibraryClasses.common.SEC] HobLib|UefiPayloadPkg/Library/PayloadEntryHobLib/HobLib.inf @@ -263,6 +264,7 @@ !endif CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuE= xceptionHandlerLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.DXE_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -275,6 +277,7 @@ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuE= xceptionHandlerLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.DXE_RUNTIME_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81481): https://edk2.groups.io/g/devel/message/81481 Mute This Topic: https://groups.io/mt/86085738/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81482+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81482+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405225; cv=none; d=zohomail.com; s=zohoarc; b=SiswH5/rzFn9h4ozuCoE/OyMDfHYhBFKStn/LYkSVJR1qSZftAa7Pxy59LglhzEYnuumBKqsOcwTrSY3Uy6YJpbZC8A5ey6fmuYEC7Cn/QJtnv1KBFYbZ5sSTSe8cPjJkWSSmfQW4z2PeCPYXDoMo2w+AuMTeLzs8yATvIR8RlI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405225; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=SbvNVYo6UNzR9N6NjVQYjvWnQ+SQPizQm1CG6QCgrVg=; b=Edk+jCzN/YM6nkfnOU51b2HGtAq/7cFIIij03mShM92RQurj2+1Z+J/VadKh3gA06XdRyZJ9fSoiZGP9SMu4xpZvgnGM+ZAUHmMJLsuIJ2u5PWVy6/zTfZm3WWfaPdAVpfaffaBxI7X6foNYoFhdqkPmpfX102NHrhgb49JQ8kU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81482+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405225536803.4323641519782; Mon, 4 Oct 2021 20:40:25 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id df9HYY1788612xrQyGWy1POJ; Mon, 04 Oct 2021 20:40:25 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:24 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958148" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958148" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:24 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828556" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:22 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 10/28] OvmfPkg: Prepare OvmfPkg to use the VmTdExitLib library Date: Tue, 5 Oct 2021 11:39:21 +0800 Message-Id: <4b5d6f4da5311d80e36221f34a5384e491bf9aaf.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: uLQYpZxQe4xSe0YkcKRF4Sadx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405225; bh=S2wEH3yqjHOHlJqRrrPh59T49oNi39toV2I/dzqtv9A=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=WtBXaY0IUT9BDlBxXzF3KdabQqSfSXzbkWCAiKopp8VABWt5TEFfKDKsyfHpMl97gDQ /IuGBwYQbcQy6dLp8qf02umeSEz+GZwfCtzJbDYqOAQUyX8CshXzPNSsNeGLX1hYdbqFv KHMoQL7Cql8zCJx2Oj+trgZUvklcHxCJTeo= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405227417100002 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Various CpuExceptionHandlerLib libraries will updated to use the new VmTdExitLib library. To prevent any build breakage, update the OvmfPkg DSC files that use a form of the CpuExceptionHandlerLib library to include the VmTdExitLib library. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/OvmfXen.dsc | 1 + 4 files changed, 4 insertions(+) diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 6a5be97c059d..1f75075152a6 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -243,6 +243,7 @@ [LibraryClasses.common] BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 71227d1b709a..771b08088b96 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -247,6 +247,7 @@ [LibraryClasses.common] BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 52f7598cf1c7..162858e2659b 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -247,6 +247,7 @@ [LibraryClasses.common] BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc index a31519e356b7..5fce410523f8 100644 --- a/OvmfPkg/OvmfXen.dsc +++ b/OvmfPkg/OvmfXen.dsc @@ -227,6 +227,7 @@ [LibraryClasses.common] BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf =20 [LibraryClasses.common.SEC] QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81482): https://edk2.groups.io/g/devel/message/81482 Mute This Topic: https://groups.io/mt/86085739/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81483+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81483+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405228; cv=none; d=zohomail.com; s=zohoarc; b=cUyLNp51Co6ikb5DpvCMtTnUl55EEl3MXQnVcUfLUblHWEbB4VVTLNlxYducS/mnkT8yN+OHHohsGTEHh1RNPRRKdg1Tiibu5Clguq9vebLCg2mTqpQF6Z3li41L77MCzGPflRyx3orG5dPteS4jwkxS5G+Br8IOBi4WpDWYPNk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405228; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=NqYNDJ7RhH+HvqkAtpXrsVg+fK5wJJ76GQSJUFrNydk=; b=k/erjXXtyOArWdOzicPfKynEVChCQqplGt0qeukBadUy0+rzBw4jIrWo0NsiS8X0HNxfX/zbtQKCPaB82HeLrTO4D+SASDXTeJbUX37+DXi91sAmBey9miQOU5mwMbwi1cQQ8twnZIJcQ4FOyOZCAxBDsVWowmfhX9l9XEc1JjE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81483+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 163340522870851.8157199088314; Mon, 4 Oct 2021 20:40:28 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id Q0l8YY1788612xIr5Ay8x6WD; Mon, 04 Oct 2021 20:40:28 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:27 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958165" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958165" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:27 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828576" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:25 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jiewen Yao , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Tom Lendacky Subject: [edk2-devel] [PATCH V2 11/28] OvmfPkg: Implement library support for VmTdExitLib in Ovmf Date: Tue, 5 Oct 2021 11:39:22 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: t3t0iznu2x0ILrJyuHf6mFeCx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405228; bh=eLWZU04AKPLwqzGn7FHsQe2a+Wa7phw9Py5+C/5pN3k=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=JozP5bTxDyGsBHroq2Xr3QYNY6+4Uer319wX0Y3wV4GEqhcHzH/5VFWLfigMLuJcZyF mq3qKmZHuoRFcq9Y3stWnI2FNbvcw6YCyP0/jW1ve57VhfFNHNbVcw4MEk2dBBWwsdTiL AbEeWkvmvRhW7HKueHbvttvDBlISCkLeGa4= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405229603100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 The base VmTdExitLib library provides a default limited interface. As it does not provide full support, create an OVMF version of this library to begin the process of providing full support of TDX within OVMF. PcdIgnoreVeHalt is created in OvmfPkg.dec to ignore the VE halt in TDX. Cc: Ard Biesheuvel Cc: Jiewen Yao Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Library/VmTdExitLib/VmTdExitLib.inf | 39 ++ .../Library/VmTdExitLib/VmTdExitVeHandler.c | 515 ++++++++++++++++++ OvmfPkg/OvmfPkg.dec | 3 + 3 files changed, 557 insertions(+) create mode 100644 OvmfPkg/Library/VmTdExitLib/VmTdExitLib.inf create mode 100644 OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c diff --git a/OvmfPkg/Library/VmTdExitLib/VmTdExitLib.inf b/OvmfPkg/Library/= VmTdExitLib/VmTdExitLib.inf new file mode 100644 index 000000000000..84e308621f7f --- /dev/null +++ b/OvmfPkg/Library/VmTdExitLib/VmTdExitLib.inf @@ -0,0 +1,39 @@ +## @file +# VMTDEXIT Support Library. +# +# Copyright (c) 2020, Intel Inc. All rights reserved.
+# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D VmTdExitLib + FILE_GUID =3D b29eabb0-f9a3-11ea-8b6e-0800200c9a66 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D VmTdExitLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources.common] + VmTdExitVeHandler.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + TdxLib + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdIgnoreVeHalt diff --git a/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c b/OvmfPkg/Libr= ary/VmTdExitLib/VmTdExitVeHandler.c new file mode 100644 index 000000000000..6e41261cd108 --- /dev/null +++ b/OvmfPkg/Library/VmTdExitLib/VmTdExitVeHandler.c @@ -0,0 +1,515 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +typedef union { + struct { + UINT32 Eax; + UINT32 Edx; + } Regs; + UINT64 Val; +} MSR_DATA; + +typedef union { + UINT8 Val; + struct { + UINT8 B:1; + UINT8 X:1; + UINT8 R:1; + UINT8 W:1; + } Bits; +} REX; + +typedef union { + UINT8 Val; + struct { + UINT8 Rm:3; + UINT8 Reg:3; + UINT8 Mod:2; + } Bits; +} MODRM; + +typedef struct { + UINT64 Regs[4]; +} CPUID_DATA; + +/** + Handle an CPUID event. + + Use the TDVMCALL instruction to handle cpuid #ve + + @param[in, out] Regs x64 processor context + @param[in] Veinfo VE Info + + @retval 0 Event handled successfully + @return New exception value to propagate +**/ +STATIC +UINT64 +EFIAPI +CpuIdExit ( + IN EFI_SYSTEM_CONTEXT_X64 *Regs, + IN TDCALL_VEINFO_RETURN_DATA *Veinfo + ) +{ + CPUID_DATA CpuIdData; + UINT64 Status; + + Status =3D TdVmCallCpuid (Regs->Rax, Regs->Rcx, &CpuIdData); + + if (Status =3D=3D 0) { + Regs->Rax =3D CpuIdData.Regs[0]; + Regs->Rbx =3D CpuIdData.Regs[1]; + Regs->Rcx =3D CpuIdData.Regs[2]; + Regs->Rdx =3D CpuIdData.Regs[3]; + } + + return Status; +} + +/** + Handle an IO event. + + Use the TDVMCALL instruction to handle either an IO read or an IO write. + + @param[in, out] Regs x64 processor context + @param[in] Veinfo VE Info + + @retval 0 Event handled successfully + @return New exception value to propagate +**/ +STATIC +UINT64 +EFIAPI +IoExit ( + IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, + IN TDCALL_VEINFO_RETURN_DATA *Veinfo + ) +{ + BOOLEAN Write; + UINTN Size; + UINTN Port; + UINT64 Val; + UINT64 RepCnt; + UINT64 Status; + + Val =3D 0; + Write =3D Veinfo->ExitQualification.Io.Direction ? FALSE : TRUE; + Size =3D Veinfo->ExitQualification.Io.Size + 1; + Port =3D Veinfo->ExitQualification.Io.Port; + + if (Veinfo->ExitQualification.Io.String) { + // + // If REP is set, get rep-cnt from Rcx + // + RepCnt =3D Veinfo->ExitQualification.Io.Rep ? Regs->Rcx : 1; + + while (RepCnt) { + Val =3D 0; + if (Write =3D=3D TRUE) { + CopyMem (&Val, (VOID *) Regs->Rsi, Size); + Regs->Rsi +=3D Size; + } + + Status =3D TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, = Val, (Write ? NULL : &Val)); + if (Status !=3D 0) { + break; + } + if (Write =3D=3D FALSE) { + CopyMem ((VOID *) Regs->Rdi, &Val, Size); + Regs->Rdi +=3D Size; + } + + if (Veinfo->ExitQualification.Io.Rep) { + Regs->Rcx -=3D 1; + } + RepCnt -=3D 1; + } + } else { + if (Write =3D=3D TRUE) { + CopyMem (&Val, (VOID *) &Regs->Rax, Size); + } + Status =3D TdVmCall (EXIT_REASON_IO_INSTRUCTION, Size, Write, Port, Va= l, (Write ? NULL : &Val)); + if ((Status =3D=3D 0) && (Write =3D=3D FALSE)) { + CopyMem ((VOID *) &Regs->Rax, &Val, Size); + } + } + return Status; +} + +/** + Handle an READ MSR event. + + Use the TDVMCALL instruction to handle msr read + + @param[in, out] Regs x64 processor context + @param[in] Veinfo VE Info + + @retval 0 Event handled successfully + @return New exception value to propagate +**/ +STATIC +UINT64 +ReadMsrExit ( + IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, + IN TDCALL_VEINFO_RETURN_DATA *Veinfo + ) +{ + MSR_DATA Data; + UINT64 Status; + + Status =3D TdVmCall (EXIT_REASON_MSR_READ, Regs->Rcx, 0, 0, 0, &Data); + if (Status =3D=3D 0) { + Regs->Rax =3D Data.Regs.Eax; + Regs->Rdx =3D Data.Regs.Edx; + } + + return Status; +} + +/** + Handle an WRITE MSR event. + + Use the TDVMCALL instruction to handle msr write + + @param[in, out] Regs x64 processor context + @param[in] Veinfo VE Info + + @retval 0 Event handled successfully + @return New exception value to propagate +**/ +STATIC +UINT64 +WriteMsrExit ( + IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, + IN TDCALL_VEINFO_RETURN_DATA *Veinfo + ) +{ + UINT64 Status; + MSR_DATA Data; + + Data.Regs.Eax =3D (UINT32) Regs->Rax; + Data.Regs.Edx =3D (UINT32) Regs->Rdx; + + Status =3D TdVmCall (EXIT_REASON_MSR_WRITE, Regs->Rcx, Data.Val, 0, 0, = NULL); + + return Status; +} + +STATIC +VOID +EFIAPI +TdxDecodeInstruction ( + IN UINT8 *Rip +) +{ + UINTN i; + DEBUG ((DEBUG_INFO,"TDX: #TD[EPT] instruction (%p):", Rip)); + for (i =3D 0; i < 15; i++) { + DEBUG ((DEBUG_INFO, "%02x:", Rip[i])); + } + DEBUG ((DEBUG_INFO, "\n")); +} + +#define TDX_DECODER_BUG_ON(x) \ + if ((x)) { \ + TdxDecodeInstruction(Rip); \ + TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \ + } + +STATIC +UINT64 * +EFIAPI +GetRegFromContext ( + IN EFI_SYSTEM_CONTEXT_X64 *Regs, + IN UINTN RegIndex +) +{ + switch (RegIndex) { + case 0: return &Regs->Rax; break; + case 1: return &Regs->Rcx; break; + case 2: return &Regs->Rdx; break; + case 3: return &Regs->Rbx; break; + case 4: return &Regs->Rsp; break; + case 5: return &Regs->Rbp; break; + case 6: return &Regs->Rsi; break; + case 7: return &Regs->Rdi; break; + case 8: return &Regs->R8; break; + case 9: return &Regs->R9; break; + case 10: return &Regs->R10; break; + case 11: return &Regs->R11; break; + case 12: return &Regs->R12; break; + case 13: return &Regs->R13; break; + case 14: return &Regs->R14; break; + case 15: return &Regs->R15; break; + } + return NULL; +} + +/** + Handle an MMIO event. + + Use the TDVMCALL instruction to handle either an mmio read or an mmio wr= ite. + + @param[in, out] Regs x64 processor context + @param[in] Veinfo VE Info + + @retval 0 Event handled successfully + @return New exception value to propagate +**/ +STATIC +INTN +EFIAPI +MmioExit ( + IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs, + IN TDCALL_VEINFO_RETURN_DATA *Veinfo + ) +{ + UINT64 Status; + UINT32 MmioSize; + UINT32 RegSize;; + UINT8 OpCode; + BOOLEAN SeenRex; + UINT64 *Reg; + UINT8 *Rip; + UINT64 Val; + UINT32 OpSize; + MODRM ModRm; + REX Rex; + + Rip =3D (UINT8 *) Regs->Rip; + Val =3D 0; + Rex.Val =3D 0; + SeenRex =3D FALSE; + + // + // Default to 32bit transfer + // + OpSize =3D 4; + + do { + OpCode =3D *Rip++; + if (OpCode =3D=3D 0x66) { + OpSize =3D 2; + } else if (OpCode =3D=3D 0x64 || OpCode =3D=3D 0x65 || OpCode =3D=3D 0= x67) { + continue; + } else if (OpCode >=3D 0x40 && OpCode <=3D 0x4f) { + SeenRex =3D TRUE; + Rex.Val =3D OpCode; + } else { + break; + } + } while (TRUE); + + // + // We need to have at least 2 more bytes for this instruction + // + TDX_DECODER_BUG_ON(((UINT64)Rip - Regs->Rip) > 13); + + OpCode =3D *Rip++; + // + // Two-byte opecode, get next byte + // + if (OpCode =3D=3D 0x0F) { + OpCode =3D *Rip++; + } + + switch (OpCode) { + case 0x88: + case 0x8A: + case 0xB6: + MmioSize =3D 1; + break; + case 0xB7: + MmioSize =3D 2; + break; + default: + MmioSize =3D Rex.Bits.W ? 8 : OpSize; + break; + } + + /* Punt on AH/BH/CH/DH unless it shows up. */ + ModRm.Val =3D *Rip++; + TDX_DECODER_BUG_ON(MmioSize =3D=3D 1 && ModRm.Bits.Reg > 4 && !SeenRex &= & OpCode !=3D 0xB6); + Reg =3D GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R << 3)= ); + TDX_DECODER_BUG_ON(!Reg); + + if (ModRm.Bits.Rm =3D=3D 4) + ++Rip; /* SIB byte */ + + if (ModRm.Bits.Mod =3D=3D 2 || (ModRm.Bits.Mod =3D=3D 0 && ModRm.Bits.Rm= =3D=3D 5)) + Rip +=3D 4; /* DISP32 */ + else if (ModRm.Bits.Mod =3D=3D 1) + ++Rip; /* DISP8 */ + + switch (OpCode) { + case 0x88: + case 0x89: + CopyMem ((void *)&Val, Reg, MmioSize); + Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Va= l, 0); + break; + case 0xC7: + CopyMem ((void *)&Val, Rip, OpSize); + Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA, Va= l, 0); + Rip +=3D OpSize; + default: + // + // 32-bit write registers are zero extended to the full register + // Hence 'MOVZX r[32/64], r/m16' is + // hardcoded to reg size 8, and the straight MOV case has a reg + // size of 8 in the 32-bit read case. + // + switch (OpCode) { + case 0xB6: + RegSize =3D Rex.Bits.W ? 8 : OpSize; + break; + case 0xB7: + RegSize =3D 8; + break; + default: + RegSize =3D MmioSize =3D=3D 4 ? 8 : MmioSize; + break; + } + + Status =3D TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA, 0,= &Val); + if (Status =3D=3D 0) { + ZeroMem (Reg, RegSize); + CopyMem (Reg, (void *)&Val, MmioSize); + } + } + + if (Status =3D=3D 0) { + TDX_DECODER_BUG_ON(((UINT64)Rip - Regs->Rip) > 15); + + // + // We change instruction length to reflect true size so handler can + // bump rip + // + Veinfo->ExitInstructionLength =3D (UINT32)((UINT64)Rip - Regs->Rip); + } + + return Status; +} + +/** + Handle a #VE exception. + + Performs the necessary processing to handle a #VE exception. + + @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be s= et + as value to use on error. + @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT + + @retval EFI_SUCCESS Exception handled + @retval EFI_UNSUPPORTED #VE not supported, (new) exception value= to + propagate provided + @retval EFI_PROTOCOL_ERROR #VE handling failed, (new) exception val= ue to + propagate provided + +**/ +EFI_STATUS +EFIAPI +VmTdExitHandleVe ( + IN OUT EFI_EXCEPTION_TYPE *ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT64 Status; + TD_RETURN_DATA ReturnData; + EFI_SYSTEM_CONTEXT_X64 *Regs; + + Regs =3D SystemContext.SystemContextX64; + Status =3D TdCall (TDCALL_TDGETVEINFO, 0, 0, 0, &ReturnData); + ASSERT (Status =3D=3D 0); + if (Status !=3D 0) { + DEBUG ((DEBUG_ERROR, "#VE happened. TDGETVEINFO failed with Status =3D= 0x%llx\n", Status)); + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + + switch (ReturnData.VeInfo.ExitReason) { + case EXIT_REASON_CPUID: + Status =3D CpuIdExit (Regs, &ReturnData.VeInfo); + DEBUG ((DEBUG_VERBOSE , + "CPUID #VE happened, ExitReasion is %d, ExitQualification =3D 0x= %x.\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val + )); + break; + + case EXIT_REASON_HLT: + if (FixedPcdGetBool (PcdIgnoreVeHalt) =3D=3D FALSE) { + Status =3D TdVmCall (EXIT_REASON_HLT, 0, 0, 0, 0, 0); + } + break; + + case EXIT_REASON_IO_INSTRUCTION: + Status =3D IoExit (Regs, &ReturnData.VeInfo); + DEBUG ((DEBUG_VERBOSE , + "IO_Instruction #VE happened, ExitReasion is %d, ExitQualificati= on =3D 0x%x.\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val + )); + break; + + case EXIT_REASON_MSR_READ: + Status =3D ReadMsrExit (Regs, &ReturnData.VeInfo); + DEBUG ((DEBUG_VERBOSE , + "RDMSR #VE happened, ExitReasion is %d, ExitQualification =3D 0x= %x. Regs->Rcx=3D0x%llx, Status =3D 0x%llx\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val, Regs->Rcx, Status + )); + break; + + case EXIT_REASON_MSR_WRITE: + Status =3D WriteMsrExit (Regs, &ReturnData.VeInfo); + DEBUG ((DEBUG_VERBOSE , + "WRMSR #VE happened, ExitReasion is %d, ExitQualification =3D 0x= %x. Regs->Rcx=3D0x%llx, Status =3D 0x%llx\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val, Regs->Rcx, Status + )); + break; + + case EXIT_REASON_EPT_VIOLATION: + Status =3D MmioExit (Regs, &ReturnData.VeInfo); + DEBUG ((DEBUG_VERBOSE , + "MMIO #VE happened, ExitReasion is %d, ExitQualification =3D 0x%= x.\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val + )); + break; + + case EXIT_REASON_VMCALL: + case EXIT_REASON_MWAIT_INSTRUCTION: + case EXIT_REASON_MONITOR_INSTRUCTION: + case EXIT_REASON_WBINVD: + case EXIT_REASON_RDPMC: + /* Handle as nops. */ + break; + + default: + DEBUG ((DEBUG_ERROR, + "Unsupported #VE happened, ExitReason is %d, ExitQualification = =3D 0x%x.\n", + ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQualificatio= n.Val + )); + + ASSERT (FALSE); + CpuDeadLoop (); + } + if (Status) { + DEBUG ((DEBUG_ERROR, + "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQu= alification =3D 0x%x.\n", + Status, ReturnData.VeInfo.ExitReason, ReturnData.VeInfo.ExitQual= ification.Val + )); + + TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0); + } + SystemContext.SystemContextX64->Rip +=3D ReturnData.VeInfo.ExitInstructi= onLength; + return EFI_SUCCESS; +} diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 340d83f794d0..2124bd639399 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -350,6 +350,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataOffset|0|UINT32|0x56 gUefiOvmfPkgTokenSpaceGuid.PcdBfvRawDataSize|0|UINT32|0x57 =20 + ## Ignore the VE halt in Tdx + gUefiOvmfPkgTokenSpaceGuid.PcdIgnoreVeHalt|FALSE|BOOLEAN|0x58 + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81483): https://edk2.groups.io/g/devel/message/81483 Mute This Topic: https://groups.io/mt/86085741/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81484+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81484+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405231; cv=none; d=zohomail.com; s=zohoarc; b=M8ml9hRsqDkbwpjs1nGUhfupOUKfbbZdxwqu5hBJytQynthdkyBa/E3NSDFPd3vpwhfTXJVUhbZbe4ofYJdKSO1PzdfawcbAxcUPLunLUSUxRrL3K+ntyZPAXXehV7gKhn+hANcCtY0br4FzLN8zilRtO7mPcjnyAKHIPo+eRog= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405231; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=AVd1Su1wNf66d3l3HWuBs27J6/Mgv0xNqdcwB1Gk1s8=; b=iO1OA2gaxQVt7iRS8MIvm+F047mZf0gT2oEYSQ7fDmWWK4LaQsUp0m3fxY5Y9icBjsM7LckUw37lQh1hthr+K+Q3C6/DpFnOyATF98nrXxI3sQ4PYO5vwyEEd7Qc6tkC+1/ascjjmdXCfA7bZMvHWgqGiuwLnGfh05L8W5qToeg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81484+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405231367342.5200399692824; Mon, 4 Oct 2021 20:40:31 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id XiRJYY1788612x906WaWHPd1; Mon, 04 Oct 2021 20:40:31 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:30 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958183" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958183" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:30 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828600" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:27 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH V2 12/28] UefiCpuPkg/CpuExceptionHandler: Add base support for the #VE exception Date: Tue, 5 Oct 2021 11:39:23 +0800 Message-Id: <24d3a351f21bff1a4b20490313d039e403b1453c.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 7EKi1O143rydcLK7poBGXA3Hx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405231; bh=qRlGEvuBEEWRhQjhhZSg2FRjt1E7FYdXteUupNWWKzg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=TU/zKxs8TxH2wsw4BEnlo+bbPD911M/dLF5W/4o6oNoYrCuNVBRE6jd4Yk+Y3YAnm07 ye3gJfmYbSdGK2vNnI4XUb4/r49hyvKHqBmQriIQ+fijq0Ltu4wZaB3UoYxHzV4BDOx4R wybKDZUlhh2OWND/dXLE/Ht38MQapPLOvqY= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405231708100002 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Add base support to handle #VE exceptions. Update the common exception handlers to invoke the VmTdExitHandleVe () function of the VmTdExitLib library when a #VE is encountered. A non-zero return code will propagate to the targeted exception handler. Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Signed-off-by: Min Xu --- .../DxeCpuExceptionHandlerLib.inf | 1 + .../PeiCpuExceptionHandlerLib.inf | 1 + .../PeiDxeSmmCpuException.c | 18 ++++++++++++++++++ .../SecPeiCpuException.c | 19 +++++++++++++++++++ .../SecPeiCpuExceptionHandlerLib.inf | 1 + .../SmmCpuExceptionHandlerLib.inf | 1 + .../Xcode5SecPeiCpuExceptionHandlerLib.inf | 1 + 7 files changed, 42 insertions(+) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandl= erLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandle= rLib.inf index e7a81bebdb13..630a83bf003b 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.i= nf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.i= nf @@ -61,3 +61,4 @@ MemoryAllocationLib DebugLib VmgExitLib + VmTdExitLib diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandl= erLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandle= rLib.inf index cf5bfe40832b..63a7abfb6242 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.i= nf @@ -53,6 +53,7 @@ MemoryAllocationLib SynchronizationLib VmgExitLib + VmTdExitLib =20 [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard # CONSUMES diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuExceptio= n.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c index 892d349d4b37..0976a880825b 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #include #include +#include #include "CpuExceptionCommon.h" =20 /** @@ -45,6 +46,23 @@ CommonExceptionHandlerWorker ( } } =20 + if (ExceptionType =3D=3D VE_EXCEPTION) { + EFI_STATUS Status; + // + // #VE needs to be handled immediately upon enabling exception handling + // and therefore can't use the RegisterCpuInterruptHandler() interface. + // + // Handle the #VE: + // On EFI_SUCCESS - Exception has been handled, return + // On other - ExceptionType contains (possibly new) exception + // value + // + Status =3D VmTdExitHandleVe (&ExceptionType, SystemContext); + if (!EFI_ERROR (Status)) { + return; + } + } + ExceptionHandlerContext =3D (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (Syst= emContext.SystemContextIa32); ReservedVectors =3D ExceptionHandlerData->ReservedVectors; ExternalInterruptHandler =3D ExceptionHandlerData->ExternalInterruptHand= ler; diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c= b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c index 01b5a2f1f4fc..173047a6b494 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #include #include +#include #include "CpuExceptionCommon.h" =20 CONST UINTN mDoFarReturnFlag =3D 0; @@ -43,6 +44,24 @@ CommonExceptionHandler ( } } =20 + if (ExceptionType =3D=3D VE_EXCEPTION) { + EFI_STATUS Status; + // + // #VE needs to be handled immediately upon enabling exception handling + // and therefore can't use the RegisterCpuInterruptHandler() interface + // (which isn't supported under Sec and Pei anyway). + // + // Handle the #VE: + // On EFI_SUCCESS - Exception has been handled, return + // On other - ExceptionType contains (possibly new) exception + // value + // + Status =3D VmTdExitHandleVe (&ExceptionType, SystemContext); + if (!EFI_ERROR (Status)) { + return; + } + } + // // Initialize the serial port before dumping. // diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHa= ndlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException= HandlerLib.inf index 8ae4feae6238..4aeab2057b08 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLi= b.inf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLi= b.inf @@ -49,6 +49,7 @@ LocalApicLib PeCoffGetEntryPointLib VmgExitLib + VmTdExitLib =20 [FeaturePcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONS= UMES diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandl= erLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandle= rLib.inf index c9f20da05860..2622e48103f3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.i= nf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.i= nf @@ -52,6 +52,7 @@ PeCoffGetEntryPointLib DebugLib VmgExitLib + VmTdExitLib =20 [FeaturePcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONS= UMES diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExcep= tionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPei= CpuExceptionHandlerLib.inf index a15f125d5b5e..36ccb7ef97ec 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHan= dlerLib.inf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHan= dlerLib.inf @@ -54,6 +54,7 @@ LocalApicLib PeCoffGetEntryPointLib VmgExitLib + VmTdExitLib =20 [FeaturePcd] gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONS= UMES --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81484): https://edk2.groups.io/g/devel/message/81484 Mute This Topic: https://groups.io/mt/86085742/1787277 Mute #ve:https://edk2.groups.io/g/devel/mutehashtag/ve Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81485+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81485+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405234; cv=none; d=zohomail.com; s=zohoarc; b=HMnN1bYJNCEZFiMECIA4ooL1i1RK0baFm2LwbjZPM/xpPnDTJ9NOtm+i+OU4ct/1xMF06yHOQy7tqkK9BKwANuETAMeELChuT+BuA/NqwkSgjDGyQ9Dvsi91Eexz8JBKCnqLyz+0Pna0CmLvFMCqXKgP9VVknLyC1keG85g8GH8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405234; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=0HhfOinP4pzAuqfyu7V3/Hk9iv5t20dD8aG3vus0XLg=; b=O5uoXIhWK7hbi69wVP/itCOCpLw7GYJdxLv0quiSLB9uLbj6rghrpnL9GAi16F++3lNWUZkGFU4LhrXnwqCDYHSCPinloOVatcHWo6Ebdpm/N/EDwDhYQT282+tsC8J8QVDvKbEeeAv5rBdp5r5mjhOWE22ubzOG9bPBMzoyelo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81485+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405234720271.60300589898645; Mon, 4 Oct 2021 20:40:34 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id jWhvYY1788612x1Rod8G6YzY; Mon, 04 Oct 2021 20:40:34 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:33 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958197" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958197" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:33 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828616" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:30 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky , Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH V2 13/28] UefiCpuPkg: Enable Tdx support in MpInitLib Date: Tue, 5 Oct 2021 11:39:24 +0800 Message-Id: <80403cd301cc6f0e88bc1c10e11ec262c1093cbf.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: SFIeiEAnGdtQ9ej40LQUUQEox1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405234; bh=Q6ewi5OpF00uRyNehPnoqD1wP9Bik+lKnuyRCqxEfbg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=gzErmHPJuxU7YPSLA4hpFjDY9Ojy/knvYPyWMJhhAQDmg/AybXnop5yGUhrHR0IEQjA v8JvWxlQMQf/r4xCF3LiLoqO46H3zWhxOTxam5sDCZwp5D5kUrIIBeq+IEOCjuZyxJLaX Wugf4oJFm9F+2+SVE1wGjtg+7Hv03bZP9vw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405236005100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In TDVF BSP and APs are simplified. BSP is the vCPU-0, while the others are treated as APs. So MP intialization is rather simple. The processor info is retrieved by TDCALL, ApWorker is not supported, BSP is always the working processor, while the APs are just in a wait-for-precedure state. Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Signed-off-by: Min Xu --- UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf | 4 + UefiCpuPkg/Library/MpInitLib/DxeMpLib.c | 14 +- UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h | 107 ++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.c | 26 +++ UefiCpuPkg/Library/MpInitLib/MpLibTdx.c | 186 ++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c | 117 +++++++++++ UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf | 4 + .../Library/MpInitLib/X64/IntelTdcall.nasm | 120 +++++++++++ 8 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h create mode 100644 UefiCpuPkg/Library/MpInitLib/MpLibTdx.c create mode 100644 UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/DxeMpInitLib.inf index d34419c2a524..084e025564ef 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf @@ -22,10 +22,13 @@ # =20 [Sources.IA32] + MpLibTdxNull.c Ia32/MpFuncs.nasm =20 [Sources.X64] + MpLibTdx.c X64/MpFuncs.nasm + X64/IntelTdcall.nasm =20 [Sources.common] MpEqu.inc @@ -33,6 +36,7 @@ MpLib.c MpLib.h Microcode.c + MpIntelTdx.h =20 [Packages] MdePkg/MdePkg.dec diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/M= pInitLib/DxeMpLib.c index 93fc63bf93e3..b7275db3d564 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -7,6 +7,7 @@ **/ =20 #include "MpLib.h" +#include "MpIntelTdx.h" =20 #include #include @@ -15,7 +16,6 @@ #include #include #include - #include =20 #define AP_SAFE_STACK_SIZE 128 @@ -801,6 +801,10 @@ MpInitLibStartupThisAP ( { EFI_STATUS Status; =20 + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + // // temporarily stop checkAllApsStatus for avoid resource dead-lock. // @@ -857,6 +861,10 @@ MpInitLibSwitchBSP ( EFI_TIMER_ARCH_PROTOCOL *Timer; UINT64 TimerPeriod; =20 + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + TimerPeriod =3D 0; // // Locate Timer Arch Protocol @@ -930,6 +938,10 @@ MpInitLibEnableDisableAP ( EFI_STATUS Status; BOOLEAN TempStopCheckState; =20 + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + TempStopCheckState =3D FALSE; // // temporarily stop checkAllAPsStatus for initialize parameters. diff --git a/UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h b/UefiCpuPkg/Library= /MpInitLib/MpIntelTdx.h new file mode 100644 index 000000000000..59bd739eed22 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpIntelTdx.h @@ -0,0 +1,107 @@ +/** @file + Intel Tdx header file. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef MP_INTEL_TDX_H_ +#define MP_INTEL_TDX_H_ + +#include +#include +#include +#include +#include + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where informat= ion for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified = by + ProcessorNumber does not exist in the pl= atform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ); + +/** + Retrieves the number of logical processor in the platform and the number= of + those logical processors that are enabled on this boot. This service may= only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of l= ogical + processors in the system, includ= ing the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled= logical + processors that exist in system,= including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and ena= bled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfE= nabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ); + +/** + The TDCALL instruction causes a VM exit to the Intel TDX module. It is + used to call guest-side Intel TDX functions, either local or a TD exit + to the host VMM, as selected by Leaf. + + @param[in] Leaf Leaf number of TDCALL instruction + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in,out] Results Returned result of the Leaf function + + @return EFI_SUCCESS + @return Other See individual leaf functions +**/ +EFI_STATUS +EFIAPI +MpTdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ); + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ); + +#endif diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpIn= itLib/MpLib.c index b9a06747edbf..d03ad8ff483e 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -9,6 +9,7 @@ **/ =20 #include "MpLib.h" +#include "MpIntelTdx.h" #include #include #include @@ -1965,6 +1966,10 @@ MpInitLibInitialize ( UINTN BackupBufferAddr; UINTN ApIdtBase; =20 + if (MpTdxIsEnabled ()) { + return EFI_SUCCESS; + } + OldCpuMpData =3D GetCpuMpDataFromGuidedHob (); if (OldCpuMpData =3D=3D NULL) { MaxLogicalProcessorNumber =3D PcdGet32(PcdCpuMaxLogicalProcessorNumber= ); @@ -2215,6 +2220,10 @@ MpInitLibGetProcessorInfo ( CPU_INFO_IN_HOB *CpuInfoInHob; UINTN OriginalProcessorNumber; =20 + if (MpTdxIsEnabled ()) { + return TdxMpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuf= fer, HealthData); + } + CpuMpData =3D GetCpuMpData (); CpuInfoInHob =3D (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob; =20 @@ -2446,6 +2455,10 @@ EnableDisableApWorker ( CPU_MP_DATA *CpuMpData; UINTN CallerNumber; =20 + if (MpTdxIsEnabled ()) { + return EFI_UNSUPPORTED; + } + CpuMpData =3D GetCpuMpData (); =20 // @@ -2506,6 +2519,11 @@ MpInitLibWhoAmI ( return EFI_INVALID_PARAMETER; } =20 + if (MpTdxIsEnabled ()) { + *ProcessorNumber =3D 0; + return EFI_SUCCESS; + } + CpuMpData =3D GetCpuMpData (); =20 return GetProcessorNumber (CpuMpData, ProcessorNumber); @@ -2544,6 +2562,10 @@ MpInitLibGetNumberOfProcessors ( UINTN EnabledProcessorNumber; UINTN Index; =20 + if (MpTdxIsEnabled ()) { + return TdxMpInitLibGetNumberOfProcessors(NumberOfProcessors, NumberOfE= nabledProcessors); + } + CpuMpData =3D GetCpuMpData (); =20 if ((NumberOfProcessors =3D=3D NULL) && (NumberOfEnabledProcessors =3D= =3D NULL)) { @@ -2629,6 +2651,10 @@ StartupAllCPUsWorker ( BOOLEAN HasEnabledAp; CPU_STATE ApState; =20 + if (MpTdxIsEnabled ()) { + return EFI_SUCCESS; + } + CpuMpData =3D GetCpuMpData (); =20 if (FailedCpuList !=3D NULL) { diff --git a/UefiCpuPkg/Library/MpInitLib/MpLibTdx.c b/UefiCpuPkg/Library/M= pInitLib/MpLibTdx.c new file mode 100644 index 000000000000..d8bd4eb65d25 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpLibTdx.c @@ -0,0 +1,186 @@ +/** @file + CPU MP Initialize Library common functions. + + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, AMD Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include "MpIntelTdx.h" +#include +#include +#include +#include + +BOOLEAN mMpTdxEnabled =3D FALSE; +BOOLEAN mMpTdxProbed =3D FALSE; + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where informat= ion for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified = by + ProcessorNumber does not exist in the pl= atform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ) +{ + EFI_STATUS Status; + TD_RETURN_DATA TdReturnData; + + if (ProcessorInfoBuffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + Status =3D MpTdCall(TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status =3D=3D EFI_SUCCESS); + + if (ProcessorNumber >=3D TdReturnData.TdInfo.NumVcpus) { + return EFI_NOT_FOUND; + } + + ProcessorInfoBuffer->ProcessorId =3D ProcessorNumber; + ProcessorInfoBuffer->StatusFlag =3D 0; + if (ProcessorNumber =3D=3D 0) { + ProcessorInfoBuffer->StatusFlag |=3D PROCESSOR_AS_BSP_BIT; + } + ProcessorInfoBuffer->StatusFlag |=3D PROCESSOR_ENABLED_BIT; + + // + // Get processor location information + // + GetProcessorLocationByApicId ( + (UINT32)ProcessorNumber, + &ProcessorInfoBuffer->Location.Package, + &ProcessorInfoBuffer->Location.Core, + &ProcessorInfoBuffer->Location.Thread + ); + + if (HealthData !=3D NULL) { + HealthData->Uint32 =3D 0; + } + + return Status; +} + +/** + Retrieves the number of logical processor in the platform and the number= of + those logical processors that are enabled on this boot. This service may= only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of l= ogical + processors in the system, includ= ing the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled= logical + processors that exist in system,= including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and ena= bled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfE= nabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ) +{ + EFI_STATUS Status; + TD_RETURN_DATA TdReturnData; + + if ((NumberOfProcessors =3D=3D NULL) && (NumberOfEnabledProcessors =3D= =3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status =3D MpTdCall(TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status =3D=3D EFI_SUCCESS); + + if (NumberOfProcessors !=3D NULL) { + *NumberOfProcessors =3D TdReturnData.TdInfo.NumVcpus; + } + if (NumberOfEnabledProcessors !=3D NULL) { + *NumberOfEnabledProcessors =3D TdReturnData.TdInfo.MaxVcpus; + } + + return Status; +} + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ) +{ + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; + UINT32 LargestEax; + + if (mMpTdxProbed) { + return mMpTdxEnabled; + } + + mMpTdxEnabled =3D FALSE; + + do { + AsmCpuid (0, &LargestEax, &Ebx, &Ecx, &Edx); + + if (Ebx !=3D SIGNATURE_32 ('G', 'e', 'n', 'u') + || Edx !=3D SIGNATURE_32 ('i', 'n', 'e', 'I') + || Ecx !=3D SIGNATURE_32 ('n', 't', 'e', 'l')) { + break; + } + + AsmCpuid (1, NULL, NULL, &Ecx, NULL); + if ((Ecx & BIT31) =3D=3D 0) { + break; + } + + if (LargestEax < 0x21) { + break; + } + + AsmCpuidEx (0x21, 0, &Eax, &Ebx, &Ecx, &Edx); + if (Ebx !=3D SIGNATURE_32 ('I', 'n', 't', 'e') + || Edx !=3D SIGNATURE_32 ('l', 'T', 'D', 'X') + || Ecx !=3D SIGNATURE_32 (' ', ' ', ' ', ' ')) { + break; + } + + mMpTdxEnabled =3D TRUE; + }while (FALSE); + + mMpTdxProbed =3D TRUE; + + return mMpTdxEnabled; +} diff --git a/UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c b/UefiCpuPkg/Libra= ry/MpInitLib/MpLibTdxNull.c new file mode 100644 index 000000000000..f9cfedf01240 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/MpLibTdxNull.c @@ -0,0 +1,117 @@ +/** @file + CPU MP Initialize Library common functions. + + Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, AMD Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MpLib.h" +#include "MpIntelTdx.h" +#include + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + @param[in] ProcessorNumber The handle number of processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where informat= ion for + the requested processor is deposited. + @param[out] HealthData Return processor health data. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified = by + ProcessorNumber does not exist in the pl= atform. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetProcessorInfo ( + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer, + OUT EFI_HEALTH_FLAGS *HealthData OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +/** + Retrieves the number of logical processor in the platform and the number= of + those logical processors that are enabled on this boot. This service may= only + be called from the BSP. + + @param[out] NumberOfProcessors Pointer to the total number of l= ogical + processors in the system, includ= ing the BSP + and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled= logical + processors that exist in system,= including + the BSP. + + @retval EFI_SUCCESS The number of logical processors and ena= bled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL and NumberOfE= nabledProcessors + is NULL. + @retval EFI_NOT_READY MP Initialize Library is not initialized. + +**/ +EFI_STATUS +EFIAPI +TdxMpInitLibGetNumberOfProcessors ( + OUT UINTN *NumberOfProcessors, OPTIONAL + OUT UINTN *NumberOfEnabledProcessors OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +/** + Whether Intel TDX is enabled. + + @return TRUE TDX enabled + @return FALSE TDX not enabled +**/ +BOOLEAN +EFIAPI +MpTdxIsEnabled ( + VOID + ) +{ + return FALSE; +} + +/** + The TDCALL instruction causes a VM exit to the Intel TDX module. It is + used to call guest-side Intel TDX functions, either local or a TD exit + to the host VMM, as selected by Leaf. + Leaf functions are described at + + @param[in] Leaf Leaf number of TDCALL instruction + @param[in] Arg1 Arg1 + @param[in] Arg2 Arg2 + @param[in] Arg3 Arg3 + @param[in,out] Results Returned result of the Leaf function + + @return EFI_SUCCESS + @return Other See individual leaf functions +**/ +EFI_STATUS +EFIAPI +MpTdCall ( + IN UINT64 Leaf, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN OUT VOID *Results + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Lib= rary/MpInitLib/PeiMpInitLib.inf index 36fcb96b5852..b48dab2b1537 100644 --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf @@ -22,10 +22,13 @@ # =20 [Sources.IA32] + MpLibTdxNull.c Ia32/MpFuncs.nasm =20 [Sources.X64] + MpLibTdx.c X64/MpFuncs.nasm + X64/IntelTdcall.nasm =20 [Sources.common] MpEqu.inc @@ -33,6 +36,7 @@ MpLib.c MpLib.h Microcode.c + MpIntelTdx.h =20 [Packages] MdePkg/MdePkg.dec diff --git a/UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm b/UefiCpuPkg= /Library/MpInitLib/X64/IntelTdcall.nasm new file mode 100644 index 000000000000..5e98557d5590 --- /dev/null +++ b/UefiCpuPkg/Library/MpInitLib/X64/IntelTdcall.nasm @@ -0,0 +1,120 @@ +;-------------------------------------------------------------------------= ----- +;* +;* Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+;* SPDX-License-Identifier: BSD-2-Clause-Patent +;* +;* +;-------------------------------------------------------------------------= ----- + +DEFAULT REL +SECTION .text + +%macro tdcall 0 + db 0x66,0x0f,0x01,0xcc +%endmacro + +%macro tdcall_push_regs 0 + push rbp + mov rbp, rsp + push r15 + push r14 + push r13 + push r12 + push rbx + push rsi + push rdi +%endmacro + +%macro tdcall_pop_regs 0 + pop rdi + pop rsi + pop rbx + pop r12 + pop r13 + pop r14 + pop r15 + pop rbp +%endmacro + +%define number_of_regs_pushed 8 +%define number_of_parameters 4 + +; +; Keep these in sync for push_regs/pop_regs, code below +; uses them to find 5th or greater parameters +; +%define first_variable_on_stack_offset \ + ((number_of_regs_pushed * 8) + (number_of_parameters * 8) + 8) +%define second_variable_on_stack_offset \ + ((first_variable_on_stack_offset) + 8) + +%macro tdcall_regs_preamble 2 + mov rax, %1 + + mov ecx, %2 + + ; R10 =3D 0 (standard TDVMCALL) + + xor r10d, r10d + + ; Zero out unused (for standard TDVMCALL) registers to avoid leaking + ; secrets to the VMM. + + xor ebx, ebx + xor esi, esi + xor edi, edi + + xor edx, edx + xor ebp, ebp + xor r8d, r8d + xor r9d, r9d +%endmacro + +%macro tdcall_regs_postamble 0 + xor ebx, ebx + xor esi, esi + xor edi, edi + + xor ecx, ecx + xor edx, edx + xor r8d, r8d + xor r9d, r9d + xor r10d, r10d + xor r11d, r11d +%endmacro + +; MpTdCall ( +; UINT64 Leaf, // Rcx +; UINT64 P1, // Rdx +; UINT64 P2, // R8 +; UINT64 P3, // R9 +; UINT64 Results, // rsp + 0x28 +; ) +global ASM_PFX(MpTdCall) +ASM_PFX(MpTdCall): + tdcall_push_regs + + mov rax, rcx + mov rcx, rdx + mov rdx, r8 + mov r8, r9 + + tdcall + + ; exit if tdcall reports failure. + test rax, rax + jnz .exit + + ; test if caller wanted results + mov r12, [rsp + first_variable_on_stack_offset ] + test r12, r12 + jz .exit + mov [r12 + 0 ], rcx + mov [r12 + 8 ], rdx + mov [r12 + 16], r8 + mov [r12 + 24], r9 + mov [r12 + 32], r10 + mov [r12 + 40], r11 +.exit: + tdcall_pop_regs + ret --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81485): https://edk2.groups.io/g/devel/message/81485 Mute This Topic: https://groups.io/mt/86085743/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81486+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81486+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405236; cv=none; d=zohomail.com; s=zohoarc; b=bJrZkew0mZKcXhSPohjgYQLiRkB1hK5pnOmOHdPhod0tSxhZLayzHJc1lkfre1BjUXj4gskle6wZ9NBWXNFy+DcUVC4FhE+WrkJ1hkNpKjQQHg8O/fXUXUiDFPmWvmOmK6WMquOtSBq12zOCmfVWTURfSsjctA2DGWwNzniq5Ag= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405236; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=e8cwaZFkQVqUgbl7xnmF28w2ARnDDjOeUSSi26HOGO8=; b=APbm/4XjHXp2VMuTTIxTQM6QD0t+PNgQRrumM1R83XzVZxpypyW7+jtyBaVSfoJrdOmpD3TvDRJl2LhA3lIwJJAEGybD76GH2VfF4W/VA0fH645lIhfS6K3RXqJ1xiNSKcM63YJMMLtBSNxtRZGa/nA75X2syq9YhJXXEobC7d0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81486+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405236937362.7522778359404; Mon, 4 Oct 2021 20:40:36 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id SfmIYY1788612x6wTO8js8ms; Mon, 04 Oct 2021 20:40:36 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20667.1633405209770974351 for ; Mon, 04 Oct 2021 20:40:36 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958208" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958208" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:35 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828626" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:33 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 14/28] OvmfPkg: Update SecEntry.nasm to support Tdx Date: Tue, 5 Oct 2021 11:39:25 +0800 Message-Id: <2f440070a868156b6f22ab57076f86bad003c88e.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: jAIhv137bmArkTpHmJTTsSplx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405236; bh=vXJJGO8tkq1nOZUJeQpVfW5DHJLYNzn/T1frAxeT1XA=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=idKRkZQDesDnXVubrmu6vv/v2srHqyAbDHGBN29AwFa325ygdpQ77QMLyNE3jBb+xp3 c8OesW9Tr+Ziq2XaeV6NEo4zcQhF0bBdkGMvcnZcwc2US2H5r+Fk9m7CaJxc6Ivd06cos DYAqVCDI4Fd7rViV5CbI4wU1xsYJ/C7gNCU= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405238232100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In TDX BSP and APs goes to the same entry point in SecEntry.nasm. BSP initialize the temporary stack and then jumps to SecMain, just as legacy Ovmf does. APs spin in a modified mailbox loop using initial mailbox structure. Its structure defition is in OvmfPkg/Include/IndustryStandard/IntelTdx.h. APs wait for command to see if the command is for me. If so execute the command. There are 2 commands are supported: - WakeUp: BSP issues this command to move APs to final OS spinloop and Mailbox in reserved memory. - AcceptPages: To mitigate the performance impact of accepting pages in SEC phase on BSP, BSP will parse memory resources and assign each AP the task of accepting a subset of pages. This command may be called several times until all memory resources are processed. In accepting pages, PageLevel may fall back to smaller one if SIZE_MISMATCH error is returned. TdxCommondefs.inc is added which includes the common definitions used by the APs in SecEntry.nasm. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/TdxCommondefs.inc | 51 +++++ OvmfPkg/Sec/SecMain.inf | 1 + OvmfPkg/Sec/X64/SecEntry.nasm | 314 ++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 OvmfPkg/Include/TdxCommondefs.inc diff --git a/OvmfPkg/Include/TdxCommondefs.inc b/OvmfPkg/Include/TdxCommond= efs.inc new file mode 100644 index 000000000000..970eac96592a --- /dev/null +++ b/OvmfPkg/Include/TdxCommondefs.inc @@ -0,0 +1,51 @@ +;-------------------------------------------------------------------------= ----- +; @file +; TDX Common defitions used by the APs in mailbox +; +; Copyright (c) 2021, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;-------------------------------------------------------------------------= ----- + +CommandOffset equ 00h +ApicidOffset equ 04h +WakeupVectorOffset equ 08h +OSArgsOffset equ 10h +FirmwareArgsOffset equ 800h +WakeupArgsRelocatedMailBox equ 800h +AcceptPageArgsPhysicalStart equ 800h +AcceptPageArgsPhysicalEnd equ 808h +AcceptPageArgsChunkSize equ 810h +AcceptPageArgsPageSize equ 818h +CpuArrivalOffset equ 900h +CpusExitingOffset equ 0a00h +TalliesOffset equ 0a08h +ErrorsOffset equ 0e08h + +SIZE_4KB equ 1000h +SIZE_2MB equ 200000h +SIZE_1GB equ 40000000h + +PAGE_ACCEPT_LEVEL_4K equ 0 +PAGE_ACCEPT_LEVEL_2M equ 1 +PAGE_ACCEPT_LEVEL_1G equ 2 + +TDX_PAGE_ALREADY_ACCEPTED equ 0x00000b0a +TDX_PAGE_SIZE_MISMATCH equ 0xc0000b0b + +; Errors of APs in Mailbox +ERROR_NON equ 0 +ERROR_INVALID_ACCEPT_PAGE_SIZE equ 1 +ERROR_ACCEPT_PAGE_ERROR equ 2 +ERROR_INVALID_FALLBACK_PAGE_LEVEL equ 3 + +MpProtectedModeWakeupCommandNoop equ 0 +MpProtectedModeWakeupCommandWakeup equ 1 +MpProtectedModeWakeupCommandSleep equ 2 +MpProtectedModeWakeupCommandAcceptPages equ 3 + +MailboxApicIdInvalid equ 0xffffffff +MailboxApicidBroadcast equ 0xfffffffe + +%define TDCALL_TDINFO 0x1 +%define TDCALL_TDACCEPTPAGE 0x6 diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index ea4b9611f52d..6083fa21a433 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -72,6 +72,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentialComputingWorkAreaHeader gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase =20 [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire diff --git a/OvmfPkg/Sec/X64/SecEntry.nasm b/OvmfPkg/Sec/X64/SecEntry.nasm index 1cc680a70716..d0833db68410 100644 --- a/OvmfPkg/Sec/X64/SecEntry.nasm +++ b/OvmfPkg/Sec/X64/SecEntry.nasm @@ -10,12 +10,17 @@ ;-------------------------------------------------------------------------= ----- =20 #include +%include "TdxCommondefs.inc" =20 DEFAULT REL SECTION .text =20 extern ASM_PFX(SecCoreStartupWithStack) =20 +%macro tdcall 0 + db 0x66, 0x0f, 0x01, 0xcc +%endmacro + ; ; SecCore Entry Point ; @@ -35,6 +40,32 @@ extern ASM_PFX(SecCoreStartupWithStack) global ASM_PFX(_ModuleEntryPoint) ASM_PFX(_ModuleEntryPoint): =20 + ; + ; 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. @@ -67,3 +98,286 @@ ASM_PFX(_ModuleEntryPoint): sub rsp, 0x20 call ASM_PFX(SecCoreStartupWithStack) =20 + ; + ; 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 + + cmp eax, MpProtectedModeWakeupCommandAcceptPages + jne .check_command + + ; + ; AP Accept Pages + ; + ; Accept Pages in TDX is time-consuming, especially for big memory. + ; One of the mitigation is to accept pages by BSP and APs parallely. + ; + ; For example, there are 4 CPUs (1 BSP and 3 APs). Totally there are + ; 1G memory to be accepted. + ; + ; BSP is responsible for the memory regions of: + ; Start : StartAddress + ChunkSize * (4) * Index + ; Length: ChunkSize + ; APs is reponsible for the memory regions of: + ; Start : StartAddress + ChunkSize * (4) * Index + ChunkSize * CpuId + ; Length: ChunkSize + ; + ; TDCALL_TDACCEPTPAGE supports the PageSize of 4K and 2M. Sometimes wh= en + ; the PageSize is 2M, TDX_PAGE_SIZE_MISMATCH is returned as the error = code. + ; In this case, TDVF need fall back to 4k PageSize to accept again. + ; + ; If any errors happened in accept pages, an error code is recorded in + ; Mailbox [ErrorsOffset + CpuIndex] + ; +.ap_accept_page: + + ; + ; Clear the errors and fallback flag + ; + mov al, ERROR_NON + mov byte[rsp + ErrorsOffset + rbp], al + xor r12, r12 + + ; + ; Get PhysicalAddress/ChunkSize/PageSize + ; + mov rcx, [rsp + AcceptPageArgsPhysicalStart] + mov rbx, [rsp + AcceptPageArgsChunkSize] + + ; + ; Set AcceptPageLevel based on the AcceptPagesize + ; Currently only 2M/4K page size is acceptable + ; + mov r15, [rsp + AcceptPageArgsPageSize] + cmp r15, SIZE_4KB + je .set_4kb + cmp r15, SIZE_2MB + je .set_2mb + + mov al, ERROR_INVALID_ACCEPT_PAGE_SIZE + mov byte[rsp + ErrorsOffset + rbp], al + jmp .do_finish_command + +.set_4kb: + mov r15, PAGE_ACCEPT_LEVEL_4K + jmp .physical_address + +.set_2mb: + mov r15, PAGE_ACCEPT_LEVEL_2M + +.physical_address: + ; + ; PhysicalAddress +=3D (CpuId * ChunkSize) + ; + xor rdx, rdx + mov eax, ebp + mul ebx + add rcx, rax + shl rdx, 32 + add rcx, rdx + +.do_accept_next_range: + ; + ; Make sure we don't accept page beyond ending page + ; This could happen is ChunkSize crosses the end of region + ; + cmp rcx, [rsp + AcceptPageArgsPhysicalEnd ] + jge .do_finish_command + + ; + ; Save starting address for this region + ; + mov r11, rcx + + ; + ; Size =3D MIN(ChunkSize, PhysicalEnd - PhysicalAddress); + ; + mov rax, [rsp + AcceptPageArgsPhysicalEnd] + sub rax, rcx + cmp rax, rbx + jge .do_accept_loop + mov rbx, rax + +.do_accept_loop: + ; + ; RCX: Accept address + ; R15: Accept Page Level + ; R12: Flag of fall back accept + ; + mov rax, TDCALL_TDACCEPTPAGE + xor rdx, rdx + or rcx, r15 + + tdcall + + ; + ; Check status code in RAX + ; + test rax, rax + jz .accept_success + + shr rax, 32 + cmp eax, TDX_PAGE_ALREADY_ACCEPTED + jz .already_accepted + + cmp eax, TDX_PAGE_SIZE_MISMATCH + jz .accept_size_mismatch + + ; + ; other error + ; + mov al, ERROR_ACCEPT_PAGE_ERROR + mov byte[rsp + ErrorsOffset + rbp], al + jmp .do_finish_command + +.accept_size_mismatch: + ; + ; Check the current PageLevel. + ; ACCEPT_LEVEL_4K is the least level and cannot fall back any more. + ; If in this case, just record the error and return + ; + cmp r15, PAGE_ACCEPT_LEVEL_4K + jne .do_fallback_accept + mov al, ERROR_INVALID_FALLBACK_PAGE_LEVEL + mov byte[rsp + ErrorsOffset + rbp], al + jmp .do_finish_command + +.do_fallback_accept: + ; + ; In fall back accept, just loop 512 times (2M =3D 512 * 4K) + ; Save the rcx in r13. + ; Decrease the PageLevel in R15. + ; R12 indicates it is in a fall back accept loop. + ; + mov r14, 512 + and rcx, ~0x3ULL + mov r13, rcx + xor rdx, rdx + dec r15 + mov r12, 1 + + jmp .do_accept_loop + +.accept_success: + ; + ; Keep track of how many accepts per cpu + ; + inc dword[rsp + TalliesOffset + rbp * 4] + + ; + ; R12 indicate whether it is a fall back accept + ; If it is a success of fall back accept + ; Just loop 512 times to .do_accept_loop + ; + test r12, r12 + jz .normal_accept_success + + ; + ; This is fallback accept success + ; + add rcx, SIZE_4KB + dec r14 + test r14, r14 + jz .fallback_accept_done + jmp .do_accept_loop + +.fallback_accept_done: + ; + ; Fall back accept done. + ; Restore the start address to RCX from R13 + ; Clear the fall back accept flag + ; + mov rcx, r13 + inc r15 + xor r12, r12 + +.already_accepted: + ; + ; Handle the sitution of fall back accpet + ; + test r12, r12 + jnz .accept_success + +.normal_accept_success: + ; + ; Reduce accept size by a PageSize, and increment address + ; + mov r12, [rsp + AcceptPageArgsPageSize] + sub rbx, r12 + add rcx, r12 + xor r12, r12 + + ; + ; We may be given multiple pages to accept, make sure we + ; aren't done + ; + test rbx, rbx + jne .do_accept_loop + + ; + ; Restore address before, and then increment by stride (num-cpus * Chu= nkSize) + ; + xor rdx, rdx + mov rcx, r11 + mov eax, r8d + mov ebx, [rsp + AcceptPageArgsChunkSize] + mul ebx + add rcx, rax + shl rdx, 32 + add rcx, rdx + jmp .do_accept_next_range + +.do_finish_command: + mov eax, 0FFFFFFFFh + lock xadd dword [rsp + CpusExitingOffset], eax + dec eax + +.check_exiting_cnt: + cmp eax, 0 + je .do_wait_loop + mov eax, dword[rsp + CpusExitingOffset] + jmp .check_exiting_cnt + +.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 $ --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81486): https://edk2.groups.io/g/devel/message/81486 Mute This Topic: https://groups.io/mt/86085745/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81487+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81487+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405265; cv=none; d=zohomail.com; s=zohoarc; b=NBJIoJRdCB4sUnMkmyLIHSBrbsLVKwr7udwq+EOn3g22ilR/7rMeZwW3sqDZesVVCyHN/eL0LeNMyza/DrC2BsPtB6PHSg3OG/JRl3AabFTj7nlgZNEgGrJTNurMfU1OvtqPYCzlCW7FAkRXf9rlLmdATnVakFYRBeblT862jZ8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405265; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=smw9Xvf3cRH0wBUVWnEBNQWJipk3c9xdmW4pCf3l6dk=; b=O+W4Em+eJX0/IJm1g7m0xwq1KneRD5CfRuDxUYI7+PF56zatFL2jk9DieymOvstJ35fp3k/mP49iIQylPIwX9jMw48uw6KkJISjY7q9nZYzmY7wIaq0HsLJ3W3Z9Wj7YJcFY4RGEyFp3coIdIko590uMBYCvSlCDtlrwrVowsjE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81487+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405265026251.06856048629777; Mon, 4 Oct 2021 20:41:05 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id SLrfYY1788612xdH0Syv7HUT; Mon, 04 Oct 2021 20:41:04 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:04 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958227" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958227" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:38 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828657" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:36 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 15/28] OvmfPkg: Add IntelTdx.h in OvmfPkg/Include/IndustryStandard Date: Tue, 5 Oct 2021 11:39:26 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: WMOEKMQVfDQUEVZD9C6qcFmgx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405264; bh=yPsnDv179VasFQSZXajLKoilXkOHT44NrfkljOry1gk=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=ZXenK3riDt1qfIdD8PO+uVc4oDB30INaDbhe1QIznwrDV8m9V/nTlTQN4b/1HUxaENF 5EP37/XC3Mo91MbQ5Ute0CH9HCtZpnPDonZ405Djd/s10TN7FcU8B479pv5yr4fyoWRNs h/mtYVvHryo5IZ/Plpdp0HU2ZBAfN4smLXE= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405266456100002 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 IntelTdx.h defines the defitions used by TDX in OvmfPkg: - Mailbox related defitions,such as the data structure, command code, AP relocation defitions. - EFI_HOB_PLATFORM_INFO describes the TDX platform information Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/IndustryStandard/IntelTdx.h | 77 +++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 OvmfPkg/Include/IndustryStandard/IntelTdx.h diff --git a/OvmfPkg/Include/IndustryStandard/IntelTdx.h b/OvmfPkg/Include/= IndustryStandard/IntelTdx.h new file mode 100644 index 000000000000..2370f18289a1 --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/IntelTdx.h @@ -0,0 +1,77 @@ +/** @file + TBD + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _OVMF_INTEL_TDX__H_ +#define _OVMF_INTEL_TDX__H_ + +#include +#include +#include +#include + +#define MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID 0xFFFFFFFF +#define MP_CPU_PROTECTED_MODE_MAILBOX_APICID_BROADCAST 0xFFFFFFFE + +typedef enum { + MpProtectedModeWakeupCommandNoop =3D 0, + MpProtectedModeWakeupCommandWakeup =3D 1, + MpProtectedModeWakeupCommandSleep =3D 2, + MpProtectedModeWakeupCommandAcceptPages =3D 3, +} MP_CPU_PROTECTED_MODE_WAKEUP_CMD; + +#pragma pack (1) + + // + // Describes the CPU MAILBOX control structure use to + // wakeup cpus spinning in long mode + // + typedef struct { + UINT16 Command; + UINT16 Resv; + UINT32 ApicId; + UINT64 WakeUpVector; + UINT8 ResvForOs[2032]; + // + // Arguments available for wakeup code + // + UINT64 WakeUpArgs1; + UINT64 WakeUpArgs2; + UINT64 WakeUpArgs3; + UINT64 WakeUpArgs4; + UINT8 Pad1[0xe0]; + UINT64 NumCpusArriving; + UINT8 Pad2[0xf8]; + UINT64 NumCpusExiting; + UINT32 Tallies[256]; + UINT8 Errors[256]; + UINT8 Pad3[0xf8]; + } MP_WAKEUP_MAILBOX; + + +// +// AP relocation 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 *RelocateApLoopFuncAddress; + UINTN RelocateApLoopFuncSize; +} MP_RELOCATION_MAP; + +typedef struct { + /// + EFI_HOB_GUID_TYPE GuidHeader; + UINT64 RelocatedMailBox; + UINT16 HostBridgePciDevId; + BOOLEAN SetNxForStack; + UINT8 SystemStates[6]; +} EFI_HOB_PLATFORM_INFO; + +#pragma pack() + +#endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81487): https://edk2.groups.io/g/devel/message/81487 Mute This Topic: https://groups.io/mt/86085755/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81488+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81488+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405265; cv=none; d=zohomail.com; s=zohoarc; b=R51T6BjNkXUiUgrky2sWkwWKr8yDhWgA/0nd5DTstxuk0hD/nQbUG7vLxsHtQVieq4RqkDycz9i5JsWCh2QG73tbfYsjtWPy59sByexbJmcQgCG8oLqvuGqMey+ihPuwwMib8W8FoORbB3BfqRoGRhiiq45/3kESYccuQIo9u0c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405265; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=b+OcZPrXRhSXarwMhIkg8y42qdByjuth4Z/NKh/b+3c=; b=lp3OWggTz1RGI5ZK0lHdEnguF3/YmxF0gR72pvsrH0nuraAzyAG+AWHRHFu5en+JhBL0zo2q7rw0dzjJdzBiP/hziRR9A6Nw5Q5gsyGwRHgQ9UZ/TGrdxVt+Ze0kgCx8W9/TXKYNzZvsJ1Rcy8UGcWciZvw10tQRKIYdXg6PPWo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81488+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405265714583.0650900859048; Mon, 4 Oct 2021 20:41:05 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id ahzxYY1788612xT1z3NrXaOb; Mon, 04 Oct 2021 20:41:05 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:04 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958229" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958229" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:41 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828670" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:38 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 16/28] OvmfPkg: Add TdxMailboxLib Date: Tue, 5 Oct 2021 11:39:27 +0800 Message-Id: <01f7c0e040a56cdfe065484d02ae634e89fb09ed.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: Q2rb18wEy08YQbIuEP60YAkTx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405265; bh=9sXX0srloG3Q0a8MQJOYMqFdMgi1hcRFGSLeCdoW2bI=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=hIMvn1hRkrDqCxV3GK4mroBgmgKvnVt7FbB2B5V3bjj4hua84vaYs0jEcp4aqOVNq87 9Lo8TffCqwczSNF9YvvsB9LHszjLyvKkl/0akSti/uSDFza1Ioe+KAdp0iz29LtIwMXnq WzxMKZF7X1AKkJrM7ek7jus7ZwloHyFUqU0= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405266618100008 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In Tdx BSP may issues commands to APs for some task, for example, to accept pages paralelly. BSP also need to wait until all the APs have done the task. TdxMailboxLib wraps these common funtions for BSP. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/Library/TdxMailboxLib.h | 75 ++++++++++ OvmfPkg/Library/TdxMailboxLib/TdxMailbox.c | 138 ++++++++++++++++++ .../Library/TdxMailboxLib/TdxMailboxLib.inf | 52 +++++++ .../Library/TdxMailboxLib/TdxMailboxNull.c | 86 +++++++++++ OvmfPkg/OvmfPkg.dec | 4 + 5 files changed, 355 insertions(+) create mode 100644 OvmfPkg/Include/Library/TdxMailboxLib.h create mode 100644 OvmfPkg/Library/TdxMailboxLib/TdxMailbox.c create mode 100644 OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf create mode 100644 OvmfPkg/Library/TdxMailboxLib/TdxMailboxNull.c diff --git a/OvmfPkg/Include/Library/TdxMailboxLib.h b/OvmfPkg/Include/Libr= ary/TdxMailboxLib.h new file mode 100644 index 000000000000..a410a9618495 --- /dev/null +++ b/OvmfPkg/Include/Library/TdxMailboxLib.h @@ -0,0 +1,75 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __TDX_MAILBOX_LIB_H__ +#define __TDX_MAILBOX_LIB_H__ + +#include +#include +#include +#include +#include +#include + +/** + This function will be called by BSP to get the CPU number. + + @retval CPU number +**/ +UINT32 +EFIAPI +GetCpusNum ( + VOID +); + +/** + Get the address of Td mailbox. +**/ +volatile VOID * +EFIAPI +GetTdxMailBox ( + VOID +); + +/** + This function will be called by BSP to wakeup APs the are spinning on ma= ilbox + in protected mode + + @param[in] Command Command to send APs + @param[in] WakeupVector If used, address for APs to start executing + @param[in] WakeArgsX Args to pass to APs for excuting commands +**/ +VOID +EFIAPI +MpSendWakeupCommand( + IN UINT16 Command, + IN UINT64 WakeupVector, + IN UINT64 WakeupArgs1, + IN UINT64 WakeupArgs2, + IN UINT64 WakeupArgs3, + IN UINT64 WakeupArgs4 +); + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is started. +**/ +VOID +EFIAPI +MpSerializeStart ( + VOID + ); + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is ended. +**/ +VOID +EFIAPI +MpSerializeEnd ( + VOID + ); + +#endif diff --git a/OvmfPkg/Library/TdxMailboxLib/TdxMailbox.c b/OvmfPkg/Library/T= dxMailboxLib/TdxMailbox.c new file mode 100644 index 000000000000..688ac6ca8262 --- /dev/null +++ b/OvmfPkg/Library/TdxMailboxLib/TdxMailbox.c @@ -0,0 +1,138 @@ +/** @file + + Copyright (c) 2008, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +volatile VOID *mMailBox =3D NULL; +UINT32 mNumOfCpus =3D 0; + +/** + This function will be called by BSP to get the CPU number. + + @retval CPU number +**/ +UINT32 +EFIAPI +GetCpusNum ( + VOID + ) +{ + if (mNumOfCpus =3D=3D 0) { + mNumOfCpus =3D TdVCpuNum (); + } + + return mNumOfCpus; +} + +/** + Get the address of Td mailbox. +**/ +volatile VOID * +EFIAPI +GetTdxMailBox ( + VOID + ) +{ + if (mMailBox =3D=3D NULL) { + mMailBox =3D (VOID *)(UINTN) PcdGet32 (PcdOvmfSecGhcbBackupBase); + } + + return mMailBox; +} + +/** + This function will be called by BSP to wakeup APs the are spinning on ma= ilbox + in protected mode + + @param[in] Command Command to send APs + @param[in] WakeupVector If used, address for APs to start executing + @param[in] WakeArgsX Args to pass to APs for excuting commands +**/ +VOID +EFIAPI +MpSendWakeupCommand ( + IN UINT16 Command, + IN UINT64 WakeupVector, + IN UINT64 WakeupArgs1, + IN UINT64 WakeupArgs2, + IN UINT64 WakeupArgs3, + IN UINT64 WakeupArgs4 +) +{ + volatile MP_WAKEUP_MAILBOX *MailBox; + + MailBox =3D (volatile MP_WAKEUP_MAILBOX *) GetTdxMailBox (); + MailBox->ApicId =3D MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALID; + MailBox->WakeUpVector =3D 0; + MailBox->Command =3D MpProtectedModeWakeupCommandNoop; + MailBox->ApicId =3D MP_CPU_PROTECTED_MODE_MAILBOX_APICID_BROADCAST; + MailBox->WakeUpVector =3D WakeupVector; + MailBox->WakeUpArgs1 =3D WakeupArgs1; + MailBox->WakeUpArgs2 =3D WakeupArgs2; + MailBox->WakeUpArgs3 =3D WakeupArgs3; + MailBox->WakeUpArgs4 =3D WakeupArgs4; + AsmCpuid (0x01, NULL, NULL, NULL, NULL); + MailBox->Command =3D Command; + AsmCpuid (0x01, NULL, NULL, NULL, NULL); + return; +} + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is started. +**/ +VOID +EFIAPI +MpSerializeStart ( + VOID + ) +{ + volatile MP_WAKEUP_MAILBOX *MailBox; + UINT32 NumOfCpus; + + NumOfCpus =3D GetCpusNum (); + MailBox =3D (volatile MP_WAKEUP_MAILBOX *) GetTdxMailBox (); + + DEBUG ((DEBUG_VERBOSE, "Waiting for APs to arriving. NumOfCpus=3D%d, Mai= lBox=3D%p\n", NumOfCpus, MailBox)); + while (MailBox->NumCpusArriving !=3D ( NumOfCpus -1 )) { + CpuPause (); + } + DEBUG ((DEBUG_VERBOSE, "Releasing APs\n")); + MailBox->NumCpusExiting =3D NumOfCpus; + InterlockedIncrement ((UINT32 *) &MailBox->NumCpusArriving); +} + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is ended. +**/ +VOID +EFIAPI +MpSerializeEnd ( + VOID + ) +{ + volatile MP_WAKEUP_MAILBOX *MailBox; + + MailBox =3D (volatile MP_WAKEUP_MAILBOX *) GetTdxMailBox (); + DEBUG ((DEBUG_VERBOSE, "Waiting for APs to finish\n")); + while (MailBox->NumCpusExiting !=3D 1 ) { + CpuPause (); + } + DEBUG ((DEBUG_VERBOSE, "Restarting APs\n")); + MailBox->Command =3D MpProtectedModeWakeupCommandNoop; + MailBox->NumCpusArriving =3D 0; + InterlockedDecrement ((UINT32 *) &MailBox->NumCpusExiting); +} diff --git a/OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf b/OvmfPkg/Libr= ary/TdxMailboxLib/TdxMailboxLib.inf new file mode 100644 index 000000000000..3cf3690a16c7 --- /dev/null +++ b/OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf @@ -0,0 +1,52 @@ +#/** @file +# +# TBD +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2008, Apple Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +#**/ + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D TdxMailboxLib + FILE_GUID =3D 2F81A9BA-748E-4519-BB11-A63A039D561E + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D TdxMailboxLib + +# +# VALID_ARCHITECTURES =3D X64 IA32 +# + +[Sources.IA32] + TdxMailboxNull.c + +[Sources.X64] + TdxMailbox.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PcdLib + UefiCpuLib + DebugAgentLib + IoLib + SynchronizationLib + MemoryAllocationLib + +[Guids] + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize diff --git a/OvmfPkg/Library/TdxMailboxLib/TdxMailboxNull.c b/OvmfPkg/Libra= ry/TdxMailboxLib/TdxMailboxNull.c new file mode 100644 index 000000000000..f15222d51f45 --- /dev/null +++ b/OvmfPkg/Library/TdxMailboxLib/TdxMailboxNull.c @@ -0,0 +1,86 @@ +/** @file + + Copyright (c) 2008, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + + +/** + This function will be called by BSP to get the CPU number. + + @retval CPU number +**/ +UINT32 +EFIAPI +GetCpusNum ( + VOID + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Get the address of Td mailbox. +**/ +volatile VOID * +EFIAPI +GetTdxMailBox ( + VOID + ) +{ + ASSERT (FALSE); + return (volatile VOID *) NULL; +} + +/** + This function will be called by BSP to wakeup APs the are spinning on ma= ilbox + in protected mode + + @param[in] Command Command to send APs + @param[in] WakeupVector If used, address for APs to start executing + @param[in] WakeArgsX Args to pass to APs for excuting commands +**/ +VOID +EFIAPI +MpSendWakeupCommand ( + IN UINT16 Command, + IN UINT64 WakeupVector, + IN UINT64 WakeupArgs1, + IN UINT64 WakeupArgs2, + IN UINT64 WakeupArgs3, + IN UINT64 WakeupArgs4 +) +{ + ASSERT (FALSE); +} + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is started. +**/ +VOID +EFIAPI +MpSerializeStart ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + BSP wait until all the APs arriving. It means the task triggered by BSP = is ended. +**/ +VOID +EFIAPI +MpSerializeEnd ( + VOID + ) +{ + ASSERT (FALSE); +} diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 2124bd639399..145943532a74 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -109,6 +109,10 @@ # XenPlatformLib|Include/Library/XenPlatformLib.h =20 + ## @libraryclass TdxMailboxLib + # + TdxMailboxLib|Include/Library/TdxMailboxLib.h + [Guids] gUefiOvmfPkgTokenSpaceGuid =3D {0x93bb96af, 0xb9f2, 0x4eb8, {= 0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} gEfiXenInfoGuid =3D {0xd3b46f3b, 0xd441, 0x1244, {= 0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81488): https://edk2.groups.io/g/devel/message/81488 Mute This Topic: https://groups.io/mt/86085757/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81489+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81489+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405266; cv=none; d=zohomail.com; s=zohoarc; b=YOebnARsx8mKXB/B5g+ycr6Uu8p5G63ig8LHQfUghbrLfRph8CS/2B+yujXmD92X82L/PNzKSPaKMNtszzSFvefk8PPhIDV52j99CQ+3rC+sFAxnV9DpCjgHEc8JY2/ZwmfN4Ghi1RtnXdjinmN4n9vGZmfhf1bkfRCQeNd5jTQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405266; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=mAoEareuTAel66+5YlPL9ZDqnTh3+zyMDpQZQcCcjYk=; b=Xft6Auzon99ed93teJfsvvd3HtJTViHNtAYppgmqE9Ac60yA5osb5/u7bg0q9qWifohQ0poktVORLq3v9hFXL9FqzPlDEDnO7vPFhkhniBB3Q6eZ3Ofs0prfz520vi9XhzUKv9yYX61dRaG8pW0Z8o15+Ao+CEG8uEEWM6c4FcY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81489+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405266214810.7043755311917; Mon, 4 Oct 2021 20:41:06 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id iTI0YY1788612xcJwPzF0iOE; Mon, 04 Oct 2021 20:41:05 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:05 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958231" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958231" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:43 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828682" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:41 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 17/28] MdePkg: Add EFI_RESOURCE_ATTRIBUTE_ENCRYPTED in PiHob.h Date: Tue, 5 Oct 2021 11:39:28 +0800 Message-Id: <51cb3119e06524c83f06dd4505b8b7ea7173f97e.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: ZmDKeL4kcKSWLuhSpUc52km7x1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405265; bh=YsQhyzVUcjzuE4F3F/lVBYhMs484mBlwI13Dcs4K9FI=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=Si5NUVtn4a2DntFP2LVmagak5B1AwuGfpe8jL0G/+BdB4KywEntpZHjmQypxJEPwn4c 12FrrOx8mMVL7kZcKf38GJSZzT+2rXskZ06xwbjKzMrSEGM23kX1y18uk14cP6a7AIT+e Sy/ouoAfmnapi5EIVnki9uE18XomTeENScw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405266598100006 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 EFI_RESOURCE_ATTRIBUTE_ENCRYPTED is Physical memory encrypted attribute. It indicates the memory uses platform encrpytion capabilities for protection. If this bit is clear, the memory does not use platform encryption protection. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- MdePkg/Include/Pi/PiHob.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MdePkg/Include/Pi/PiHob.h b/MdePkg/Include/Pi/PiHob.h index 62c07742a688..600ec2d4919e 100644 --- a/MdePkg/Include/Pi/PiHob.h +++ b/MdePkg/Include/Pi/PiHob.h @@ -298,6 +298,14 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; // #define EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE 0x02000000 =20 +// +// Physical memory encrypted attribute. This +// memory uses platform encrpytion capabilities for +// protection. If this bit is clear, the memory does +// not use platform encryption protection +// +#define EFI_RESOURCE_ATTRIBUTE_ENCRYPTED 0x04000000 + /// /// Describes the resource properties of all fixed, /// nonrelocatable resource ranges found on the processor --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81489): https://edk2.groups.io/g/devel/message/81489 Mute This Topic: https://groups.io/mt/86085758/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81490+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81490+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405266; cv=none; d=zohomail.com; s=zohoarc; b=UldGg90dVGd4bfqZ7bi2ZWKWc4vFKTPuZ6lTBo2hQjSFBag+184Dc23OhVk49V2UFo9H2tg35BuzTWgrJQxxwCwQ9ycbUloy2Lc78RoqGn2Ak9qcHldaskBEFJrkhYU8rGFERZoDOHD7J87kKjEoIqwwbyGMwxag4NkJbh0SLkQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405266; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=kCYYIzzKMKNXP/Fa+/O8oKbuGjnE8VgHidvnUykGK5s=; b=fuYYE3bdjBCgFzbQpiuPH/yPS1RnHP8SFvG3lkCk0NLVoNsJ6HlL5r4V4jYe3RXDHYFApbn3UKPlhmQMoCLr9OL+dZ6mEdx/b3VV9i4IyprJ5yajBElGTK6a/ay9jQoYyrLwUu35AjtHv0fj60E5NIpk9P004YwJiDdN9Awjobg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81490+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 163340526672223.408542094683867; Mon, 4 Oct 2021 20:41:06 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id F42FYY1788612xyc0JzdXQKB; Mon, 04 Oct 2021 20:41:06 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.20836.1633405265395581286 for ; Mon, 04 Oct 2021 20:41:05 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958233" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958233" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:46 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828696" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:43 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 18/28] OvmfPkg: Enable Tdx in SecMain.c Date: Tue, 5 Oct 2021 11:39:29 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: uLFFkxeFh1zh81QlZVTALYuox1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405266; bh=S3Y+JcbO8KMMxkeOeEbPzzL2oMAKlNEEYb584nSEio0=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=iN3YpYYYsgQa6j7RsMSbOJ4t84qhPEzU3h0hRkS/NbNqNPCxFCSHCO6lMnay0ZJT3dp GMj/8IA/BItouw250r0/0ke7zkahiMeKoNTQMkg6dXG06ix8jfqMR6hiUnXKynF25imrp rhmGtkXujDI6uoZZzdTlfRPalSn0V98Be6o= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405268724100014 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 When host VMM create the Td guest, the system memory informations are stored in TdHob, which is a memory region described in Tdx metadata. The system memory region in TdHob should be accepted before it can be accessed. So the major task of this patch set is to process the TdHobList to accept the memory. After that TDVF follow the standard OVMF flow and jump to PEI phase. PcdTdxAcceptChunkSize & PcdTdxAcceptPageSize are added for page accepting. They're the default settings of the chunk size and the Accept page size. PcdUse1GPageTable is set to FALSE by default in OvmfPkgX64.dsc. It gives no chance for Intel TDX to support 1G page table. To support 1G page table this PCD is set to TRUE in OvmfPkgX64.dsc. 3 Tdx specific libs are used by OvmfPkgX64: - VmTdExitLib - TdxLib - TdxMailboxLib TDX only works on X64, so the code is only valid in X64 arch. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/OvmfPkg.dec | 6 + OvmfPkg/OvmfPkgIa32.dsc | 2 + OvmfPkg/OvmfPkgIa32X64.dsc | 2 + OvmfPkg/OvmfPkgX64.dsc | 8 +- OvmfPkg/Sec/IntelTdx.c | 608 +++++++++++++++++++++++++++++++++++++ OvmfPkg/Sec/IntelTdx.h | 33 ++ OvmfPkg/Sec/SecMain.c | 60 +++- OvmfPkg/Sec/SecMain.inf | 6 + 8 files changed, 718 insertions(+), 7 deletions(-) create mode 100644 OvmfPkg/Sec/IntelTdx.c create mode 100644 OvmfPkg/Sec/IntelTdx.h diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 145943532a74..6f535d718203 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -357,6 +357,12 @@ ## Ignore the VE halt in Tdx gUefiOvmfPkgTokenSpaceGuid.PcdIgnoreVeHalt|FALSE|BOOLEAN|0x58 =20 + ## The chunk size of Tdx accept page + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptChunkSize|0x2000000|UINT64|0x59 + + ## The Tdx accept page size. 0x1000(4k),0x200000(2M) + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize|0x1000|UINT64|0x5a + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 1f75075152a6..46040357da83 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -244,6 +244,8 @@ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 771b08088b96..acdcdeee9969 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -248,6 +248,8 @@ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 162858e2659b..12ebde74433d 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -247,7 +247,9 @@ [LibraryClasses.common] BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf - VmTdExitLib|UefiCpuPkg/Library/VmTdExitLibNull/VmTdExitLibNull.inf + VmTdExitLib|OvmfPkg/Library/VmTdExitLib/VmTdExitLib.inf + TdxLib|MdePkg/Library/TdxLib/TdxLib.inf + TdxMailboxLib|OvmfPkg/Library/TdxMailboxLib/TdxMailboxLib.inf =20 [LibraryClasses.common.SEC] TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf @@ -573,6 +575,10 @@ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0x100 gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0x100 =20 + # + # TDX need 1G PageTable support + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE + # # Network Pcds # diff --git a/OvmfPkg/Sec/IntelTdx.c b/OvmfPkg/Sec/IntelTdx.c new file mode 100644 index 000000000000..e4bbd0fdea4e --- /dev/null +++ b/OvmfPkg/Sec/IntelTdx.c @@ -0,0 +1,608 @@ +/** @file + + Copyright (c) 2008, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IntelTdx.h" + +#define ALIGNED_2MB_MASK 0x1fffff + +/** + BSP call this function to accept memory in a range. + + @param[in] StartAddress Start address of the memory region + @param[in] Length Length of the memory region + @param[in] AcceptChunkSize Accept chunk size + @param[in] AcceptPageSize Accept page size + @retval EFI_SUCCESS Successfully accept the memory region + @retval Others Indicate the other errors +**/ +EFI_STATUS +EFIAPI +BspAcceptMemoryResourceRange ( + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINT64 Length, + IN UINT64 AcceptChunkSize, + IN UINT64 AcceptPageSize + ) +{ + EFI_STATUS Status; + UINT64 Pages; + UINT64 Stride; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + volatile MP_WAKEUP_MAILBOX *MailBox; + + Status =3D EFI_SUCCESS; + PhysicalAddress =3D StartAddress; + Stride =3D GetCpusNum () * AcceptChunkSize; + MailBox =3D (volatile MP_WAKEUP_MAILBOX *) GetTdxMailBox (); + + while (!EFI_ERROR(Status) && PhysicalAddress < StartAddress + Length) { + // + // Decrease size of near end of resource if needed. + // + Pages =3D MIN (AcceptChunkSize, StartAddress + Length - PhysicalAddres= s) / AcceptPageSize; + + MailBox->Tallies[0] +=3D (UINT32)Pages; + + Status =3D TdAcceptPages (PhysicalAddress, Pages, AcceptPageSize); + // + // Bump address to next chunk this cpu is responisble for + // + PhysicalAddress +=3D Stride; + } + + return Status; +} + +/** + This function will be called to accept pages. BSP and APs are invokded + to do the task together. + + TDCALL(ACCEPT_PAGE) supports the accept page size of 4k and 2M. To + simplify the implementation, the Memory to be accpeted is splitted + into 3 parts: + ----------------- <-- StartAddress1 (not 2M aligned) + | part 1 | Length1 < 2M + |---------------| <-- StartAddress2 (2M aligned) + | | Length2 =3D Integer multiples of 2M + | part 2 | + | | + |---------------| <-- StartAddress3 + | part 3 | Length3 < 2M + |---------------| + + part 1) will be accepted in 4k and by BSP. + Part 2) will be accepted in 2M and by BSP/AP. + Part 3) will be accepted in 4k and by BSP. + + @param[in] PhysicalAddress Start physical adress + @param[in] PhysicalEnd End physical address + + @retval EFI_SUCCESS Accept memory successfully + @retval Others Other errors as indicated +**/ +EFI_STATUS +EFIAPI +MpAcceptMemoryResourceRange ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN EFI_PHYSICAL_ADDRESS PhysicalEnd + ) +{ + EFI_STATUS Status; + UINT64 AcceptChunkSize; + UINT64 AcceptPageSize; + UINT64 StartAddress1; + UINT64 StartAddress2; + UINT64 StartAddress3; + UINT64 TotalLength; + UINT64 Length1; + UINT64 Length2; + UINT64 Length3; + UINT32 Index; + UINT32 CpusNum; + volatile MP_WAKEUP_MAILBOX *MailBox; + + AcceptChunkSize =3D FixedPcdGet64 (PcdTdxAcceptChunkSize); + AcceptPageSize =3D FixedPcdGet64 (PcdTdxAcceptPageSize); + TotalLength =3D PhysicalEnd - PhysicalAddress; + StartAddress1 =3D 0; + StartAddress2 =3D 0; + StartAddress3 =3D 0; + Length1 =3D 0; + Length2 =3D 0; + Length3 =3D 0; + + if (AcceptPageSize =3D=3D SIZE_4KB || TotalLength <=3D SIZE_2MB) { + // + // if total length is less than 2M, then we accept pages in 4k + // + StartAddress1 =3D 0; + Length1 =3D 0; + StartAddress2 =3D PhysicalAddress; + Length2 =3D PhysicalEnd - PhysicalAddress; + StartAddress3 =3D 0; + Length3 =3D 0; + AcceptPageSize =3D SIZE_4KB; + } else if (AcceptPageSize =3D=3D SIZE_2MB) { + // + // Total length is bigger than 2M and Page Accept size 2M is supported. + // + if ((PhysicalAddress & ALIGNED_2MB_MASK) =3D=3D 0) { + // + // Start address is 2M aligned + // + StartAddress1 =3D 0; + Length1 =3D 0; + StartAddress2 =3D PhysicalAddress; + Length2 =3D TotalLength & ~(UINT64)ALIGNED_2MB_MASK; + + if (TotalLength > Length2) { + // + // There is remaining part 3) + // + StartAddress3 =3D StartAddress2 + Length2; + Length3 =3D TotalLength - Length2; + ASSERT (Length3 < SIZE_2MB); + } + } else { + // + // Start address is not 2M aligned and total length is bigger than 2= M. + // + StartAddress1 =3D PhysicalAddress; + ASSERT (TotalLength > SIZE_2MB); + Length1 =3D SIZE_2MB - (PhysicalAddress & ALIGNED_2MB_MASK); + if (TotalLength - Length1 < SIZE_2MB) { + // + // The Part 2) length is less than 2MB, so let's accept all the + // memory in 4K + // + Length1 =3D TotalLength; + + } else { + StartAddress2 =3D PhysicalAddress + Length1; + Length2 =3D (TotalLength - Length1) & ~(UINT64)ALIGNED_2MB_MASK; + Length3 =3D TotalLength - Length1 - Length2; + StartAddress3 =3D Length3 > 0 ? StartAddress2 + Length2 : 0; + ASSERT (Length3 < SIZE_2MB); + } + } + } + + DEBUG ((DEBUG_INFO, "TdAccept: 0x%llx - 0x%llx\n", PhysicalAddress, Tota= lLength)); + DEBUG ((DEBUG_INFO, " Part1: 0x%llx - 0x%llx\n", StartAddress1, Length= 1)); + DEBUG ((DEBUG_INFO, " Part2: 0x%llx - 0x%llx\n", StartAddress2, Length= 2)); + DEBUG ((DEBUG_INFO, " Part3: 0x%llx - 0x%llx\n", StartAddress3, Length= 3)); + DEBUG ((DEBUG_INFO, " Chunk: 0x%llx, Page : 0x%llx\n", AcceptChunkSize= , AcceptPageSize)); + + MpSerializeStart (); + + if (Length2 > 0) { + MpSendWakeupCommand ( + MpProtectedModeWakeupCommandAcceptPages, + 0, + StartAddress2, + StartAddress2 + Length2, + AcceptChunkSize, + AcceptPageSize); + + Status =3D BspAcceptMemoryResourceRange ( + StartAddress2, + Length2, + AcceptChunkSize, + AcceptPageSize); + ASSERT (!EFI_ERROR (Status)); + } + + if (Length1 > 0) { + Status =3D BspAcceptMemoryResourceRange ( + StartAddress1, + Length1, + AcceptChunkSize, + SIZE_4KB); + ASSERT (!EFI_ERROR (Status)); + } + + if (Length3 > 0) { + Status =3D BspAcceptMemoryResourceRange ( + StartAddress3, + Length3, + AcceptChunkSize, + SIZE_4KB); + ASSERT (!EFI_ERROR (Status)); + } + + MpSerializeEnd (); + + CpusNum =3D GetCpusNum (); + MailBox =3D (volatile MP_WAKEUP_MAILBOX *) GetTdxMailBox (); + + DEBUG ((DEBUG_INFO, "AcceptPage Tallies:\n")); + DEBUG ((DEBUG_INFO, " ")); + for (Index =3D 0; Index < CpusNum; Index++) { + DEBUG ((DEBUG_INFO, "%8d", MailBox->Tallies[Index])); + if (Index % 8 =3D=3D 7) { + DEBUG ((DEBUG_INFO, "\n")); + DEBUG ((DEBUG_INFO, " ")); + } + } + DEBUG ((DEBUG_INFO, "\n")); + + for (Index =3D 0; Index < CpusNum; Index++) { + if (MailBox->Errors[Index] > 0) { + Status =3D EFI_DEVICE_ERROR; + DEBUG ((DEBUG_ERROR, "Error(%d) of CPU-%d when accepting memory\n", + MailBox->Errors[Index], Index)); + } + } + + return Status; +} + +/** + Dump out the hob list + + @param[in] HobStart Start address of the hob list +**/ +VOID +EFIAPI +DEBUG_HOBLIST ( + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + Hob.Raw =3D (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + DEBUG ((DEBUG_INFO, "HOB(%p) : %x %x\n", Hob, Hob.Header->HobType, Hob= .Header->HobLength)); + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + DEBUG ((DEBUG_INFO, "\t: %x %x %llx %llx\n", + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength)); + + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + DEBUG ((DEBUG_INFO, "\t: %llx %llx %x\n", + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength, + Hob.MemoryAllocation->AllocDescriptor.MemoryType)); + break; + default: + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + } +} + +/** + Check the value whether in the valid list. + + @param[in] Value A value + @param[in] ValidList A pointer to valid list + @param[in] ValidListLength Length of valid list + + @retval TRUE The value is in valid list. + @retval FALSE The value is not in valid list. + +**/ +BOOLEAN +EFIAPI +IsInValidList ( + IN UINT32 Value, + IN UINT32 *ValidList, + IN UINT32 ValidListLength +) { + UINT32 index; + + if (ValidList =3D=3D NULL) { + return FALSE; + } + + for (index =3D 0; index < ValidListLength; index ++) { + if (ValidList[index] =3D=3D Value) { + return TRUE; + } + } + + return FALSE; +} + +/** + Check the integrity of VMM Hob List. + + @param[in] VmmHobList A pointer to Hob List + + @retval TRUE The Hob List is valid. + @retval FALSE The Hob List is invalid. + +**/ +BOOLEAN +EFIAPI +ValidateHobList ( + IN CONST VOID *VmmHobList + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINT32 EFI_BOOT_MODE_LIST[12] =3D { BOOT_WITH_FULL_CONFIGURATION, + BOOT_WITH_MINIMAL_CONFIGURATION, + BOOT_ASSUMING_NO_CONFIGURATION_CHANGES, + BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAG= NOSTICS, + BOOT_WITH_DEFAULT_SETTINGS, + BOOT_ON_S4_RESUME, + BOOT_ON_S5_RESUME, + BOOT_WITH_MFG_MODE_SETTINGS, + BOOT_ON_S2_RESUME, + BOOT_ON_S3_RESUME, + BOOT_ON_FLASH_UPDATE, + BOOT_IN_RECOVERY_MODE + }; + + UINT32 EFI_RESOURCE_TYPE_LIST[8] =3D { EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_MEMORY_MAPPED_IO, + EFI_RESOURCE_IO, + EFI_RESOURCE_FIRMWARE_DEVICE, + EFI_RESOURCE_MEMORY_MAPPED_IO_PORT, + EFI_RESOURCE_MEMORY_RESERVED, + EFI_RESOURCE_IO_RESERVED, + EFI_RESOURCE_MAX_MEMORY_TYPE + }; + + if (VmmHobList =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "HOB: HOB data pointer is NULL\n")); + return FALSE; + } + + Hob.Raw =3D (UINT8 *) VmmHobList; + + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->Reserved !=3D (UINT32) 0) { + DEBUG ((DEBUG_ERROR, "HOB: Hob header Reserved filed should be zero\= n")); + return FALSE; + } + + if (Hob.Header->HobLength =3D=3D 0) { + DEBUG ((DEBUG_ERROR, "HOB: Hob header LEANGTH should not be zero\n= ")); + return FALSE; + } + + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_HANDOFF: + if (Hob.Header->HobLength !=3D sizeof(EFI_HOB_HANDOFF_INFO_TABLE))= { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_HANDOFF)); + return FALSE; + } + + if (IsInValidList (Hob.HandoffInformationTable->BootMode, EFI_BOOT= _MODE_LIST, 12) =3D=3D FALSE) { + DEBUG ((DEBUG_ERROR, "HOB: Unknow HandoffInformationTable BootMo= de type. Type: 0x%08x\n", Hob.HandoffInformationTable->BootMode)); + return FALSE; + } + + if ((Hob.HandoffInformationTable->EfiFreeMemoryTop % 4096) !=3D 0)= { + DEBUG ((DEBUG_ERROR, "HOB: HandoffInformationTable EfiFreeMemory= Top address must be 4-KB aligned to meet page restrictions of UEFI.\ + Address: 0x%016lx\n", Hob.HandoffInformatio= nTable->EfiFreeMemoryTop)); + return FALSE; + } + break; + + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + if (Hob.Header->HobLength !=3D sizeof(EFI_HOB_RESOURCE_DESCRIPTOR)= ) { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_RESOURCE_DESCRIPTOR)); + return FALSE; + } + + if (IsInValidList (Hob.ResourceDescriptor->ResourceType, EFI_RESOU= RCE_TYPE_LIST, 8) =3D=3D FALSE) { + DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceTyp= e type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceType)); + return FALSE; + } + + if ((Hob.ResourceDescriptor->ResourceAttribute & (~(EFI_RESOURCE_A= TTRIBUTE_PRESENT | + EFI_RESOURCE_ATT= RIBUTE_INITIALIZED | + EFI_RESOURCE_ATT= RIBUTE_TESTED | + EFI_RESOURCE_ATT= RIBUTE_READ_PROTECTED | + EFI_RESOURCE_ATT= RIBUTE_WRITE_PROTECTED | + EFI_RESOURCE_ATT= RIBUTE_EXECUTION_PROTECTED | + EFI_RESOURCE_ATT= RIBUTE_PERSISTENT | + EFI_RESOURCE_ATT= RIBUTE_SINGLE_BIT_ECC | + EFI_RESOURCE_ATT= RIBUTE_MULTIPLE_BIT_ECC | + EFI_RESOURCE_ATT= RIBUTE_ECC_RESERVED_1 | + EFI_RESOURCE_ATT= RIBUTE_ECC_RESERVED_2 | + EFI_RESOURCE_ATT= RIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATT= RIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATT= RIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATT= RIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATT= RIBUTE_16_BIT_IO | + EFI_RESOURCE_ATT= RIBUTE_32_BIT_IO | + EFI_RESOURCE_ATT= RIBUTE_64_BIT_IO | + EFI_RESOURCE_ATT= RIBUTE_UNCACHED_EXPORTED | + EFI_RESOURCE_ATT= RIBUTE_READ_PROTECTABLE | + EFI_RESOURCE_ATT= RIBUTE_WRITE_PROTECTABLE | + EFI_RESOURCE_ATT= RIBUTE_EXECUTION_PROTECTABLE | + EFI_RESOURCE_ATT= RIBUTE_PERSISTABLE | + EFI_RESOURCE_ATT= RIBUTE_READ_ONLY_PROTECTED | + EFI_RESOURCE_ATT= RIBUTE_READ_ONLY_PROTECTABLE | + EFI_RESOURCE_ATT= RIBUTE_MORE_RELIABLE | + EFI_RESOURCE_ATT= RIBUTE_ENCRYPTED))) !=3D 0) { + DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceAtt= ribute type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceAttribute)); + return FALSE; + } + break; + + // EFI_HOB_GUID_TYPE is variable length data, so skip check + case EFI_HOB_TYPE_GUID_EXTENSION: + break; + + case EFI_HOB_TYPE_FV: + if (Hob.Header->HobLength !=3D sizeof (EFI_HOB_FIRMWARE_VOLUME)) { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV)); + return FALSE; + } + break; + + case EFI_HOB_TYPE_FV2: + if (Hob.Header->HobLength !=3D sizeof(EFI_HOB_FIRMWARE_VOLUME2)) { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV2)); + return FALSE; + } + break; + + case EFI_HOB_TYPE_FV3: + if (Hob.Header->HobLength !=3D sizeof(EFI_HOB_FIRMWARE_VOLUME3)) { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV3)); + return FALSE; + } + break; + + case EFI_HOB_TYPE_CPU: + if (Hob.Header->HobLength !=3D sizeof(EFI_HOB_CPU)) { + DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding= hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_CPU)); + return FALSE; + } + + for (UINT32 index =3D 0; index < 6; index ++) { + if (Hob.Cpu->Reserved[index] !=3D 0) { + DEBUG ((DEBUG_ERROR, "HOB: Cpu Reserved field will always be s= et to zero.\n")); + return FALSE; + } + } + break; + + default: + DEBUG ((DEBUG_ERROR, "HOB: Hob type is not know. Type: 0x%04x\n", = Hob.Header->HobType)); + return FALSE; + } + // Get next HOB + Hob.Raw =3D (UINT8 *) (Hob.Raw + Hob.Header->HobLength); + } + + return TRUE; +} + +/** + Processing the incoming HobList for the TDX + + Firmware must parse list, and accept the pages of memory before their ca= n be + use by the guest. + + @param[in] VmmHobList The Hoblist pass the firmware + + @retval EFI_SUCCESS Process the HobList successfully + @retval Others Other errors as indicated + +**/ +EFI_STATUS +EFIAPI +ProcessHobList ( + IN CONST VOID *VmmHobList + ) +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS PhysicalEnd; + + Status =3D EFI_SUCCESS; + ASSERT (VmmHobList !=3D NULL); + Hob.Raw =3D (UINT8 *) VmmHobList; + + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + + if (Hob.Header->HobType =3D=3D EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor= ->ResourceType)); + + if (Hob.ResourceDescriptor->ResourceType =3D=3D EFI_RESOURCE_SYSTEM_= MEMORY) { + DEBUG ((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescr= iptor->ResourceAttribute)); + DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%llx\n", Hob.ResourceDescrip= tor->PhysicalStart)); + DEBUG ((DEBUG_INFO, "ResourceLength: 0x%llx\n", Hob.ResourceDescri= ptor->ResourceLength)); + DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owne= r)); + + PhysicalEnd =3D Hob.ResourceDescriptor->PhysicalStart + Hob.Resour= ceDescriptor->ResourceLength; + + Status =3D MpAcceptMemoryResourceRange ( + Hob.ResourceDescriptor->PhysicalStart, + PhysicalEnd); + if (EFI_ERROR (Status)) { + break; + } + } + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + } + + return Status; +} + +/** + In Tdx guest, some information need to be passed from host VMM to guest + firmware. For example, the memory resource, etc. These information are + prepared by host VMM and put in HobList which is described in TdxMetadat= a. + + Information in HobList is treated as external input. From the security + perspective before it is consumed, it should be validated. + + @retval EFI_SUCCESS Successfully process the hoblist + @retval Others Other error as indicated +**/ +EFI_STATUS +EFIAPI +ProcessTdxHobList ( + VOID + ) +{ + EFI_STATUS Status; + VOID *TdHob; + TD_RETURN_DATA TdReturnData; + + TdHob =3D (VOID *) (UINTN) FixedPcdGet32 (PcdOvmfSecGhcbBase); + Status =3D TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_INFO, + "Intel Tdx Started with (GPAW: %d, Cpus: %d)\n", + TdReturnData.TdInfo.Gpaw, + TdReturnData.TdInfo.NumVcpus + )); + + // + // Validate HobList + // + if (ValidateHobList (TdHob) =3D=3D FALSE) { + return EFI_INVALID_PARAMETER; + } + + // + // Process Hoblist to accept memory + // + Status =3D ProcessHobList (TdHob); + + return Status; +} diff --git a/OvmfPkg/Sec/IntelTdx.h b/OvmfPkg/Sec/IntelTdx.h new file mode 100644 index 000000000000..9420f586b176 --- /dev/null +++ b/OvmfPkg/Sec/IntelTdx.h @@ -0,0 +1,33 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __INTEL_TDX_H__ +#define __INTEL_TDX_H__ + +#include +#include +#include +#include +#include + +/** + In Tdx guest, some information need to be passed from host VMM to guest + firmware. For example, the memory resource, etc. These information are + prepared by host VMM and put in HobList which is described in TdxMetadat= a. + + Information in HobList is treated as external input. From the security + perspective before it is consumed, it should be validated. + + @retval EFI_SUCCESS Successfully process the hoblist + @retval Others Other error as indicated +**/ +EFI_STATUS +EFIAPI +ProcessTdxHobList ( + VOID + ); +#endif diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 707b0d4bbff4..56ee8c4a230c 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -29,8 +29,10 @@ #include #include #include - +#include +#include #include +#include "IntelTdx.h" =20 #define SEC_IDT_ENTRY_COUNT 34 =20 @@ -865,6 +867,24 @@ SevEsIsEnabled ( return (SevEsWorkArea->SevEsEnabled !=3D 0); } =20 +/** + Check TDX is enabled. + + @retval TRUE TDX is enabled + @retval FALSE TDX is not enabled +**/ +BOOLEAN +SecTdxIsEnabled ( + VOID + ) +{ + CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; + + CcWorkAreaHeader =3D (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *) FixedPc= dGet32 (PcdOvmfWorkAreaBase); + return (CcWorkAreaHeader !=3D NULL && CcWorkAreaHeader->GuestType =3D=3D= GUEST_TYPE_INTEL_TDX); +} + + VOID EFIAPI SecCoreStartupWithStack ( @@ -878,6 +898,19 @@ SecCoreStartupWithStack ( UINT32 Index; volatile UINT8 *Table; =20 +#if defined (MDE_CPU_X64) + if (SecTdxIsEnabled ()) { + // + // For Td guests, the memory map info is in TdHobLib. It should be pro= cessed + // first so that the memory is accepted. Otherwise access to the unacc= epted + // memory will trigger tripple fault. + // + if (ProcessTdxHobList () !=3D EFI_SUCCESS) { + CpuDeadLoop (); + } + } +#endif + // // To ensure SMM can't be compromised on S3 resume, we must force re-ini= t of // the BaseExtractGuidedSectionLib. Since this is before library contruc= tors @@ -895,13 +928,20 @@ SecCoreStartupWithStack ( // we use a loop rather than CopyMem. // IdtTableInStack.PeiService =3D NULL; + for (Index =3D 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { - UINT8 *Src; - UINT8 *Dst; - UINTN Byte; + // + // 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 =3D (CONST UINT8 *) &mIdtEntryTemplate; + Dst =3D (volatile UINT8 *) &IdtTableInStack.IdtTable[Index]; =20 - Src =3D (UINT8 *) &mIdtEntryTemplate; - Dst =3D (UINT8 *) &IdtTableInStack.IdtTable[Index]; for (Byte =3D 0; Byte < sizeof (mIdtEntryTemplate); Byte++) { Dst[Byte] =3D Src[Byte]; } @@ -947,6 +987,14 @@ SecCoreStartupWithStack ( AsmEnableCache (); } =20 + if (SecTdxIsEnabled ()) { + // + // 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, diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index 6083fa21a433..4f16ff5d8330 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -28,6 +28,7 @@ Ia32/SecEntry.nasm =20 [Sources.X64] + IntelTdx.c X64/SecEntry.nasm =20 [Packages] @@ -51,6 +52,8 @@ ExtractGuidedSectionLib LocalApicLib CpuExceptionHandlerLib + TdxLib + TdxMailboxLib =20 [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED @@ -73,6 +76,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentialComputingWorkAreaHeader gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptChunkSize + gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase =20 [FeaturePcd] gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81490): https://edk2.groups.io/g/devel/message/81490 Mute This Topic: https://groups.io/mt/86085759/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81491+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81491+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405267; cv=none; d=zohomail.com; s=zohoarc; b=dlCVQt8ctz638iTlb2MY/NO8f1TB2cibaQOvU2awG8NB1hmRyznkdlrs0oLq2BQpQurOB0k5LxHdKpHVsVuAmQYwF0No+j8RQA3B0BcohYKN+D90k+CmZkxuBpUc1pXuur6Ms9T6cYp4f4+R/Km8CQBCQuAd7O+Z5uQA56z5gyI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405267; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Hkp4Lvk5VuJ5rg4gJMblsioseagn04c5y8OIIcsp21c=; b=IGIZ/ydQ8FxIglxl0H9FgLcj437adk3gflfo+EL/p1ZkHmrxyJ5DSLp6X90he0GwxnmGdKb3vhRlVMjv5iGTFg8+Lna83biMuweR7bE6MeTeptkmaQ8RA5WnFekfRDSTVNXsn5DqAYIpW7K3gWQMJMoyDVpwbJzzPrDpZYUzI54= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81491+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405267643573.3772139067822; Mon, 4 Oct 2021 20:41:07 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id QLqvYY1788612xUE1wQZiAYX; Mon, 04 Oct 2021 20:41:07 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:05 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958235" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958235" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:48 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828712" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:46 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 19/28] OvmfPkg: Check Tdx in QemuFwCfgPei to avoid DMA operation Date: Tue, 5 Oct 2021 11:39:30 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: T9guwG9KfJCOQziTXTqyQ3HUx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405267; bh=WQMwHupv2stMDXm11NALnecvfoiO9PIyPLcCjg1g1cE=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=iz8PEQZwLJNoEWUKqSqGjNHNd1cqUFh+/QFYzxAbGLAkKpL9dwJYDrqUVwr8S6x40oT H8ji+4SSLqO2ZznQh7+QjSqZK77LIQqhqjC06/A5PQoeY963afR0zT0jXmc+CdtGEdlbQ WUoqp31xrTNOnXV94QWhCFwqNwGs32zx2cU= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405268744100015 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 If TDX is enabled then we do not support DMA operation in PEI phase. This is mainly because DMA in TDX guest requires using bounce buffer (which need to allocate dynamic memory and allocating a PAGE size'd buffer can be challenge in PEI phase). Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- .../QemuFwCfgLib/QemuFwCfgLibInternal.h | 11 +++++++ OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 32 +++++++++++++++++++ .../Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf | 2 ++ 3 files changed, 45 insertions(+) diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/= Library/QemuFwCfgLib/QemuFwCfgLibInternal.h index 1fa80686e0bd..1130552bc60a 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h @@ -60,4 +60,15 @@ InternalQemuFwCfgDmaBytes ( IN UINT32 Control ); =20 +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +QemuFwCfgIsTdxGuest ( + VOID + ); + #endif diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/Library/= QemuFwCfgLib/QemuFwCfgPei.c index ecabd88fab66..bd2e51363bc6 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c @@ -14,12 +14,30 @@ #include #include #include +#include =20 #include "QemuFwCfgLibInternal.h" =20 STATIC BOOLEAN mQemuFwCfgSupported =3D FALSE; STATIC BOOLEAN mQemuFwCfgDmaSupported; =20 +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +QemuFwCfgIsTdxGuest ( + VOID + ) +{ + CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; + + CcWorkAreaHeader =3D (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *) FixedPc= dGet32 (PcdOvmfWorkAreaBase); + return (CcWorkAreaHeader !=3D NULL && CcWorkAreaHeader->GuestType =3D=3D= GUEST_TYPE_INTEL_TDX); +} + =20 /** Returns a boolean indicating if the firmware configuration interface @@ -82,6 +100,14 @@ QemuFwCfgInitialize ( // if (MemEncryptSevIsEnabled ()) { DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n= ")); + } else if (QemuFwCfgIsTdxGuest ()) { + // + // If TDX is enabled then we do not support DMA operations in PEI ph= ase. + // This is mainly because DMA in TDX guest requires using bounce buf= fer + // (which need to allocate dynamic memory and allocating a PAGE size= 'd + // buffer can be challenge in PEI phase) + // + DEBUG ((DEBUG_INFO, "TDX: QemuFwCfg fallback to IO Port interface.\n= ")); } else { mQemuFwCfgDmaSupported =3D TRUE; DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n")); @@ -162,6 +188,12 @@ InternalQemuFwCfgDmaBytes ( // ASSERT (!MemEncryptSevIsEnabled ()); =20 + // + // TDX does not support DMA operations in PEI stage, we should + // not have reached here. + // + ASSERT (!QemuFwCfgIsTdxGuest ()); + Access.Control =3D SwapBytes32 (Control); Access.Length =3D SwapBytes32 (Size); Access.Address =3D SwapBytes64 ((UINTN)Buffer); diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf b/OvmfPkg/Lib= rary/QemuFwCfgLib/QemuFwCfgPeiLib.inf index 9f9af7d03201..3910511880c9 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf @@ -43,3 +43,5 @@ MemoryAllocationLib MemEncryptSevLib =20 +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81491): https://edk2.groups.io/g/devel/message/81491 Mute This Topic: https://groups.io/mt/86085760/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81492+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81492+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405267; cv=none; d=zohomail.com; s=zohoarc; b=eu95lU6bFUp1QffkuWAwb3TXwp/wvt8fmKSi8xcCSruWTmeqvNNibhC6Ux2v8N4RwnMT8BZeL0LP9oViXW3byipgmAb+r7QI5BDLdBL/Jc2nWEZ1YD4aYIwtqPE2KNf42CllpVlc0UOV9sKuQYXu0Ve80eDdRXiMRkGl+YAB+Rk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405267; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=J+2Cw8G8+d0zJ3eN6tmR9mB0Kj7SRMmLlOX9OjPhN6A=; b=ndmPsdKC5elybeye45v7ozHpTD1ip3TcSCe/qnPNVmez7MzTmUoegh64zjz+L+ysirOLsoaVjUMuPF/Bb8uYW65VhohaYwIZgalTN1cs+seIt7GGgdSS3K+RUgU+a4j5xS5Ltw/c18SDPs+ygblezltUGhMh3GYIuDvuou7dG4Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81492+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405267743118.66495094076163; Mon, 4 Oct 2021 20:41:07 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id llwlYY1788612xFKEFdF6NOT; Mon, 04 Oct 2021 20:41:07 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.20836.1633405265395581286 for ; Mon, 04 Oct 2021 20:41:05 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958238" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958238" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:51 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828748" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:49 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Jian J Wang , Hao A Wu , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 20/28] MdeModulePkg: EFER should not be changed in TDX Date: Tue, 5 Oct 2021 11:39:31 +0800 Message-Id: <9f383ae10faa94b915750bec72ca8b5a28b8469b.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: eaoxBodpDIcOChetOOW084myx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405267; bh=yjMf96s9QCPeYfcXEPZBYURK20Mt/Rzb4Nqr0PoXqUg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=cIWpg3qhYkWli78xElAw+92KOph+OOaFqKRkcyteLIDeYtUu1SLAfTNA8oeSQrHDXra LJOzwJgDbBsMBY5RT5qUbQ6mUnmPTm9+lqaLt5FNQgPu1bXbdfaK8VKOOgDU6Ruu8SESn y1medBsFyMBgAZ+vxA6XSgAinoODBIbOWjM= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405268758100016 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In TDX IA32_ERER is RO to host VMM. It could not be changed. PcdIa32EferChangeAllowed is added in MdeModulePkg.dec and it is to be set to FALSE in Tdx guest. Cc: Jian J Wang Cc: Hao A Wu Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf | 1 + MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c | 6 ++++++ MdeModulePkg/MdeModulePkg.dec | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/Dx= eIplPeim/DxeIpl.inf index 19b8a4c8aefa..106b679b6bd0 100644 --- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf @@ -117,6 +117,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ##= SOMETIMES_CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ##= CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ##= CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed ##= CONSUMES =20 [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64] gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIM= ES_CONSUMES diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePk= g/Core/DxeIplPeim/X64/VirtualMemory.c index 6831946c54d3..8a3b72509310 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -148,6 +148,12 @@ IsEnableNonExecNeeded ( return FALSE; } =20 + // + // Intel TDX sets this flag to FALSE. + // + if (!PcdGetBool (PcdIa32EferChangeAllowed)) { + return FALSE; + } // // XD flag (BIT63) in page table entry is only valid if IA32_EFER.NXE is= set. // Features controlled by Following PCDs need this feature to be enabled. diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 133e04ee86ca..007044a311c2 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -2138,6 +2138,11 @@ # @Prompt GHCB Pool Size gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0|UINT64|0x00030008 =20 + ## This dynamic PCD indicates if IA32_EFER can be changed. The default v= alue is TRUE but in + # Intel TDX change of IA32_EFER is not allowed. + # @Prompt The flag which indicates if IA32_EFER is allowed to be changed. + gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed|TRUE|BOOLEAN|0x0= 0030009 + [PcdsDynamicEx] ## This dynamic PCD enables the default variable setting. # Its value is the default store ID value. The default value is zero as= Standard default. --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81492): https://edk2.groups.io/g/devel/message/81492 Mute This Topic: https://groups.io/mt/86085761/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81494+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81494+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405268; cv=none; d=zohomail.com; s=zohoarc; b=Ie4mM68OvGhBN9/Xp1iaSdKuCMIb5tzNvCvYiBa42ywAI5hIppHZo7XelbuOZdgwOEJ97po4NOF4TBogNoBQzJ4j/B+gxW2WIYz838mMrr7Mc58aDwTLl8+RhzVTdVTOC+lzfPnMBjv20oZJdhGQT15rGqtD/8GbmO5HCu6szt4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405268; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=WCwUeN3LS00aZZ6g28PL+OoQ0CzGiFhokQDEeAD+iyA=; b=V6Uvvg83Yqo/HAnPZ7C6rSndR+/8xKDUdjpH8OqDczfUnaphuGyf9XD7k/yit9LkS85gnUTqimI0BHq1tWoickRVhKXLkO9bUTrz8FEVk0XaCTAVILJ8882ThD41dEMXA4h9EBatYtQeUta7HS1uba6d5JieN/LOLEpHY9bPyyg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81494+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405268669254.6711594848374; Mon, 4 Oct 2021 20:41:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id SR6NYY1788612x98IYgAZefZ; Mon, 04 Oct 2021 20:41:08 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.20836.1633405265395581286 for ; Mon, 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958239" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958239" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:54 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828764" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:52 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 21/28] OvmfPkg: Update PlatformPei to support TDX Date: Tue, 5 Oct 2021 11:39:32 +0800 Message-Id: <7a6c9317555de257ad0fd1d76c59c841fa601086.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: kxgEpHNOGCWaww9f6ExrBqpfx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405268; bh=+X4eppMhnRopDTfE0SX/FH5g1JyDcf1k+tYAnNk1ilo=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=s3agfYbeRsbH6Oz5iL1ZEuTXMBCwCDrVTDlwyknCQLNaxzKoMaG5gDAI5yMrxnrd7IC 25EYzbfupPIpHV7t2gmUFQAbf6uN5jfAEUR2D65YpHCdSwnzLoGDQa8XgRN7PcsEV9jQa 7iKtbITnGgFRvNbaSTiBIyavHV+2admsSxg= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405270812100027 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Intel TDX has its own requirement in InitializePlatform (PlatformPei). 1. Publish the ram region Host VMM pass the memory region to TDVF in TD Hob. These memory are accepted by TDVF before they're available for access. TDVF publish these memory information in the final hoblist for DXE. 2. Relocate mailbox At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbox) is pre-allocated by host VMM. BSP & APs do the page accept together in that memory region. After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-size memory block which is allocated in the ACPI Nvs memory. APs are waken up and spin around the relocated mailbox waiting for further command. 3. Create PlatformInfoHob PlatformInfoHob contains the TDX specific information, for example, the relocated Mailbox address. gUefiOvmfPkgTdxPlatformGuid is the new GUID added in OvmfPkg.dec for this purpose. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/PlatformPei/FeatureControl.c | 8 +- OvmfPkg/PlatformPei/IntelTdx.c | 290 +++++++++++++++++++++++++ OvmfPkg/PlatformPei/IntelTdxNull.c | 49 +++++ OvmfPkg/PlatformPei/MemDetect.c | 57 +++-- OvmfPkg/PlatformPei/Platform.c | 1 + OvmfPkg/PlatformPei/Platform.h | 28 +++ OvmfPkg/PlatformPei/PlatformPei.inf | 13 ++ OvmfPkg/PlatformPei/X64/ApRunLoop.nasm | 83 +++++++ 9 files changed, 516 insertions(+), 14 deletions(-) create mode 100644 OvmfPkg/PlatformPei/IntelTdx.c create mode 100644 OvmfPkg/PlatformPei/IntelTdxNull.c create mode 100644 OvmfPkg/PlatformPei/X64/ApRunLoop.nasm diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 6f535d718203..b489c69a736e 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -128,6 +128,7 @@ gQemuKernelLoaderFsMediaGuid =3D {0x1428f772, 0xb64a, 0x441e, {= 0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}} gGrubFileGuid =3D {0xb5ae312c, 0xbc8a, 0x43b1, {= 0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}} gConfidentialComputingSecretGuid =3D {0xadf956ad, 0xe98c, 0x484c, {= 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}} + gUefiOvmfPkgTdxPlatformGuid =3D {0xdec9b486, 0x1f16, 0x47c7, {= 0x8f, 0x68, 0xdf, 0x1a, 0x41, 0x88, 0x8b, 0xa5}} =20 [Ppis] # PPI whose presence in the PPI database signals that the TPM base addre= ss diff --git a/OvmfPkg/PlatformPei/FeatureControl.c b/OvmfPkg/PlatformPei/Fea= tureControl.c index dccf9505dd7b..cf1a25722704 100644 --- a/OvmfPkg/PlatformPei/FeatureControl.c +++ b/OvmfPkg/PlatformPei/FeatureControl.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include =20 #include "Platform.h" =20 @@ -37,7 +39,11 @@ WriteFeatureControl ( IN OUT VOID *WorkSpace ) { - AsmWriteMsr64 (MSR_IA32_FEATURE_CONTROL, mFeatureControlValue); + if (PlatformPeiIsTdxGuest ()) { + TdVmCall (TDVMCALL_WRMSR, (UINT64) MSR_IA32_FEATURE_CONTROL, mFeatureC= ontrolValue, 0, 0, 0); + } else { + AsmWriteMsr64 (MSR_IA32_FEATURE_CONTROL, mFeatureControlValue); + } } =20 /** diff --git a/OvmfPkg/PlatformPei/IntelTdx.c b/OvmfPkg/PlatformPei/IntelTdx.c new file mode 100644 index 000000000000..684907179c10 --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdx.c @@ -0,0 +1,290 @@ +/** @file + Initialize Intel TDX support. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Platform.h" + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ) +{ + CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; + + CcWorkAreaHeader =3D (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *) FixedPc= dGet32 (PcdOvmfWorkAreaBase); + return (CcWorkAreaHeader !=3D NULL && CcWorkAreaHeader->GuestType =3D=3D= GUEST_TYPE_INTEL_TDX); +} + + +VOID +EFIAPI +DEBUG_HOBLIST ( + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + Hob.Raw =3D (UINT8 *) HobStart; + // + // Parse the HOB list until end of list or matching type is found. + // + while (!END_OF_HOB_LIST (Hob)) { + DEBUG ((DEBUG_INFO, "HOB(%p) : %x %x\n", Hob, Hob.Header->HobType, Hob= .Header->HobLength)); + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + DEBUG ((DEBUG_INFO, "\t: %x %x %llx %llx\n", + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength)); + + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + DEBUG ((DEBUG_INFO, "\t: %llx %llx %x\n", + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength, + Hob.MemoryAllocation->AllocDescriptor.MemoryType)); + break; + default: + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + } +} + +/** + Transfer the incoming HobList for the TD to the final HobList for Dxe. + The Hobs transferred in this function are ResourceDescriptor hob and + MemoryAllocation hob. + + @param[in] VmmHobList The Hoblist pass the firmware + +**/ +VOID +EFIAPI +TransferTdxHobList ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + + // + // PcdOvmfSecGhcbBase is used as the TD_HOB in Tdx guest. + // + Hob.Raw =3D (UINT8 *) (UINTN) PcdGet32 (PcdOvmfSecGhcbBase); + while (!END_OF_HOB_LIST (Hob)) { + switch (Hob.Header->HobType) { + case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: + ResourceAttribute =3D Hob.ResourceDescriptor->ResourceAttribute; + + BuildResourceDescriptorHob ( + Hob.ResourceDescriptor->ResourceType, + ResourceAttribute, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength); + break; + case EFI_HOB_TYPE_MEMORY_ALLOCATION: + BuildMemoryAllocationHob ( + Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, + Hob.MemoryAllocation->AllocDescriptor.MemoryLength, + Hob.MemoryAllocation->AllocDescriptor.MemoryType); + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + } + DEBUG_HOBLIST (GetHobList ()); +} + +/** + + Publish memory regions in Intel TDX guest. + +**/ +VOID +TdxPublishRamRegions ( + VOID + ) +{ + TransferTdxHobList (); + + // + // The memory region defined by PcdOvmfSecGhcbBackupBase is pre-allocate= d by + // host VMM and used as the td mailbox at the beginning of system boot. + // + BuildMemoryAllocationHob ( + PcdGet32 (PcdOvmfSecGhcbBackupBase), + PcdGet32 (PcdOvmfSecGhcbBackupSize), + EfiACPIMemoryNVS + ); +} + +/** + This function check the system status from QEMU via fw_cfg. + If the system status from QEMU is retrieved, its value is set + into PlatformInfoHob. + + @param[in] PlatformInfoHob The data structure of PlatformInfo hob +**/ +VOID +EFIAPI +CheckSystemStatsForOverride ( + IN EFI_HOB_PLATFORM_INFO * PlatformInfoHob + ) +{ + EFI_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + + // + // check for overrides + // + Status =3D QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSiz= e); + if (Status !=3D RETURN_SUCCESS || FwCfgSize !=3D sizeof PlatformInfoHob-= >SystemStates) { + DEBUG ((DEBUG_INFO, "ACPI using S3/S4 defaults\n")); + return; + } + + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof (PlatformInfoHob->SystemStates), PlatformInfo= Hob->SystemStates); +} + +/** + At the beginning of system boot, a 4K-aligned, 4K-size memory (Td mailbo= x) is + pre-allocated by host VMM. BSP & APs do the page accept together in that= memory + region. + + After that TDVF is designed to relocate the mailbox to a 4K-aligned, 4K-= size + memory block which is allocated in the ACPI Nvs memory. APs are waken up= and + spin around the relocated mailbox for further command. + + @return UINT64 Address of the relocated mailbox +**/ +UINT64 +EFIAPI +TdxRelocateMailbox ( + VOID + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Address; + VOID *ApLoopFunc =3D NULL; + UINT32 RelocationPages; + MP_RELOCATION_MAP RelocationMap; + MP_WAKEUP_MAILBOX *RelocatedMailBox; + + // + // Get information needed to setup aps running in their + // run loop in allocated acpi reserved memory + // Add another page for mailbox + // + AsmGetRelocationMap (&RelocationMap); + RelocationPages =3D EFI_SIZE_TO_PAGES ((UINT32)RelocationMap.RelocateAp= LoopFuncSize) + 1; + + Status =3D PeiServicesAllocatePages (EfiACPIMemoryNVS, RelocationPages, = &Address); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to allocate pages to relocate Td mailbox.= %r\n", Status)); + ASSERT (FALSE); + return 0; + } + + ApLoopFunc =3D (VOID *) ((UINTN) Address + EFI_PAGE_SIZE); + + CopyMem ( + ApLoopFunc, + RelocationMap.RelocateApLoopFuncAddress, + RelocationMap.RelocateApLoopFuncSize + ); + + DEBUG ((DEBUG_INFO, "Ap Relocation: mailbox %llx, loop %p\n", + Address, ApLoopFunc)); + + // + // Initialize mailbox + // + RelocatedMailBox =3D (MP_WAKEUP_MAILBOX *)Address; + RelocatedMailBox->Command =3D MpProtectedModeWakeupCommandNoop; + RelocatedMailBox->ApicId =3D MP_CPU_PROTECTED_MODE_MAILBOX_APICID_INVALI= D; + RelocatedMailBox->WakeUpVector =3D 0; + + // + // Wakup APs and have been move to the finalized run loop + // They will spin until guest OS wakes them + // + MpSerializeStart (); + + MpSendWakeupCommand ( + MpProtectedModeWakeupCommandWakeup, + (UINT64)ApLoopFunc, + (UINT64)RelocatedMailBox, + 0, + 0, + 0); + + return (UINT64)RelocatedMailBox; +} + +/** + + This Function checks if TDX is available, if present then it sets + the dynamic PcdTdxIsEnabled and PcdIa32EferChangeAllowed. + + It relocates the td mailbox and create the PlatformInfo Hob which includ= es + the TDX specific information which will be consumed in DXE phase. + + **/ +VOID +IntelTdxInitialize ( + VOID + ) +{ + EFI_HOB_PLATFORM_INFO PlatformInfoHob; + RETURN_STATUS PcdStatus; + UINT32 ConfidentialComputingCategory; + CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; + + if (!PlatformPeiIsTdxGuest ()) { + return; + } + + CcWorkAreaHeader =3D (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *) FixedPc= dGet32 (PcdOvmfWorkAreaBase); + ConfidentialComputingCategory =3D *((UINT32 *)CcWorkAreaHeader); + + PcdStatus =3D PcdSet32S (PcdConfidentialComputingCategory, ConfidentialC= omputingCategory); + ASSERT_RETURN_ERROR (PcdStatus); + + PcdStatus =3D PcdSetBoolS (PcdIa32EferChangeAllowed, FALSE); + ASSERT_RETURN_ERROR (PcdStatus); + + ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); + PlatformInfoHob.HostBridgePciDevId =3D mHostBridgeDevId; + + PlatformInfoHob.RelocatedMailBox =3D TdxRelocateMailbox (); + + CheckSystemStatsForOverride (&PlatformInfoHob); + + BuildGuidDataHob (&gUefiOvmfPkgTdxPlatformGuid, &PlatformInfoHob, sizeof= (EFI_HOB_PLATFORM_INFO)); +} diff --git a/OvmfPkg/PlatformPei/IntelTdxNull.c b/OvmfPkg/PlatformPei/Intel= TdxNull.c new file mode 100644 index 000000000000..35a079d82f66 --- /dev/null +++ b/OvmfPkg/PlatformPei/IntelTdxNull.c @@ -0,0 +1,49 @@ +/** @file + Main SEC phase code. Handles initial TDX Hob List Processing + + Copyright (c) 2008, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ) +{ + return FALSE; +} + +VOID +TdxPublishRamRegions ( + VOID + ) +{ +} + +VOID +IntelTdxInitialize ( + VOID + ) +{ +} + +VOID +AsmGetRelocationMap ( + OUT MP_RELOCATION_MAP *AddressMap + ) +{ +} diff --git a/OvmfPkg/PlatformPei/MemDetect.c b/OvmfPkg/PlatformPei/MemDetec= t.c index 2c2c4641ec8a..43febcb3bf57 100644 --- a/OvmfPkg/PlatformPei/MemDetect.c +++ b/OvmfPkg/PlatformPei/MemDetect.c @@ -35,6 +35,7 @@ Module Name: #include #include #include +#include =20 #include "Platform.h" #include "Cmos.h" @@ -484,6 +485,7 @@ AddressWidthInitialization ( ) { UINT64 FirstNonAddress; + UINT64 TdxSharedPageMask; =20 // // As guest-physical memory size grows, the permanent PEI RAM requiremen= ts @@ -511,7 +513,17 @@ AddressWidthInitialization ( if (mPhysMemAddressWidth <=3D 36) { mPhysMemAddressWidth =3D 36; } - ASSERT (mPhysMemAddressWidth <=3D 48); + + if (PlatformPeiIsTdxGuest ()) { + TdxSharedPageMask =3D TdSharedPageMask (); + if (TdxSharedPageMask =3D=3D (1ULL << 47)) { + mPhysMemAddressWidth =3D 48; + } else { + mPhysMemAddressWidth =3D 52; + } + } + + ASSERT (mPhysMemAddressWidth <=3D 52); } =20 =20 @@ -528,8 +540,10 @@ GetPeiMemoryCap ( UINT32 RegEax; UINT32 RegEdx; UINT32 Pml4Entries; + UINT32 Pml5Entries; UINT32 PdpEntries; UINTN TotalPages; + UINT8 PhysicalAddressBits; =20 // // If DXE is 32-bit, then just return the traditional 64 MB cap. @@ -557,20 +571,33 @@ GetPeiMemoryCap ( } } =20 - if (mPhysMemAddressWidth <=3D 39) { - Pml4Entries =3D 1; - PdpEntries =3D 1 << (mPhysMemAddressWidth - 30); - ASSERT (PdpEntries <=3D 0x200); + PhysicalAddressBits =3D mPhysMemAddressWidth; + Pml5Entries =3D 1; + + if (PhysicalAddressBits > 48) { + Pml5Entries =3D (UINT32) LShiftU64 (1, PhysicalAddressBits - 48); + PhysicalAddressBits =3D 48; + } + + Pml4Entries =3D 1; + if (PhysicalAddressBits > 39) { + Pml4Entries =3D (UINT32) LShiftU64 (1, PhysicalAddressBits - 39); + PhysicalAddressBits =3D 39; + } + + PdpEntries =3D 1; + ASSERT (PhysicalAddressBits > 30); + PdpEntries =3D (UINT32) LShiftU64 (1, PhysicalAddressBits - 30); + + // + // Pre-allocate big pages to avoid later allocations. + // + if (!Page1GSupport) { + TotalPages =3D ((PdpEntries + 1) * Pml4Entries + 1) * Pml5Entries + 1; } else { - Pml4Entries =3D 1 << (mPhysMemAddressWidth - 39); - ASSERT (Pml4Entries <=3D 0x200); - PdpEntries =3D 512; + TotalPages =3D (Pml4Entries + 1) * Pml5Entries + 1; } =20 - TotalPages =3D Page1GSupport ? Pml4Entries + 1 : - (PdpEntries + 1) * Pml4Entries + 1; - ASSERT (TotalPages <=3D 0x40201); - // // Add 64 MB for miscellaneous allocations. Note that for // mPhysMemAddressWidth values close to 36, the cap will actually be @@ -815,7 +842,11 @@ InitializeRamRegions ( VOID ) { - QemuInitializeRam (); + if (PlatformPeiIsTdxGuest ()) { + TdxPublishRamRegions (); + } else { + QemuInitializeRam (); + } =20 if (mS3Supported && mBootMode !=3D BOOT_ON_S3_RESUME) { // diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c index d3a20122a2ea..2c099376dad0 100644 --- a/OvmfPkg/PlatformPei/Platform.c +++ b/OvmfPkg/PlatformPei/Platform.c @@ -742,6 +742,7 @@ InitializePlatform ( =20 InstallClearCacheCallback (); AmdSevInitialize (); + IntelTdxInitialize (); MiscInitialization (); InstallFeatureControlCallback (); =20 diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h index 8b1d270c2b0b..bf12b52d153e 100644 --- a/OvmfPkg/PlatformPei/Platform.h +++ b/OvmfPkg/PlatformPei/Platform.h @@ -10,6 +10,7 @@ #define _PLATFORM_PEI_H_INCLUDED_ =20 #include +#include =20 VOID AddIoMemoryBaseSizeHob ( @@ -102,6 +103,33 @@ AmdSevInitialize ( VOID ); =20 +VOID +TdxPublishRamRegions ( + VOID + ); + +VOID +AsmGetRelocationMap ( + OUT MP_RELOCATION_MAP *AddressMap + ); + + +VOID +IntelTdxInitialize ( + VOID + ); + +/** + Check if it is Tdx guest + + @retval TRUE It is Tdx guest + @retval FALSE It is not Tdx guest +**/ +BOOLEAN +PlatformPeiIsTdxGuest ( + VOID + ); + extern EFI_BOOT_MODE mBootMode; =20 extern BOOLEAN mS3Supported; diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/Plat= formPei.inf index 67eb7aa7166b..eec1bb3d9c38 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -34,6 +34,13 @@ Platform.c Platform.h =20 +[Sources.IA32, Sources.EBC] + IntelTdxNull.c + +[Sources.X64] + IntelTdx.c + X64/ApRunLoop.nasm + [Packages] EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec @@ -44,6 +51,7 @@ =20 [Guids] gEfiMemoryTypeInformationGuid + gUefiOvmfPkgTdxPlatformGuid =20 [LibraryClasses] BaseLib @@ -62,6 +70,9 @@ MtrrLib MemEncryptSevLib PcdLib + TdxMailboxLib + TdxLib + MemoryAllocationLib =20 [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase @@ -106,6 +117,8 @@ gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled + gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed + gUefiCpuPkgTokenSpaceGuid.PcdConfidentialComputingCategory =20 [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/OvmfPkg/PlatformPei/X64/ApRunLoop.nasm b/OvmfPkg/PlatformPei/X= 64/ApRunLoop.nasm new file mode 100644 index 000000000000..adf4f03c3a9e --- /dev/null +++ b/OvmfPkg/PlatformPei/X64/ApRunLoop.nasm @@ -0,0 +1,83 @@ +;-------------------------------------------------------------------------= ----- ; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ApRunLoop.nasm +; +; Abstract: +; +; This is the assembly code for run loop for APs in the guest TD +; +;-------------------------------------------------------------------------= ------ + +%include "TdxCommondefs.inc" + +DEFAULT REL + +SECTION .text + +BITS 64 + +%macro tdcall 0 + db 0x66, 0x0f, 0x01, 0xcc +%endmacro + +; +; Relocated Ap Mailbox loop +; +; @param[in] RBX: Relocated mailbox address +; @param[in] RBP: vCpuId +; +; @return None This routine does not return +; +global ASM_PFX(AsmRelocateApMailBoxLoop) +ASM_PFX(AsmRelocateApMailBoxLoop): +AsmRelocateApMailBoxLoopStart: + + ; + ; TdCall[TDINFO] to get the vCpuId + ; + ;mov rax, 1 + ;tdcall + ; + ; R8 [31:0] NUM_VCPUS + ; [63:32] MAX_VCPUS + ; R9 [31:0] VCPU_INDEX + ; + + mov r8, rbp +MailBoxLoop: + ; Spin until command set + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandNo= op + je MailBoxLoop + ; Determine if this is a broadcast or directly for my apic-id, if not,= ignore + cmp dword [rbx + ApicidOffset], MailboxApicidBroadcast + je MailBoxProcessCommand + cmp dword [rbx + ApicidOffset], r8d + jne MailBoxLoop +MailBoxProcessCommand: + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandWa= keup + je MailBoxWakeUp + cmp dword [rbx + CommandOffset], MpProtectedModeWakeupCommandSl= eep + je MailBoxSleep + ; Don't support this command, so ignore + jmp MailBoxLoop +MailBoxWakeUp: + mov rax, [rbx + WakeupVectorOffset] + jmp rax +MailBoxSleep: + jmp $ +BITS 64 +AsmRelocateApMailBoxLoopEnd: + +;-------------------------------------------------------------------------= ------------ +; AsmGetRelocationMap (&RelocationMap); +;-------------------------------------------------------------------------= ------------ +global ASM_PFX(AsmGetRelocationMap) +ASM_PFX(AsmGetRelocationMap): + lea rax, [ASM_PFX(AsmRelocateApMailBoxLoopStart)] + mov qword [rcx], rax + mov qword [rcx + 8h], AsmRelocateApMailBoxLoopEnd - AsmRelocat= eApMailBoxLoopStart + ret --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81494): https://edk2.groups.io/g/devel/message/81494 Mute This Topic: https://groups.io/mt/86085763/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81493+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81493+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405269; cv=none; d=zohomail.com; s=zohoarc; b=EewXNW10e6IiG5OHOxNEDXbCNr2y7xLNTywkt7nxJLdMvfLCL7/YFscygFZ5MqUs3DPKs2NXI3UhMX7hW4mCJOtbZqGAIAxcTy2cmMretqhRSRm7unHR5x31xSBf+i4Zqu2j0GKZPw0r6ao+moYWmff+Aj/03Tw/5hidblxLEQU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405269; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=Rj5lW6vb5mCbLNjAetJRcj7vtHz8kYKbgsN39y9JBvE=; b=mUJgaFQsdPt1lwCBgjnnsFGf6ODFy3+bsyYFhN1ZAwp/D1+qI3RxWZ6yOsC3C/6zGICaJWGLImWAYA8or/oIsv6LHbcOOy60PRjFd+zhqAeC9tWJBgvH2Z3qoOXTsSLfkx9LGWBt8y8aoUOBfBzsvPk/ustRS7P5kMOAn12c3+s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81493+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405269041853.4039852971937; Mon, 4 Oct 2021 20:41:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id orcgYY1788612x61eE6WU27L; Mon, 04 Oct 2021 20:41:08 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958240" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958240" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:55 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828775" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:54 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Brijesh Singh Subject: [edk2-devel] [PATCH V2 22/28] UefiCpuPkg: Define ConfidentialComputingGuestAttr (Temp) Date: Tue, 5 Oct 2021 11:39:33 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: WkHliBBMRcIToTos6zgqFd4Yx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405268; bh=nz/1PnVv1+DDcYDF+k/5CWzgqi/L2rkndYZeeRAmcr0=; h=Cc:Date:From:Reply-To:Subject:To; b=h4R+NozafF7Sp0Lqy06/cqSGWXaDWFf61GFz3hZxjwgN+NUWkQaFvUb0gJ63QkFXqO9 VO6CMfh4ekIBqul3Mz0VAY13DGai0V7wwIjutaNRSUCSQFFBIMKJDrtUncrQaRphdYY25 HnAlS6zP6H3V3UBxrh/Jg8i7ugjVHzOEnpw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405270865100029 Content-Type: text/plain; charset="utf-8" Add a new ConfidentialComputingGuestAttr PCD that can be used to query the memory encryption attribute. (This is AMD's patch) Signed-off-by: Brijesh Singh --- OvmfPkg/PlatformPei/IntelTdx.c | 8 ++---- OvmfPkg/PlatformPei/PlatformPei.inf | 2 +- .../Include/ConfidentialComputingGuestAttr.h | 25 +++++++++++++++++++ UefiCpuPkg/UefiCpuPkg.dec | 4 +++ 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 UefiCpuPkg/Include/ConfidentialComputingGuestAttr.h diff --git a/OvmfPkg/PlatformPei/IntelTdx.c b/OvmfPkg/PlatformPei/IntelTdx.c index 684907179c10..5256740376b8 100644 --- a/OvmfPkg/PlatformPei/IntelTdx.c +++ b/OvmfPkg/PlatformPei/IntelTdx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "Platform.h" =20 /** @@ -263,17 +264,12 @@ IntelTdxInitialize ( { EFI_HOB_PLATFORM_INFO PlatformInfoHob; RETURN_STATUS PcdStatus; - UINT32 ConfidentialComputingCategory; - CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *CcWorkAreaHeader; =20 if (!PlatformPeiIsTdxGuest ()) { return; } =20 - CcWorkAreaHeader =3D (CONFIDENTIAL_COMPUTING_WORK_AREA_HEADER *) FixedPc= dGet32 (PcdOvmfWorkAreaBase); - ConfidentialComputingCategory =3D *((UINT32 *)CcWorkAreaHeader); - - PcdStatus =3D PcdSet32S (PcdConfidentialComputingCategory, ConfidentialC= omputingCategory); + PcdStatus =3D PcdSet64S (PcdConfidentialComputingGuestAttr, CCAttrIntelT= dx); ASSERT_RETURN_ERROR (PcdStatus); =20 PcdStatus =3D PcdSetBoolS (PcdIa32EferChangeAllowed, FALSE); diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/Plat= formPei.inf index eec1bb3d9c38..91a35f77a81f 100644 --- a/OvmfPkg/PlatformPei/PlatformPei.inf +++ b/OvmfPkg/PlatformPei/PlatformPei.inf @@ -118,7 +118,7 @@ gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled gEfiMdeModulePkgTokenSpaceGuid.PcdIa32EferChangeAllowed - gUefiCpuPkgTokenSpaceGuid.PcdConfidentialComputingCategory + gUefiCpuPkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr =20 [FixedPcd] gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress diff --git a/UefiCpuPkg/Include/ConfidentialComputingGuestAttr.h b/UefiCpuP= kg/Include/ConfidentialComputingGuestAttr.h new file mode 100644 index 000000000000..495b0df0ac33 --- /dev/null +++ b/UefiCpuPkg/Include/ConfidentialComputingGuestAttr.h @@ -0,0 +1,25 @@ +/** @file +Definitions for Confidential Computing Attribute + +Copyright (c) 2021 AMD Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CONFIDENTIAL_COMPUTING_GUEST_ATTR_H_ +#define CONFIDENTIAL_COMPUTING_GUEST_ATTR_H_ + +typedef enum { + /* The guest is running with memory encryption disabled. */ + CCAttrNotEncrypted =3D 0, + + /* The guest is running with AMD SEV memory encryption enabled. */ + CCAttrAmdSev =3D 0x100, + CCAttrAmdSevEs =3D 0x101, + CCAttrAmdSevSnp =3D 0x102, + + /* The guest is running with Intel TDX memory encryption enabled. */ + CCAttrIntelTdx =3D 0x200, +} CONFIDENTIAL_COMPUTING_GUEST_ATTR; + +#endif diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec index 439bfc86a112..f270bbb990f6 100644 --- a/UefiCpuPkg/UefiCpuPkg.dec +++ b/UefiCpuPkg/UefiCpuPkg.dec @@ -399,5 +399,9 @@ # @Prompt SEV-ES Status gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|FALSE|BOOLEAN|0x60000016 =20 + ## This dynamic PCD indicates the memory encryption attribute of the gue= st. + # @Prompt Memory encryption attribute + gUefiCpuPkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr|0|UINT64|0x6= 0000017 + [UserExtensions.TianoCore."ExtraFiles"] UefiCpuPkgExtra.uni --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81493): https://edk2.groups.io/g/devel/message/81493 Mute This Topic: https://groups.io/mt/86085762/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81495+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81495+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405270; cv=none; d=zohomail.com; s=zohoarc; b=FIOw4KW3eZTlAX73ujm5PU7jNXcQrGjpWv9NR0rmFDu3+Z++2oITHzzIeatvJnd1TW6vLJA5ap9kpetHtKskH7SN4zntwdGRMz68icVPXErG3Fxohmigwuw65zmqAZr/MjcNMcRqG6+mCD0/r5uBNHFeYfjcQ+0TL0pCnQZZ3yc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405270; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=cyfcjzSKX9iBlvxsj9CZ/SZjUnWiHxxJz4hAkiZN088=; b=TPSjN5ZelCAjq+KB5atHQBcEVr4Ye/RuCK1uSTUPzHb1y9W8fyuaJwHDFaimUuRRqQkq/RkoexlpHYHAfhHRWVx90h4aFyj90YXl2JdnMOFmfkWjyeXWxykYwuCqaoS1iwVPCC9RTmaFI2Q11IwpMmPmTj9kdsGR4Rv70QgdQfA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81495+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405270227442.564528753437; Mon, 4 Oct 2021 20:41:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id pbDOYY1788612xP3yBvrvdam; Mon, 04 Oct 2021 20:41:09 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web11.20673.1633405264221469310 for ; Mon, 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958244" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958244" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:58 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828786" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:56 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 23/28] OvmfPkg: Update AcpiPlatformDxe to alter MADT table Date: Tue, 5 Oct 2021 11:39:34 +0800 Message-Id: <3c7bf0653e02c333fb25009df61c9ef40b2c7625.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: RD5aUMGChiQ7zckhrjj5tQt9x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405269; bh=yWagvEtjty0ypDH5D8kIHFMvQWuMA9gS5Jh0lQSfnYs=; h=Cc:Date:From:Reply-To:Subject:To; b=hPkpwTcGe0x9MGQjagBcCDNdy2YY3lHsOo/0rUfIa/Ruu7ECTQooAUfuVgejIANzZFz ITVtdoF41/ZFl0pBwiDzDytKYSxHlRzShRTyu9OM7qDoQHi06TnfGBMMy8z0L70D/zCBO HW9u60EnGh9qdHsdnlGJfsPMfqrMtyLe3wI= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405271017100037 Content-Type: text/plain; charset="utf-8" RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In TDX the guest firmware is designed to publish a multiprocessor-wakeup structure to let the guest-bootstrap processor wake up guest-application processors with a mailbox. The mailbox is memory that the guest firmware can reserve so each guest virtual processor can have the guest OS send a message to them. The address of the mailbox is recorded in the MADT table. See [ACPI]. To maintain the simplicity of the AcpiPlatformDxe, the MADT ACPI table will be altered in another driver (TdxDxe) by installing a protocol to notify that the ACPI table provided by Qemu is ready. Then in TdxDxe a notification functioin will be called to alter the MADT table to recorded the mailbox address. The protocol is gQemuAcpiTableNotifyProtocolGuid. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 12 +++++++- .../QemuFwCfgAcpiPlatformDxe.inf | 1 + .../Include/Protocol/QemuAcpiTableNotify.h | 29 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/Include/Protocol/QemuAcpiTableNotify.h diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatform= Dxe/QemuFwCfgAcpi.c index df800b149275..e8a9aff089e8 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c @@ -19,7 +19,10 @@ #include // QemuFwCfgS3Enabled() #include // gBS =20 +#include #include "AcpiPlatform.h" +EFI_HANDLE mQemuAcpiHandle =3D NULL; +QEMU_ACPI_TABLE_NOTIFY_PROTOCOL mAcpiNotifyProtocol; =20 // // The user structure for the ordered collection that will track the fw_cfg @@ -1129,7 +1132,14 @@ UninstallAcpiTables: AcpiProtocol->UninstallAcpiTable (AcpiProtocol, InstalledKey[Install= ed]); } } else { - DEBUG ((DEBUG_INFO, "%a: installed %d tables\n", __FUNCTION__, Install= ed)); + // + // Install a protocol to notify that the ACPI table provided by Qemu= is + // ready. + // + gBS->InstallProtocolInterface (&mQemuAcpiHandle, + &gQemuAcpiTableNotifyProtocolGuid, + EFI_NATIVE_INTERFACE, + &mAcpiNotifyProtocol); } =20 for (SeenPointerEntry =3D OrderedCollectionMin (SeenPointers); diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf b/OvmfPkg= /AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf index dac25d1505be..6ffce2db5f99 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpiPlatformDxe.inf @@ -48,6 +48,7 @@ [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED + gQemuAcpiTableNotifyProtocolGuid # PROTOCOL PRODUCES =20 [Guids] gRootBridgesConnectedEventGroupGuid diff --git a/OvmfPkg/Include/Protocol/QemuAcpiTableNotify.h b/OvmfPkg/Inclu= de/Protocol/QemuAcpiTableNotify.h new file mode 100644 index 000000000000..8549ea9ec374 --- /dev/null +++ b/OvmfPkg/Include/Protocol/QemuAcpiTableNotify.h @@ -0,0 +1,29 @@ +/** @file + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef QEMU_ACPI_TABLE_NOTIFY_H_ +#define QEMU_ACPI_TABLE_NOTIFY_H_ + + +#define QEMU_ACPI_TABLE_NOTIFY_GUID \ + { 0x928939b2, 0x4235, 0x462f, { 0x95, 0x80, 0xf6, 0xa2, 0xb2, 0xc2, 0x1a= , 0x4f } }; + + +/// +/// Forward declaration +/// +typedef struct _QEMU_ACPI_TABLE_NOTIFY_PROTOCOL QEMU_ACPI_TABLE_NOTIFY_PRO= TOCOL; + +/// +/// Protocol structure +/// +struct _QEMU_ACPI_TABLE_NOTIFY_PROTOCOL { + UINT8 Notify; +}; + +extern EFI_GUID gQemuAcpiTableNotifyProtocolGuid; + +#endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81495): https://edk2.groups.io/g/devel/message/81495 Mute This Topic: https://groups.io/mt/86085764/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81496+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81496+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405269; cv=none; d=zohomail.com; s=zohoarc; b=MRZZ33SH3eFIxtgxq8v5bv8f1VD1ErcFpsCD4VJrdq1028A525r5bQ7GWGrXMmPBmHt88rJBG691WJTbwlqVftgLR+299HfzxwNi9uZtgDRJBYaF57Y6QB+g7vwDubLD+1Q6fXT9/sPSF0WwapkPur30VXfLvXFMigoV5LgQWWw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405269; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=hxpt3BcSaJLpzIGKq8qO2pRCn4WTPI2YOXmZvUfwA2Y=; b=bhmEy6KNnbqn2NhqCYOJb8Uh9sZCOag/uolvgpRFr0/uASxyyah5/Jx6GsUywu4LzGC968JhvCdnPy/SYqeQRiTfGlxksGGtkI9J5WOJrc+8gesEauAHhf5uHys17cXjev27s3QfHnj/pnjgDWBAZMZGj6M0vcz4ilMzlYriye4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81496+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405269431847.6984560427542; Mon, 4 Oct 2021 20:41:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id i8mpYY1788612xhWGZ2VO531; Mon, 04 Oct 2021 20:41:09 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.20836.1633405265395581286 for ; Mon, 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958250" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958250" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:01 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828800" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:40:58 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 24/28] OvmfPkg: Add TdxDxe driver Date: Tue, 5 Oct 2021 11:39:35 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: FpSISYVMd2nY5cELP8Krg4E3x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405269; bh=Rv2V6kcRjuockV90Oh1VxhSdGf2LwoNHfb1TxIh3m/M=; h=Cc:Date:From:Reply-To:Subject:To; b=aeNjN2MkYA+RTI3f1MeQcs/sVpA4vDDKNOiD7ghNLIYrkNkha29NwooyTN4argT2wsh +V3JCUx51dVmVSIvNJwxvOVp1q8c9Y6IN8mdqiVMsD4WYv7Y3XctOCEUEI7QrOHUEUSej nHaT9svEddmw60zQPS03uz0FvRhSWdA6rNU= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405270948100032 Content-Type: text/plain; charset="utf-8" RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 TdxDxe driver is dispatched early in DXE, due to being list in APRIORI. This module is responsible for below features: - Sets max logical cpus based on TDINFO - Sets PCI PCDs based on resource hobs Besides above features, TdxDxe driver will update the ACPI MADT Mutiprocessor Wakeup Table. In TDX the guest firmware is designed to publish a multiprocessor-wakeup structure to let the guest-bootstrap processor wake up guest-application processors with a mailbox. The mailbox is memory that the guest firmware can reserve so each guest virtual processor can have the guest OS send a message to them. The address of the mailbox is recorded in the MADT table. See [ACPI]. TdxDxe registers for protocol notification (gQemuAcpiTableNotifyProtocolGuid) to call the AlterAcpiTable(), in which MADT table is altered by the above Mailbox address. The protocol will be installed in AcpiPlatformDxe when the MADT table provided by Qemu is ready. This is to maintain the simplicity of the AcpiPlatformDxe. AlterAcpiTable is the registered function which traverses the ACPI table list to find the original MADT from Qemu. After the new MADT is configured and installed, the original one will be uninstalled. [ACPI] https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model /ACPI_Software_Programming_Model.html#multiprocessor-wakeup-structure Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/IndustryStandard/AcpiTdx.h | 23 +++ OvmfPkg/Include/IndustryStandard/IntelTdx.h | 5 +- OvmfPkg/OvmfPkg.dec | 4 + OvmfPkg/OvmfPkgX64.dsc | 2 + OvmfPkg/OvmfPkgX64.fdf | 3 + OvmfPkg/TdxDxe/TdxAcpiTable.c | 207 ++++++++++++++++++++ OvmfPkg/TdxDxe/TdxAcpiTable.h | 38 ++++ OvmfPkg/TdxDxe/TdxDxe.c | 207 ++++++++++++++++++++ OvmfPkg/TdxDxe/TdxDxe.inf | 62 ++++++ 9 files changed, 548 insertions(+), 3 deletions(-) create mode 100644 OvmfPkg/Include/IndustryStandard/AcpiTdx.h create mode 100644 OvmfPkg/TdxDxe/TdxAcpiTable.c create mode 100644 OvmfPkg/TdxDxe/TdxAcpiTable.h create mode 100644 OvmfPkg/TdxDxe/TdxDxe.c create mode 100644 OvmfPkg/TdxDxe/TdxDxe.inf diff --git a/OvmfPkg/Include/IndustryStandard/AcpiTdx.h b/OvmfPkg/Include/I= ndustryStandard/AcpiTdx.h new file mode 100644 index 000000000000..9e2753bbe52a --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/AcpiTdx.h @@ -0,0 +1,23 @@ +/** @file + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef ACPI_TDX_H_ +#define ACPI_TDX_H_ + +#define ACPI_MADT_MPWK_STRUCT_TYPE 0x10 + +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 MailBoxVersion; + UINT32 Reserved2; + UINT64 MailBoxAddress; +} ACPI_MADT_MPWK_STRUCT; + +#pragma pack() +#endif diff --git a/OvmfPkg/Include/IndustryStandard/IntelTdx.h b/OvmfPkg/Include/= IndustryStandard/IntelTdx.h index 2370f18289a1..bb02970394d7 100644 --- a/OvmfPkg/Include/IndustryStandard/IntelTdx.h +++ b/OvmfPkg/Include/IndustryStandard/IntelTdx.h @@ -6,8 +6,8 @@ =20 **/ =20 -#ifndef _OVMF_INTEL_TDX__H_ -#define _OVMF_INTEL_TDX__H_ +#ifndef OVMF_INTEL_TDX_H_ +#define OVMF_INTEL_TDX_H_ =20 #include #include @@ -52,7 +52,6 @@ typedef enum { UINT8 Pad3[0xf8]; } MP_WAKEUP_MAILBOX; =20 - // // AP relocation code information including code address and size, // this structure will be shared be C code and assembly code. diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index b489c69a736e..cc5087da6aa2 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -153,6 +153,7 @@ gEfiLegacyInterruptProtocolGuid =3D {0x31ce593d, 0x108a, 0x485d, {= 0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe}} gEfiVgaMiniPortProtocolGuid =3D {0xc7735a2f, 0x88f5, 0x4882, {= 0xae, 0x63, 0xfa, 0xac, 0x8c, 0x8b, 0x86, 0xb3}} gOvmfLoadedX86LinuxKernelProtocolGuid =3D {0xa3edc05d, 0xb618, 0x4ff6, {= 0x95, 0x52, 0x76, 0xd7, 0x88, 0x63, 0x43, 0xc8}} + gQemuAcpiTableNotifyProtocolGuid =3D {0x928939b2, 0x4235, 0x462f, {= 0x95, 0x80, 0xf6, 0xa2, 0xb2, 0xc2, 0x1a, 0x4f}} =20 [PcdsFixedAtBuild] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 @@ -403,6 +404,9 @@ # instance in PiSmmCpuDxeSmm, and CpuHotplugSmm. gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress|0|UINT64|0x46 =20 + ## TDX relocated Mailbox base address + gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase|0|UINT64|0x60 + [PcdsFeatureFlag] gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0= x1c gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN= |0x1d diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 12ebde74433d..2c4a6613b1ea 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -977,6 +977,8 @@ OvmfPkg/AmdSevDxe/AmdSevDxe.inf OvmfPkg/IoMmuDxe/IoMmuDxe.inf =20 + OvmfPkg/TdxDxe/TdxDxe.inf + !if $(SMM_REQUIRE) =3D=3D TRUE OvmfPkg/SmmAccess/SmmAccess2Dxe.inf OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index b6cc3cabdd69..bbd9303ab14f 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -214,6 +214,7 @@ READ_LOCK_STATUS =3D TRUE APRIORI DXE { INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF OvmfPkg/TdxDxe/TdxDxe.inf INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf !if $(SMM_REQUIRE) =3D=3D FALSE INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf @@ -319,6 +320,8 @@ INF ShellPkg/Application/Shell/Shell.inf =20 INF MdeModulePkg/Logo/LogoDxe.inf =20 +INF OvmfPkg/TdxDxe/TdxDxe.inf + # # Network modules # diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.c b/OvmfPkg/TdxDxe/TdxAcpiTable.c new file mode 100644 index 000000000000..249dbbb9128f --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.c @@ -0,0 +1,207 @@ +/** @file + OVMF ACPI QEMU support + + Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.
+ + Copyright (C) 2012-2014, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC +EFI_STATUS +EFIAPI +QemuInstallAcpiMadtTable ( + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, + IN VOID *AcpiTableBuffer, + IN UINTN AcpiTableBufferSize, + OUT UINTN *TableKey + ) +{ + UINTN CpuCount; + UINTN NewBufferSize; + EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt; + EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic; + EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic; + EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso; + EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmi; + VOID *Ptr; + UINTN Loop; + EFI_STATUS Status; + ACPI_MADT_MPWK_STRUCT *MadtMpWk; + + ASSERT (AcpiTableBufferSize >=3D sizeof (EFI_ACPI_DESCRIPTION_HEADER)); + + CpuCount =3D TdVCpuNum(); + + ASSERT (CpuCount >=3D 1); + +#define NUM_8259_IRQS 16 + NewBufferSize =3D 1 * sizeof (*Madt) + + CpuCount * sizeof (*LocalApic) + + 1 * sizeof (*IoApic) + + NUM_8259_IRQS * sizeof (*Iso) + + 1 * sizeof (*LocalApicNmi); + + NewBufferSize +=3D sizeof(ACPI_MADT_MPWK_STRUCT); + + Madt =3D AllocatePool (NewBufferSize); + if (Madt =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_= HEADER)); + Madt->Header.Length =3D (UINT32) NewBufferSize; + Madt->LocalApicAddress =3D PcdGet32 (PcdCpuLocalApicBaseAddress); + Madt->Flags =3D EFI_ACPI_1_0_PCAT_COMPAT; + Ptr =3D Madt + 1; + + LocalApic =3D Ptr; + for (Loop =3D 0; Loop < CpuCount; ++Loop) { + LocalApic->Type =3D EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC; + LocalApic->Length =3D sizeof (*LocalApic); + LocalApic->AcpiProcessorId =3D (UINT8) Loop; + LocalApic->ApicId =3D (UINT8) Loop; + LocalApic->Flags =3D 1; // enabled + ++LocalApic; + } + Ptr =3D LocalApic; + + IoApic =3D Ptr; + IoApic->Type =3D EFI_ACPI_1_0_IO_APIC; + IoApic->Length =3D sizeof (*IoApic); + IoApic->IoApicId =3D (UINT8) CpuCount; + IoApic->Reserved =3D EFI_ACPI_RESERVED_BYTE; + IoApic->IoApicAddress =3D 0xFEC00000; + IoApic->SystemVectorBase =3D 0x00000000; + Ptr =3D IoApic + 1; + + // + // IRQ0 (8254 Timer) =3D> IRQ2 (PIC) Interrupt Source Override Structure + // + Iso =3D Ptr; + Iso->Type =3D EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERR= IDE; + Iso->Length =3D sizeof (*Iso); + Iso->Bus =3D 0x00; // ISA + Iso->Source =3D 0x00; // IRQ0 + Iso->GlobalSystemInterruptVector =3D 0x00000002; + Iso->Flags =3D 0x0005; // Edge-triggered, Active = High + ++Iso; + + for (Loop =3D 1; Loop < NUM_8259_IRQS; ++Loop) { + Iso->Type =3D EFI_ACPI_1_0_INTERRUPT_SOURCE_OVE= RRIDE; + Iso->Length =3D sizeof (*Iso); + Iso->Bus =3D 0x00; // ISA + Iso->Source =3D (UINT8) Loop; + Iso->GlobalSystemInterruptVector =3D (UINT32) Loop; + Iso->Flags =3D 0x0005; // Edge-triggered, Active= High + ++Iso; + } + Ptr =3D Iso; + + LocalApicNmi =3D Ptr; + LocalApicNmi->Type =3D EFI_ACPI_1_0_LOCAL_APIC_NMI; + LocalApicNmi->Length =3D sizeof (*LocalApicNmi); + LocalApicNmi->AcpiProcessorId =3D 0xFF; // applies to all processors + // + // polarity and trigger mode of the APIC I/O input signals conform to the + // specifications of the bus + // + LocalApicNmi->Flags =3D 0x0000; + // + // Local APIC interrupt input LINTn to which NMI is connected. + // + LocalApicNmi->LocalApicInti =3D 0x01; + Ptr =3D LocalApicNmi + 1; + + MadtMpWk =3D Ptr; + MadtMpWk->Type =3D ACPI_MADT_MPWK_STRUCT_TYPE; + MadtMpWk->Length =3D sizeof(ACPI_MADT_MPWK_STRUCT); + MadtMpWk->MailBoxVersion =3D 1; + MadtMpWk->Reserved2 =3D 0; + MadtMpWk->MailBoxAddress =3D PcdGet64 (PcdTdRelocatedMailboxBase); + Ptr =3D MadtMpWk + 1; + + ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) =3D=3D NewBufferSize); + Status =3D AcpiProtocol->InstallAcpiTable (AcpiProtocol, Madt, NewBuffer= Size, TableKey); + + FreePool (Madt); + + return Status; +} + +/** + Alter the MADT when ACPI Table from QEMU is available. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +AlterAcpiTable ( + IN EFI_EVENT Event, + IN VOID* Context + ) +{ + EFI_ACPI_SDT_PROTOCOL *AcpiSdtTable; + EFI_ACPI_TABLE_PROTOCOL *AcpiTable; + EFI_STATUS Status; + UINTN Index; + EFI_ACPI_SDT_HEADER *Table; + EFI_ACPI_TABLE_VERSION Version; + UINTN OriginalTableKey; + UINTN UpdatedTableKey; + + Index =3D 0; + + Status =3D gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (void **= ) &AcpiSdtTable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate ACPI SDT protocol.\n")); + return; + } + + do { + Status =3D AcpiSdtTable->GetAcpiTable (Index, &Table, &Version, &Origi= nalTableKey); + + if (!EFI_ERROR (Status) && Table->Signature =3D=3D EFI_ACPI_1_0_APIC_S= IGNATURE) { + Status =3D gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (v= oid **) &AcpiTable); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate ACPI Table protocol.\n")); + return; + } + + // + // The altered MADT should be rebuilt and installed before uninstall= the + // original one, because unintall table will free the memory which w= ill be + // copied in QemuInstallAcpiMadtTable(). + // + QemuInstallAcpiMadtTable (AcpiTable, Table, Table->Length, &UpdatedT= ableKey); + Status =3D AcpiTable->UninstallAcpiTable (AcpiTable, OriginalTableKe= y); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Uninstall MADT table error.\n")); + } + break; + } + Index ++; + } while (!EFI_ERROR (Status)); +} diff --git a/OvmfPkg/TdxDxe/TdxAcpiTable.h b/OvmfPkg/TdxDxe/TdxAcpiTable.h new file mode 100644 index 000000000000..36aaab9d1f41 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxAcpiTable.h @@ -0,0 +1,38 @@ +/** @file + Sample ACPI Platform Driver + + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _TDX_QEMU_ACPI_H_INCLUDED_ +#define _TDX_QEMU_ACPI_H_INCLUDED_ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +/** + Alter the MADT when ACPI Table from QEMU is available. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +AlterAcpiTable ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +#endif diff --git a/OvmfPkg/TdxDxe/TdxDxe.c b/OvmfPkg/TdxDxe/TdxDxe.c new file mode 100644 index 000000000000..eecad8f6e050 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxDxe.c @@ -0,0 +1,207 @@ +/** @file + + TDX Dxe driver. This driver is dispatched early in DXE, due to being list + in APRIORI. + + This module is responsible for: + - Sets max logical cpus based on TDINFO + - Sets PCI PCDs based on resource hobs + - Alter MATD table to record address of Mailbox + + Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Location of resource hob matching type and starting address + + @param[in] Type The type of resource hob to locate. + + @param[in] Start The resource hob must at least begin at add= ress. + + @retval pointer to resource Return pointer to a resource hob that match= es or NULL. +**/ +STATIC +EFI_HOB_RESOURCE_DESCRIPTOR * +GetResourceDescriptor( + EFI_RESOURCE_TYPE Type, + EFI_PHYSICAL_ADDRESS Start, + EFI_PHYSICAL_ADDRESS End + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor =3D NULL; + + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + while (Hob.Raw !=3D NULL) { + + DEBUG ((DEBUG_INFO, "%a:%d: resource type 0x%x %llx %llx\n", + __func__, __LINE__, + Hob.ResourceDescriptor->ResourceType, + Hob.ResourceDescriptor->PhysicalStart, + Hob.ResourceDescriptor->ResourceLength)); + + if ((Hob.ResourceDescriptor->ResourceType =3D=3D Type) && + (Hob.ResourceDescriptor->PhysicalStart >=3D Start) && + ((Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->Re= sourceLength) < End)) { + ResourceDescriptor =3D Hob.ResourceDescriptor; + break; + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + return ResourceDescriptor; +} + +/** + Location of resource hob matching type and highest address below end + + @param[in] Type The type of resource hob to locate. + + @param[in] End The resource hob return is the closest to t= he End address + + @retval pointer to resource Return pointer to a resource hob that match= es or NULL. +**/ +STATIC +EFI_HOB_RESOURCE_DESCRIPTOR * +GetHighestResourceDescriptor( + EFI_RESOURCE_TYPE Type, + EFI_PHYSICAL_ADDRESS End + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor =3D NULL; + + Hob.Raw =3D GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); + while (Hob.Raw !=3D NULL) { + if ((Hob.ResourceDescriptor->ResourceType =3D=3D Type) && + (Hob.ResourceDescriptor->PhysicalStart < End)) { + if (!ResourceDescriptor || + (ResourceDescriptor->PhysicalStart < Hob.ResourceDescriptor->Physi= calStart)) { + ResourceDescriptor =3D Hob.ResourceDescriptor; + } + } + Hob.Raw =3D GET_NEXT_HOB (Hob); + Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw); + } + + return ResourceDescriptor; +} + +EFI_STATUS +EFIAPI +TdxDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + RETURN_STATUS PcdStatus; + EFI_HOB_RESOURCE_DESCRIPTOR *Res =3D NULL; + EFI_HOB_RESOURCE_DESCRIPTOR *MemRes =3D NULL; + EFI_HOB_PLATFORM_INFO *PlatformInfo =3D NULL; + EFI_HOB_GUID_TYPE *GuidHob; + UINT32 CpuMaxLogicalProcessorNumber; + TD_RETURN_DATA TdReturnData; + EFI_EVENT QemuAcpiTableEvent; + void *Registration; + + GuidHob =3D GetFirstGuidHob (&gUefiOvmfPkgTdxPlatformGuid); + + if(GuidHob =3D=3D NULL) { + return EFI_UNSUPPORTED; + } + + PlatformInfo =3D (EFI_HOB_PLATFORM_INFO *) GET_GUID_HOB_DATA (GuidHob); + + // + // Call TDINFO to get actual number of cpus in domain + // + Status =3D TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); + ASSERT(Status =3D=3D EFI_SUCCESS); + + CpuMaxLogicalProcessorNumber =3D PcdGet32 (PcdCpuMaxLogicalProcessorNumb= er); + + // + // Adjust PcdCpuMaxLogicalProcessorNumber, if needed. If firmware is con= figured for + // more than number of reported cpus, update. + // + if (CpuMaxLogicalProcessorNumber > TdReturnData.TdInfo.NumVcpus) { + PcdStatus =3D PcdSet32S (PcdCpuMaxLogicalProcessorNumber, TdReturnData= .TdInfo.NumVcpus); + ASSERT_RETURN_ERROR(PcdStatus); + } + + // + // Register for protocol notifications to call the AlterAcpiTable(), + // the protocol will be installed in AcpiPlatformDxe when the ACPI + // table provided by Qemu is ready. + // + Status =3D gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + AlterAcpiTable, + NULL, + &QemuAcpiTableEvent + ); + + Status =3D gBS->RegisterProtocolNotify ( + &gQemuAcpiTableNotifyProtocolGuid, + QemuAcpiTableEvent, + &Registration + ); + +#define INIT_PCDSET(NAME, RES) do { \ + PcdStatus =3D PcdSet64S (NAME##Base, (RES)->PhysicalStart); \ + ASSERT_RETURN_ERROR (PcdStatus); \ + PcdStatus =3D PcdSet64S (NAME##Size, (RES)->ResourceLength); \ + ASSERT_RETURN_ERROR (PcdStatus); \ +} while(0) + + if (PlatformInfo) { + PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfo->HostBridgePciDevId= ); + + if ((Res =3D GetResourceDescriptor(EFI_RESOURCE_MEMORY_MAPPED_IO, (EFI= _PHYSICAL_ADDRESS)0x100000000, (EFI_PHYSICAL_ADDRESS)-1)) !=3D NULL) { + INIT_PCDSET(PcdPciMmio64, Res); + } + + if ((Res =3D GetResourceDescriptor(EFI_RESOURCE_IO, 0, 0x10001)) !=3D = NULL) { + INIT_PCDSET(PcdPciIo, Res); + } + + // + // To find low mmio, first find top of low memory, and then search for= io space. + // + if ((MemRes =3D GetHighestResourceDescriptor(EFI_RESOURCE_SYSTEM_MEMOR= Y, 0xffc00000)) !=3D NULL) { + if ((Res =3D GetResourceDescriptor(EFI_RESOURCE_MEMORY_MAPPED_IO, Me= mRes->PhysicalStart, 0x100000000)) !=3D NULL) { + INIT_PCDSET(PcdPciMmio32, Res); + } + } + // + // Set initial protected mode reset address to our initial mailbox + // After DXE, will update address before exiting + // + PcdStatus =3D PcdSet64S (PcdTdRelocatedMailboxBase, PlatformInfo->Relo= catedMailBox); + ASSERT_RETURN_ERROR(PcdStatus); + } + + return EFI_SUCCESS; +} diff --git a/OvmfPkg/TdxDxe/TdxDxe.inf b/OvmfPkg/TdxDxe/TdxDxe.inf new file mode 100644 index 000000000000..b77c6e5e9252 --- /dev/null +++ b/OvmfPkg/TdxDxe/TdxDxe.inf @@ -0,0 +1,62 @@ +#/** @file +# +# Driver clears the encryption attribute from MMIO regions when TDX is en= abled +# +# Copyright (c) 2017, AMD Inc. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION =3D 1.25 + BASE_NAME =3D TdxDxe + FILE_GUID =3D E750224E-7BCE-40AF-B5BB-47E3611EB5C2 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D TdxDxeEntryPoint + +[Sources] + TdxDxe.c + TdxAcpiTable.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DxeServicesTableLib + MemoryAllocationLib + PcdLib + UefiDriverEntryPoint + TdxLib + HobLib + +[Depex] + TRUE + +[Guids] + gUefiOvmfPkgTdxPlatformGuid ## CONSUMES + +[Protocols] + gQemuAcpiTableNotifyProtocolGuid ## CONSUMES + gEfiAcpiSdtProtocolGuid ## CONSUMES + gEfiAcpiTableProtocolGuid ## CONSUMES + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId + gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber + gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81496): https://edk2.groups.io/g/devel/message/81496 Mute This Topic: https://groups.io/mt/86085765/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81497+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81497+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405269; cv=none; d=zohomail.com; s=zohoarc; b=Upl7DmZ7yPUrNpoyycxuEPpZ+Yc4+ADqVRYYLcvDTB6BfOROQjWDDlbLXJjk8btjAnSxwoT2y6sEDINNx5mr+wZrVUeYfAL9TMghDMLM7q9PjzDAutsalb74nQegiLMACTBmdjfYS5n8zmMhNOvF12I8hEXNUwQ1F3VSNhcbP28= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405269; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=xuZma+SHXNc4Twt86jjvzwsvQAtZvusoWsJq9w0MTaE=; b=UaXDgrEwN6dv/8OpqTvnl+BQHVJPRfpPEHZLk7wrFNgNC9GaN6uYx1m8obiYBJTA1QOGvhZV8QZzNNQNR7IoPgNC0h3embqZfDOGh1bizfy8Wbf3iAKFIR/u5ZgRsvbGE9zRV5PpAqKGlVXuOkRDI8FgyQoRMeHe2iRnZSBsDdo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81497+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405269843811.5496628411562; Mon, 4 Oct 2021 20:41:09 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 46iiYY1788612xQ1hcWWVZS4; Mon, 04 Oct 2021 20:41:09 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web12.20766.1633405266346904661 for ; Mon, 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958256" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958256" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:04 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828825" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:01 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 25/28] OvmfPkg/BaseMemEncryptTdxLib: Add TDX helper library Date: Tue, 5 Oct 2021 11:39:36 +0800 Message-Id: <96d207f5d59e60183c51321b3f3b53e5b1f8348f.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: eZYeoOFXY2asbzgPwGgv58z9x1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405269; bh=dDsGdbyejlLyDOtnQYxT13mTx4x4GtaJcehLjqCcTvk=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=FctFzxnLEE0GfIqZO6Y9Ewo6/+zyzjamwszLqh/yEvr/+PZjUukxGpJGYppEMfcyVuo Knlg1/5QO2Io+0aUjoALhDGdkH2abEWt0Ius6vWMoTJBYxIeTldiu9JlHUaZyMQlabuA/ kSskzNDIwk+ZeuIg+uMLkLAHPEZdvvM2PE8= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405271039100038 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 Add Intel TDXhelper library. The library provides the routines to: - set or clear Shared bit for a given memory region. - query whether TDX is enabled. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Include/Library/MemEncryptTdxLib.h | 81 ++ .../BaseMemEncryptTdxLib.inf | 45 + .../BaseMemEncryptTdxLibNull.inf | 35 + .../BaseMemoryEncryptionNull.c | 90 ++ .../BaseMemEncryptTdxLib/MemoryEncryption.c | 938 ++++++++++++++++++ .../BaseMemEncryptTdxLib/VirtualMemory.h | 181 ++++ OvmfPkg/OvmfPkg.dec | 4 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + 9 files changed, 1376 insertions(+) create mode 100644 OvmfPkg/Include/Library/MemEncryptTdxLib.h create mode 100644 OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxL= ib.inf create mode 100644 OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxL= ibNull.inf create mode 100644 OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemoryEncrypti= onNull.c create mode 100644 OvmfPkg/Library/BaseMemEncryptTdxLib/MemoryEncryption.c create mode 100644 OvmfPkg/Library/BaseMemEncryptTdxLib/VirtualMemory.h diff --git a/OvmfPkg/Include/Library/MemEncryptTdxLib.h b/OvmfPkg/Include/L= ibrary/MemEncryptTdxLib.h new file mode 100644 index 000000000000..6a482422f5ed --- /dev/null +++ b/OvmfPkg/Include/Library/MemEncryptTdxLib.h @@ -0,0 +1,81 @@ +/** @file + + Define Memory Encrypted Virtualization base library helper function + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef MEM_ENCRYPT_TDX_LIB_H_ +#define MEM_ENCRYPT_TDX_LIB_H_ + +#include + +/** + Returns boolean to indicate whether to indicate which, if any, memory en= cryption is enabled + + @param[in] Type Bitmask of encryption technologies to check is= enabled + + @retval TRUE The encryption type(s) are enabled + @retval FALSE The encryption type(s) are not enabled +**/ +BOOLEAN +EFIAPI +MemEncryptTdxIsEnabled ( + VOID + ); + +/** + This function clears memory encryption bit for the memory region specifi= ed by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were cleared for the + memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attri= bute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxSetPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ); + +/** + This function sets memory encryption bit for the memory region specified= by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were set for the memo= ry + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encryption attrib= ute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxClearPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ); + +#endif // _MEM_ENCRYPT_TDX_LIB_H_ diff --git a/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf = b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf new file mode 100644 index 000000000000..c74581c447bf --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLib.inf @@ -0,0 +1,45 @@ +## @file +# Library for TDX Memory Encryption +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION =3D 1.25 + BASE_NAME =3D MemEncryptTdxLib + FILE_GUID =3D 7E6651B2-B775-4593-A410-FC05B8C61993 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MemEncryptTdxLib|PEIM DXE_DRIVER DXE_= RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[Sources] + VirtualMemory.h + MemoryEncryption.c + +[LibraryClasses] + BaseLib + CacheMaintenanceLib + CpuLib + DebugLib + MemoryAllocationLib + PcdLib + TdxLib + +[Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr diff --git a/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.= inf b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf new file mode 100644 index 000000000000..a050edb5b734 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxLibNull.inf @@ -0,0 +1,35 @@ +## @file +# Library for Memory Encryption +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2017 Advanced Micro Devices. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION =3D 1.25 + BASE_NAME =3D MemEncryptTdxLibNull + FILE_GUID =3D 3C69C4CA-DE46-44D7-8AA5-6EE51A4E3EA7 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 1.0 + LIBRARY_CLASS =3D MemEncryptTdxLib|PEIM DXE_DRIVER DXE_= RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the = build +# tools. +# +# VALID_ARCHITECTURES =3D X64 IA32 +# + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[Sources] + BaseMemoryEncryptionNull.c + +[LibraryClasses] + BaseLib diff --git a/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemoryEncryptionNull.= c b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemoryEncryptionNull.c new file mode 100644 index 000000000000..3deb6ffeae3d --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemoryEncryptionNull.c @@ -0,0 +1,90 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c + +**/ + +#include +#include +#include +#include + +/** + Returns boolean to indicate whether to indicate which, if any, memory en= cryption is enabled + + @param[in] Type Bitmask of encryption technologies to check is= enabled + + @retval TRUE The encryption type(s) are enabled + @retval FALSE The encryption type(s) are not enabled +**/ +BOOLEAN +EFIAPI +MemEncryptTdxIsEnabled ( + VOID + ) +{ + return FALSE; +} + +/** + This function clears memory encryption bit for the memory region specifi= ed by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were cleared for the + memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attri= bute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxSetPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + return EFI_UNSUPPORTED; +} + +/** + This function sets memory encryption bit for the memory region specified= by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were set for the memo= ry + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encryption attrib= ute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxClearPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/OvmfPkg/Library/BaseMemEncryptTdxLib/MemoryEncryption.c b/Ovmf= Pkg/Library/BaseMemEncryptTdxLib/MemoryEncryption.c new file mode 100644 index 000000000000..29155c525401 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptTdxLib/MemoryEncryption.c @@ -0,0 +1,938 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c + +**/ + +#include +#include +#include +#include +#include +#include +#include "VirtualMemory.h" +#include +#include +#include + +typedef enum { + SetSharedBit, + ClearSharedBit +} TDX_PAGETABLE_MODE; + +STATIC PAGE_TABLE_POOL *mPageTablePool =3D NULL; + +/** + Returns boolean to indicate whether to indicate which, if any, memory en= cryption is enabled + + @param[in] Type Bitmask of encryption technologies to check is= enabled + + @retval TRUE The encryption type(s) are enabled + @retval FALSE The encryption type(s) are not enabled +**/ +BOOLEAN +EFIAPI +MemEncryptTdxIsEnabled ( + VOID + ) +{ + return PcdGet64 (PcdConfidentialComputingGuestAttr) =3D=3D CCAttrIntelTd= x; +} + +/** + Get the memory encryption mask + + @param[out] EncryptionMask contains the pte mask. + +**/ +STATIC +UINT64 +GetMemEncryptionAddressMask ( + VOID + ) +{ + return TdSharedPageMask(); +} + +/** + Initialize a buffer pool for page table use only. + + To reduce the potential split operation on page table, the pages reserve= d for + page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGE= S and + at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always + initialized with number of pages greater than or equal to the given + PoolPages. + + Once the pages in the pool are used up, this method should be called aga= in to + reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. Usually this won't + happen often in practice. + + @param[in] PoolPages The least page number of the pool to be create= d. + + @retval TRUE The pool is initialized successfully. + @retval FALSE The memory is out of resource. +**/ +STATIC +BOOLEAN +InitializePageTablePool ( + IN UINTN PoolPages + ) +{ + VOID *Buffer; + + // + // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one pag= e for + // header. + // + PoolPages +=3D 1; // Add one page for header. + PoolPages =3D ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) * + PAGE_TABLE_POOL_UNIT_PAGES; + Buffer =3D AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT); + if (Buffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n")); + return FALSE; + } + + // + // Link all pools into a list for easier track later. + // + if (mPageTablePool =3D=3D NULL) { + mPageTablePool =3D Buffer; + mPageTablePool->NextPool =3D mPageTablePool; + } else { + ((PAGE_TABLE_POOL *)Buffer)->NextPool =3D mPageTablePool->NextPool; + mPageTablePool->NextPool =3D Buffer; + mPageTablePool =3D Buffer; + } + + // + // Reserve one page for pool header. + // + mPageTablePool->FreePages =3D PoolPages - 1; + mPageTablePool->Offset =3D EFI_PAGES_TO_SIZE (1); + + return TRUE; +} + +/** + This API provides a way to allocate memory for page table. + + This API can be called more than once to allocate memory for page tables. + + Allocates the number of 4KB pages and returns a pointer to the allocated + buffer. The buffer returned is aligned on a 4KB boundary. + + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NUL= L is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +STATIC +VOID * +EFIAPI +AllocatePageTableMemory ( + IN UINTN Pages + ) +{ + VOID *Buffer; + + if (Pages =3D=3D 0) { + return NULL; + } + + // + // Renew the pool if necessary. + // + if (mPageTablePool =3D=3D NULL || + Pages > mPageTablePool->FreePages) { + if (!InitializePageTablePool (Pages)) { + return NULL; + } + } + + Buffer =3D (UINT8 *)mPageTablePool + mPageTablePool->Offset; + + mPageTablePool->Offset +=3D EFI_PAGES_TO_SIZE (Pages); + mPageTablePool->FreePages -=3D Pages; + + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: Buffer=3D0x%Lx Pages=3D%ld\n", + gEfiCallerBaseName, + __FUNCTION__, + Buffer, + Pages + )); + + return Buffer; +} + + +/** + Split 2M page to 4K. + + @param[in] PhysicalAddress Start physical address the 2M page + covered. + @param[in, out] PageEntry2M Pointer to 2M page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split2MPageTo4K ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry2M, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize, + IN UINT64 AddressEncMask + ) +{ + PHYSICAL_ADDRESS PhysicalAddress4K; + UINTN IndexOfPageTableEntries; + PAGE_TABLE_4K_ENTRY *PageTableEntry, *PageTableEntry1; + + PageTableEntry =3D AllocatePageTableMemory(1); + + PageTableEntry1 =3D PageTableEntry; + + if (PageTableEntry =3D=3D NULL) { + ASSERT (FALSE); + return; + } + + PhysicalAddress4K =3D PhysicalAddress; + for (IndexOfPageTableEntries =3D 0; + IndexOfPageTableEntries < 512; + (IndexOfPageTableEntries++, + PageTableEntry++, + PhysicalAddress4K +=3D SIZE_4KB)) { + // + // Fill in the Page Table entries + // + PageTableEntry->Uint64 =3D (UINT64) PhysicalAddress4K | AddressEncMask; + PageTableEntry->Bits.ReadWrite =3D 1; + PageTableEntry->Bits.Present =3D 1; + if ((PhysicalAddress4K >=3D StackBase) && + (PhysicalAddress4K < StackBase + StackSize)) { + // + // Set Nx bit for stack. + // + PageTableEntry->Bits.Nx =3D 1; + } + } + + // + // Fill in 2M page entry. + // + *PageEntry2M =3D ((UINT64)(UINTN)PageTableEntry1 | + IA32_PG_P | IA32_PG_RW | AddressEncMask); +} + +/** + Set one page of page table pool memory to be read-only. + + @param[in] PageTableBase Base address of page table (CR3). + @param[in] Address Start address of a page to be set as read-on= ly. + @param[in] Level4Paging Level 4 paging flag. + +**/ +STATIC +VOID +SetPageTablePoolReadOnly ( + IN UINTN PageTableBase, + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN Level4Paging + ) +{ + UINTN Index; + UINTN EntryIndex; + UINT64 AddressEncMask; + UINT64 ActiveAddressEncMask; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT64 *PageTable; + UINT64 *NewPageTable; + UINT64 PageAttr; + UINT64 LevelSize[5]; + UINT64 LevelMask[5]; + UINTN LevelShift[5]; + UINTN Level; + UINT64 PoolUnitSize; + + if (PageTableBase =3D=3D 0) { + ASSERT (FALSE); + return; + } + + // + // Since the page table is always from page table pool, which is always + // located at the boundary of PcdPageTablePoolAlignment, we just need to + // set the whole pool unit to be read-only. + // + Address =3D Address & PAGE_TABLE_POOL_ALIGN_MASK; + + LevelShift[1] =3D PAGING_L1_ADDRESS_SHIFT; + LevelShift[2] =3D PAGING_L2_ADDRESS_SHIFT; + LevelShift[3] =3D PAGING_L3_ADDRESS_SHIFT; + LevelShift[4] =3D PAGING_L4_ADDRESS_SHIFT; + + LevelMask[1] =3D PAGING_4K_ADDRESS_MASK_64; + LevelMask[2] =3D PAGING_2M_ADDRESS_MASK_64; + LevelMask[3] =3D PAGING_1G_ADDRESS_MASK_64; + LevelMask[4] =3D PAGING_1G_ADDRESS_MASK_64; + + LevelSize[1] =3D SIZE_4KB; + LevelSize[2] =3D SIZE_2MB; + LevelSize[3] =3D SIZE_1GB; + LevelSize[4] =3D SIZE_512GB; + + AddressEncMask =3D GetMemEncryptionAddressMask() & + PAGING_1G_ADDRESS_MASK_64; + PageTable =3D (UINT64 *)(UINTN)PageTableBase; + PoolUnitSize =3D PAGE_TABLE_POOL_UNIT_SIZE; + + for (Level =3D (Level4Paging) ? 4 : 3; Level > 0; --Level) { + Index =3D ((UINTN)RShiftU64 (Address, LevelShift[Level])); + Index &=3D PAGING_PAE_INDEX_MASK; + + PageAttr =3D PageTable[Index]; + ActiveAddressEncMask =3D GetMemEncryptionAddressMask() & PageAttr; + + if ((PageAttr & IA32_PG_PS) =3D=3D 0) { + // + // Go to next level of table. + // + PageTable =3D (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask & + PAGING_4K_ADDRESS_MASK_64); + continue; + } + + if (PoolUnitSize >=3D LevelSize[Level]) { + // + // Clear R/W bit if current page granularity is not larger than pool= unit + // size. + // + if ((PageAttr & IA32_PG_RW) !=3D 0) { + while (PoolUnitSize > 0) { + // + // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are f= it in + // one page (2MB). Then we don't need to update attributes for p= ages + // crossing page directory. ASSERT below is for that purpose. + // + ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64)); + + PageTable[Index] &=3D ~(UINT64)IA32_PG_RW; + PoolUnitSize -=3D LevelSize[Level]; + + ++Index; + } + } + + break; + + } else { + // + // The smaller granularity of page must be needed. + // + ASSERT (Level > 1); + + NewPageTable =3D AllocatePageTableMemory (1); + if (NewPageTable =3D=3D NULL) { + ASSERT (FALSE); + return; + } + + PhysicalAddress =3D PageAttr & LevelMask[Level]; + for (EntryIndex =3D 0; + EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64); + ++EntryIndex) { + NewPageTable[EntryIndex] =3D PhysicalAddress | ActiveAddressEncMa= sk | + IA32_PG_P | IA32_PG_RW; + if (Level > 2) { + NewPageTable[EntryIndex] |=3D IA32_PG_PS; + } + PhysicalAddress +=3D LevelSize[Level - 1]; + } + + PageTable[Index] =3D (UINT64)(UINTN)NewPageTable | ActiveAddressEncM= ask | + IA32_PG_P | IA32_PG_RW; + PageTable =3D NewPageTable; + } + } +} + +/** + Prevent the memory pages used for page table from been overwritten. + + @param[in] PageTableBase Base address of page table (CR3). + @param[in] Level4Paging Level 4 paging flag. + +**/ +STATIC +VOID +EnablePageTableProtection ( + IN UINTN PageTableBase, + IN BOOLEAN Level4Paging + ) +{ + PAGE_TABLE_POOL *HeadPool; + PAGE_TABLE_POOL *Pool; + UINT64 PoolSize; + EFI_PHYSICAL_ADDRESS Address; + + if (mPageTablePool =3D=3D NULL) { + return; + } + + // + // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to + // remember original one in advance. + // + HeadPool =3D mPageTablePool; + Pool =3D HeadPool; + do { + Address =3D (EFI_PHYSICAL_ADDRESS)(UINTN)Pool; + PoolSize =3D Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages); + + // + // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE, + // which is one of page size of the processor (2MB by default). Let's = apply + // the protection to them one by one. + // + while (PoolSize > 0) { + SetPageTablePoolReadOnly(PageTableBase, Address, Level4Paging); + Address +=3D PAGE_TABLE_POOL_UNIT_SIZE; + PoolSize -=3D PAGE_TABLE_POOL_UNIT_SIZE; + } + + Pool =3D Pool->NextPool; + } while (Pool !=3D HeadPool); + +} + + +/** + Split 1G page to 2M. + + @param[in] PhysicalAddress Start physical address the 1G page + covered. + @param[in, out] PageEntry1G Pointer to 1G page entry. + @param[in] StackBase Stack base address. + @param[in] StackSize Stack size. + +**/ +STATIC +VOID +Split1GPageTo2M ( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN OUT UINT64 *PageEntry1G, + IN PHYSICAL_ADDRESS StackBase, + IN UINTN StackSize + ) +{ + PHYSICAL_ADDRESS PhysicalAddress2M; + UINTN IndexOfPageDirectoryEntries; + PAGE_TABLE_ENTRY *PageDirectoryEntry; + UINT64 AddressEncMask; + UINT64 ActiveAddressEncMask; + + PageDirectoryEntry =3D AllocatePageTableMemory(1); + if (PageDirectoryEntry =3D=3D NULL) { + return; + } + + AddressEncMask =3D GetMemEncryptionAddressMask (); + ASSERT (PageDirectoryEntry !=3D NULL); + + ActiveAddressEncMask =3D *PageEntry1G & AddressEncMask; + // + // Fill in 1G page entry. + // + *PageEntry1G =3D ((UINT64)(UINTN)PageDirectoryEntry | + IA32_PG_P | IA32_PG_RW | ActiveAddressEncMask); + + PhysicalAddress2M =3D PhysicalAddress; + for (IndexOfPageDirectoryEntries =3D 0; + IndexOfPageDirectoryEntries < 512; + (IndexOfPageDirectoryEntries++, + PageDirectoryEntry++, + PhysicalAddress2M +=3D SIZE_2MB)) { + if ((PhysicalAddress2M < StackBase + StackSize) && + ((PhysicalAddress2M + SIZE_2MB) > StackBase)) { + // + // Need to split this 2M page that covers stack range. + // + Split2MPageTo4K ( + PhysicalAddress2M, + (UINT64 *)PageDirectoryEntry, + StackBase, + StackSize, + ActiveAddressEncMask + ); + } else { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 =3D (UINT64) PhysicalAddress2M | ActiveAd= dressEncMask; + PageDirectoryEntry->Bits.ReadWrite =3D 1; + PageDirectoryEntry->Bits.Present =3D 1; + PageDirectoryEntry->Bits.MustBe1 =3D 1; + } + } +} + + +/** + Set or Clear the memory encryption bit + + @param[in] PagetablePoint Page table entry pointer (PTE). + @param[in] Mode Set or Clear encryption bit + +**/ +STATIC VOID +SetOrClearSharedBit( + IN OUT UINT64* PageTablePointer, + IN TDX_PAGETABLE_MODE Mode, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 Length + ) +{ + UINT64 AddressEncMask; + UINT64 Status; + + AddressEncMask =3D GetMemEncryptionAddressMask (); + + // + // Set or clear page table entry. Also, set shared bit in physical addre= ss, before calling MapGPA + // + if (Mode =3D=3D SetSharedBit) { + *PageTablePointer |=3D AddressEncMask; + PhysicalAddress |=3D AddressEncMask; + } else { + *PageTablePointer &=3D ~AddressEncMask; + PhysicalAddress &=3D ~AddressEncMask; + } + + Status =3D TdVmCall(TDVMCALL_MAPGPA, PhysicalAddress, Length, 0, 0, NULL= ); + + // + // If changing shared to private, must accept-page again + // + if (Mode =3D=3D ClearSharedBit) { + TdAcceptPages(PhysicalAddress, Length / EFI_PAGE_SIZE, EFI_PAGE_SIZE); + } + + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: pte=3D0x%Lx AddressEncMask=3D0x%Lx Mode=3D0x%x MapGPA Status= =3D0x%x\n", + gEfiCallerBaseName, + __FUNCTION__, + *PageTablePointer, + AddressEncMask, + Mode, Status)); +} + +/** + Check the WP status in CR0 register. This bit is used to lock or unlock w= rite + access to pages marked as read-only. + + @retval TRUE Write protection is enabled. + @retval FALSE Write protection is disabled. +**/ +STATIC +BOOLEAN +IsReadOnlyPageWriteProtected ( + VOID + ) +{ + return ((AsmReadCr0 () & BIT16) !=3D 0); +} + + +/** + Disable Write Protect on pages marked as read-only. +**/ +STATIC +VOID +DisableReadOnlyPageWriteProtect ( + VOID + ) +{ + AsmWriteCr0 (AsmReadCr0() & ~BIT16); +} + +/** + Enable Write Protect on pages marked as read-only. +**/ +VOID +EnableReadOnlyPageWriteProtect ( + VOID + ) +{ + AsmWriteCr0 (AsmReadCr0() | BIT16); +} + +/** + This function either sets or clears memory encryption for the memory + region specified by PhysicalAddress and Length from the current page tab= le + context. + + The function iterates through the PhysicalAddress one page at a time, an= d set + or clears the memory encryption in the page table. If it encounters + that a given physical address range is part of large page then it attemp= ts to + change the attribute at one go (based on size), otherwise it splits the + large pages into smaller (e.g 2M page into 4K pages) and then try to set= or + clear the encryption bit on the smallest page size. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] PhysicalAddress The physical address that is the sta= rt + address of a memory region. + @param[in] Length The length of memory region + @param[in] Mode Set or Clear mode + + @retval RETURN_SUCCESS The attributes were cleared for the + memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encyrption attrib= ute + is not supported +**/ + +STATIC +RETURN_STATUS +EFIAPI +SetMemorySharedOrPrivate ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS PhysicalAddress, + IN UINTN Length, + IN TDX_PAGETABLE_MODE Mode + ) +{ + + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry; + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; + PAGE_TABLE_ENTRY *PageDirectory2MEntry; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + UINT64 PgTableMask; + UINT64 AddressEncMask; + UINT64 ActiveEncMask; + BOOLEAN IsWpEnabled; + RETURN_STATUS Status; + IA32_CR4 Cr4; + BOOLEAN Page5LevelSupport; + + // + // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnin= gs. + // + PageMapLevel4Entry =3D NULL; + + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: Cr3Base=3D0x%Lx Physical=3D0x%Lx Length=3D0x%Lx Mode=3D%a\n", + gEfiCallerBaseName, + __FUNCTION__, + Cr3BaseAddress, + PhysicalAddress, + (UINT64)Length, + (Mode =3D=3D SetSharedBit) ? "Shared" : "Private" + )); + + // + // Check if we have a valid memory encryption mask + // + AddressEncMask =3D GetMemEncryptionAddressMask (); + + PgTableMask =3D AddressEncMask | EFI_PAGE_MASK; + + if (Length =3D=3D 0) { + return RETURN_INVALID_PARAMETER; + } + + // + // Make sure that the page table is changeable. + // + IsWpEnabled =3D IsReadOnlyPageWriteProtected (); + if (IsWpEnabled) { + DisableReadOnlyPageWriteProtect (); + } + + // + // If Cr3BaseAddress is not specified then read the current CR3 + // + if (Cr3BaseAddress =3D=3D 0) { + Cr3BaseAddress =3D AsmReadCr3(); + } + // + // CPU will already have LA57 enabled so just check CR4 + // + Cr4.UintN =3D AsmReadCr4 (); + + Page5LevelSupport =3D (Cr4.Bits.LA57 ? TRUE : FALSE); + // + // If 5-level pages, adjust Cr3BaseAddress to point to first 4-level pag= e directory, + // we will only have 1 + // + if (Page5LevelSupport) { + Cr3BaseAddress =3D *(UINT64 *)Cr3BaseAddress & ~PgTableMask; + } + + Status =3D EFI_SUCCESS; + + while (Length) + { + PageMapLevel4Entry =3D (VOID*) (Cr3BaseAddress & ~PgTableMask); + PageMapLevel4Entry +=3D PML4_OFFSET(PhysicalAddress); + if (!PageMapLevel4Entry->Bits.Present) { + DEBUG (( + DEBUG_ERROR, + "%a:%a: bad PML4 for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + Status =3D RETURN_NO_MAPPING; + goto Done; + } + + PageDirectory1GEntry =3D (VOID *)( + (PageMapLevel4Entry->Bits.PageTableBaseAddres= s << + 12) & ~PgTableMask + ); + PageDirectory1GEntry +=3D PDP_OFFSET(PhysicalAddress); + if (!PageDirectory1GEntry->Bits.Present) { + DEBUG (( + DEBUG_ERROR, + "%a:%a: bad PDPE for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + Status =3D RETURN_NO_MAPPING; + goto Done; + } + + // + // If the MustBe1 bit is not 1, it's not actually a 1GB entry + // + if (PageDirectory1GEntry->Bits.MustBe1) { + // + // Valid 1GB page + // If we have at least 1GB to go, we can just update this entry + // + if (!(PhysicalAddress & (BIT30 - 1)) && Length >=3D BIT30) { + SetOrClearSharedBit(&PageDirectory1GEntry->Uint64, Mode, PhysicalA= ddress, BIT30); + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: updated 1GB entry for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + PhysicalAddress +=3D BIT30; + Length -=3D BIT30; + } else { + // + // We must split the page + // + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: splitting 1GB page for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + Split1GPageTo2M ( + (UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress << 30, + (UINT64 *)PageDirectory1GEntry, + 0, + 0 + ); + continue; + } + } else { + // + // Actually a PDP + // + PageUpperDirectoryPointerEntry =3D + (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory1GEntry; + PageDirectory2MEntry =3D + (VOID *)( + (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress << + 12) & ~PgTableMask + ); + PageDirectory2MEntry +=3D PDE_OFFSET(PhysicalAddress); + if (!PageDirectory2MEntry->Bits.Present) { + DEBUG (( + DEBUG_ERROR, + "%a:%a: bad PDE for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + Status =3D RETURN_NO_MAPPING; + goto Done; + } + // + // If the MustBe1 bit is not a 1, it's not a 2MB entry + // + if (PageDirectory2MEntry->Bits.MustBe1) { + // + // Valid 2MB page + // If we have at least 2MB left to go, we can just update this ent= ry + // + if (!(PhysicalAddress & (BIT21-1)) && Length >=3D BIT21) { + SetOrClearSharedBit (&PageDirectory2MEntry->Uint64, Mode, Physic= alAddress, BIT21); + PhysicalAddress +=3D BIT21; + Length -=3D BIT21; + } else { + // + // We must split up this page into 4K pages + // + DEBUG (( + DEBUG_VERBOSE, + "%a:%a: splitting 2MB page for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + + ActiveEncMask =3D PageDirectory2MEntry->Uint64 & AddressEncMask; + + Split2MPageTo4K ( + (UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress << 21, + (UINT64 *)PageDirectory2MEntry, + 0, + 0, + ActiveEncMask + ); + continue; + } + } else { + PageDirectoryPointerEntry =3D + (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry; + PageTableEntry =3D + (VOID *)( + (PageDirectoryPointerEntry->Bits.PageTableBaseAddress << + 12) & ~PgTableMask + ); + PageTableEntry +=3D PTE_OFFSET(PhysicalAddress); + if (!PageTableEntry->Bits.Present) { + DEBUG (( + DEBUG_ERROR, + "%a:%a: bad PTE for Physical=3D0x%Lx\n", + gEfiCallerBaseName, + __FUNCTION__, + PhysicalAddress + )); + Status =3D RETURN_NO_MAPPING; + goto Done; + } + SetOrClearSharedBit (&PageTableEntry->Uint64, Mode, PhysicalAddres= s, EFI_PAGE_SIZE); + PhysicalAddress +=3D EFI_PAGE_SIZE; + Length -=3D EFI_PAGE_SIZE; + } + } + } + + // + // Protect the page table by marking the memory used for page table to be + // read-only. + // + if (IsWpEnabled) { + EnablePageTableProtection ((UINTN)PageMapLevel4Entry, TRUE); + } + + // + // Flush TLB + // + CpuFlushTlb(); + +Done: + // + // Restore page table write protection, if any. + // + if (IsWpEnabled) { + EnableReadOnlyPageWriteProtect (); + } + + return Status; +} + +/** + This function clears memory encryption bit for the memory region specifi= ed by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were cleared for the + memory region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Clearing the memory encryption attri= bute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxSetPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + return SetMemorySharedOrPrivate ( + Cr3BaseAddress, + BaseAddress, + EFI_PAGES_TO_SIZE (NumPages), + SetSharedBit + ); +} + +/** + This function sets memory encryption bit for the memory region specified= by + BaseAddress and NumPages from the current page table context. + + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use + current CR3) + @param[in] BaseAddress The physical address that is the sta= rt + address of a memory region. + @param[in] NumPages The number of pages from start memory + region. + + @retval RETURN_SUCCESS The attributes were set for the memo= ry + region. + @retval RETURN_INVALID_PARAMETER Number of pages is zero. + @retval RETURN_UNSUPPORTED Setting the memory encryption attrib= ute + is not supported +**/ +RETURN_STATUS +EFIAPI +MemEncryptTdxClearPageSharedBit ( + IN PHYSICAL_ADDRESS Cr3BaseAddress, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINTN NumPages + ) +{ + return SetMemorySharedOrPrivate ( + Cr3BaseAddress, + BaseAddress, + EFI_PAGES_TO_SIZE (NumPages), + ClearSharedBit + ); +} diff --git a/OvmfPkg/Library/BaseMemEncryptTdxLib/VirtualMemory.h b/OvmfPkg= /Library/BaseMemEncryptTdxLib/VirtualMemory.h new file mode 100644 index 000000000000..c23472f71909 --- /dev/null +++ b/OvmfPkg/Library/BaseMemEncryptTdxLib/VirtualMemory.h @@ -0,0 +1,181 @@ +/** @file + + Virtual Memory Management Services to set or clear the memory encryption= bit + + Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h + +**/ + +#ifndef __VIRTUAL_MEMORY__ +#define __VIRTUAL_MEMORY__ + +#include +#include +#include +#include +#include +#include + +#define SYS_CODE64_SEL 0x38 + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, + // 1 =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, + // 1 =3D Write-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, + // 1 =3D Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system softw= are + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} PAGE_MAP_AND_DIRECTORY_POINTER; + +// +// Page Table Entry 4KB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, + // 1 =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, + // 1 =3D Write-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, + // 1 =3D Accessed (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by + // processor on access to page + UINT64 PAT:1; // + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page + // TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, + // 1 =3D No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, + // 1 =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, + // 1=3DWrite-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, + // 1 =3D Accessed (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by + // processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page + // TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, + // 1 =3D No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_ENTRY; + +// +// Page Table Entry 1GB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, + // 1 =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, + // 1 =3D Write-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, + // 1 =3D Accessed (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by + // processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page + // TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PAT:1; // + UINT64 MustBeZero:17; // Must be zero; + UINT64 PageTableBaseAddress:22; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, + // 1 =3D No Code Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_1G_ENTRY; + +#pragma pack() + +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 +#define IA32_PG_PS BIT7 + +#define PAGING_PAE_INDEX_MASK 0x1FF + +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull +#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + +#define PAGING_L1_ADDRESS_SHIFT 12 +#define PAGING_L2_ADDRESS_SHIFT 21 +#define PAGING_L3_ADDRESS_SHIFT 30 +#define PAGING_L4_ADDRESS_SHIFT 39 + +#define PAGING_PML4E_NUMBER 4 + +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1) +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK) +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK) +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK) +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK) +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + +#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB +#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB +#define PAGE_TABLE_POOL_UNIT_PAGES \ + EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE) +#define PAGE_TABLE_POOL_ALIGN_MASK \ + (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1)) + +typedef struct { + VOID *NextPool; + UINTN Offset; + UINTN FreePages; +} PAGE_TABLE_POOL; + +#endif diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index cc5087da6aa2..dda83d81695b 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -34,6 +34,10 @@ # Virtualization (SEV) guests. MemEncryptSevLib|Include/Library/MemEncryptSevLib.h =20 + ## @libraryclass Declares helper functions for TDX guests. + # + MemEncryptTdxLib|Include/Library/MemEncryptTdxLib.h + ## @libraryclass Save and restore variables using a file # NvVarsFileLib|Include/Library/NvVarsFileLib.h diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 46040357da83..b17f654c96cc 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -176,6 +176,7 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLi= b.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxL= ibNull.inf !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index acdcdeee9969..096d609d0d86 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -180,6 +180,7 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLi= b.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxL= ibNull.inf !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81497): https://edk2.groups.io/g/devel/message/81497 Mute This Topic: https://groups.io/mt/86085766/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81498+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81498+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405270; cv=none; d=zohomail.com; s=zohoarc; b=LgcPjkzQVZFqrZ+NGNoFcCzBEs3OVi6u4X3usOhS733BiAL/XxQ+isxIdFkwz2xzUugW45s40uExXL4lemH9ULpI8HSRehSvKUlw93rSjcTRX+AqA3WuLTv64S8F6O9N3xyQ2y3UAjapkHaJ9C+VGVF+yLJkCGJwnQuF4i3di6k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405270; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=a5D5q0VjFoJeoxKDi9le4Lyf9rInC46ae4tblGWR6eY=; b=WB6Qdw0ctt/wFPF+kJt5TfSD0+hYavffflErL21JSCJ0kKEf1x5TcfXhR6lo1D+l5Os7YCfDASAuUtYiNQESvFOhFKA3B+cKkR+4xASvyvEwtMNysCiUGHaIveEdgrYpwF3kHKoQlYxwIEuO5Q4TTRM1zZaJn+kecwAfxR1/chI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81498+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405270639193.89932975201305; Mon, 4 Oct 2021 20:41:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id g34QYY1788612xoomokuQ8Vl; Mon, 04 Oct 2021 20:41:10 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web12.20766.1633405266346904661 for ; Mon, 04 Oct 2021 20:41:07 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958273" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958273" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:06 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828855" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:04 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 26/28] OvmfPkg/QemuFwCfgLib: Support Tdx in QemuFwCfgDxe Date: Tue, 5 Oct 2021 11:39:37 +0800 Message-Id: <68acc64acd6a891be2727d164bb424360b3c9d05.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: FxfF2izF9VOVvQfeSOPeQmkfx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405270; bh=X18MKbXWInADBg5p3z1OtzKGSc/nNykyEdr52LWLqAM=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=AeRUwsDvSB9zNA2Qwrs1Bvk2SGYFo56eUJfpH1ZMEeq3FyuAWLGxJ+CxdExlfQcZSN5 lvE7pZ3H057M7Drthzag1QaDdO4X7QXRTBaDnWTeu9/T62eOH5wmgwdWmy/2r+nTv063r CEhM1Czw9bmlO0kp+QA0dN2s03Z43T2fOxw= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405271102100042 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 In the previous QemuFwCfgDxe only SEV is supported. This commit introduce TDX support in QemuFwCfgDxe. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 9 +++++---- OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/= QemuFwCfgLib/QemuFwCfgDxe.c index 0182c9235cac..7a60b3e82863 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c @@ -19,6 +19,7 @@ #include #include #include +#include #include =20 #include "QemuFwCfgLibInternal.h" @@ -85,7 +86,7 @@ QemuFwCfgInitialize ( DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n")); } =20 - if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) { + if (mQemuFwCfgDmaSupported && (MemEncryptSevIsEnabled () || (MemEncryptT= dxIsEnabled ()))) { EFI_STATUS Status; =20 // @@ -96,7 +97,7 @@ QemuFwCfgInitialize ( (VOID **)&mIoMmuProtocol); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, - "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n", + "QemuFwCfgDma %a:%a Failed to locate IOMMU protocol.\n", gEfiCallerBaseName, __FUNCTION__)); ASSERT (FALSE); CpuDeadLoop (); @@ -371,10 +372,10 @@ InternalQemuFwCfgDmaBytes ( DataBuffer =3D Buffer; =20 // - // When SEV is enabled, map Buffer to DMA address before issuing the DMA + // When SEV or TDX is enabled, map Buffer to DMA address before issuing = the DMA // request // - if (MemEncryptSevIsEnabled ()) { + if (MemEncryptSevIsEnabled() || MemEncryptTdxIsEnabled ()) { VOID *AccessBuffer; EFI_PHYSICAL_ADDRESS DataBufferAddress; =20 diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf b/OvmfPkg/Lib= rary/QemuFwCfgLib/QemuFwCfgDxeLib.inf index 48899ff1236a..ce3eaa5ed8b4 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf @@ -43,6 +43,7 @@ IoLib MemoryAllocationLib MemEncryptSevLib + MemEncryptTdxLib =20 [Protocols] gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81498): https://edk2.groups.io/g/devel/message/81498 Mute This Topic: https://groups.io/mt/86085767/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81499+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81499+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405270; cv=none; d=zohomail.com; s=zohoarc; b=i/k0v5rCyIjnfDNeNvF9Q6b8b3QpRwXpFPDaNBxtU+48kIvo0DIeD2DXXgyMzsG7QcP77SLg7d/8fKLre1ZLrnAGceLYlS7c9EQvkgsQyXS0Z+GrInqtO+xcPpXrHrWi4Z2pJgYGH0azozepwHsC8tn3GF7DBadPMY1+8Vv+nAw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405270; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=aP5hKy1TfbrL98ULqMEe3a6d9bplttuABTy2okIXc/0=; b=OEFCHqFUpFEOtlMwFVO2za8Y9VIFZ6dXWwdIdybRIm/7eHeX/8doSA1lUUd1gvkjGPWTJeRi5FnQk3skkTF//XXeXAQ07NnrErho4E8UuUXWW8r5zK8P55QHVLR5JQWi4+vceOvjn+GnKU941Vhf0QV+BTJoS1Cj/0ySRHqId+k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81499+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405270852195.96925639876872; Mon, 4 Oct 2021 20:41:10 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id dPapYY1788612xIjG78i6Jkp; Mon, 04 Oct 2021 20:41:10 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web12.20766.1633405266346904661 for ; Mon, 04 Oct 2021 20:41:09 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958292" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958292" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:09 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828892" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:06 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 27/28] OvmfPkg: Update IoMmuDxe to support TDX Date: Tue, 5 Oct 2021 11:39:38 +0800 Message-Id: <496053d51280854b59c5a7bdd36d3f4a158fbfe6.1633401643.git.min.m.xu@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: 5TgE5NoT3K1nf9msEaWplDbXx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405270; bh=d5B0Upu1Vk0XB/S4jvew2asBd4LRQOwnIFMkM5+pM0Y=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=wVJp5A86QYYYBLutPWEka3tU+vUMufd8QTTOwbju0Gd/RZMN8WEQz2AONSfDwS5YbE/ UC/WxBM6YtBraJTHrv1/RlLhecOfrNYV3Qd1lMCPmV4WDb699O9OJ7YYfFFrgjy9z0uKi 61Mo3Sdf95uC7aTMAbkg7ZA0M9yr8raSQsQ= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405271105100043 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 The IOMMU protocol driver provides capabilities to set a DMA access attribute and methods to allocate, free, map and unmap the DMA memory for the PCI Bus devices. The current IoMmuDxe driver supports DMA operations inside SEV guest. To support DMA operation in TDX guest, mIoMmuType is added to determine if it is Legac guest, SEV guest or TDX guest. Due to security reasons all DMA operations inside the SEV/TDX guest must be performed on shared pages. The IOMMU protocol driver for the SEV/TDX guest uses a bounce buffer to map guest DMA buffer to shared pages in order to provide the support for DMA operations inside SEV/TDX guest. The call of SEV or TDX specific function to set/clear EncMask/SharedBit is determined by mIoMmuType. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 134 ++++++++++++++++++++++++--------- OvmfPkg/IoMmuDxe/AmdSevIoMmu.h | 12 +++ OvmfPkg/IoMmuDxe/IoMmuDxe.c | 4 +- OvmfPkg/IoMmuDxe/IoMmuDxe.inf | 1 + OvmfPkg/OvmfPkgX64.dsc | 2 + 5 files changed, 117 insertions(+), 36 deletions(-) diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c index b30628078f73..6c9570677cdc 100644 --- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c +++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c @@ -1,9 +1,9 @@ /** @file =20 The protocol provides support to allocate, free, map and umap a DMA buff= er - for bus master (e.g PciHostBridge). When SEV is enabled, the DMA operati= ons - must be performed on unencrypted buffer hence we use a bounce buffer to = map - the guest buffer into an unencrypted DMA buffer. + for bus master (e.g PciHostBridge). When SEV or TDX is enabled, the DMA + operations must be performed on unencrypted buffer hence we use a bounce + buffer to map the guest buffer into an unencrypted DMA buffer. =20 Copyright (c) 2017, AMD Inc. All rights reserved.
Copyright (c) 2017, Intel Corporation. All rights reserved.
@@ -14,6 +14,12 @@ =20 #include "AmdSevIoMmu.h" =20 +#define IO_MMU_LEGACY 0x0 +#define IO_MMU_SEV 0x01 +#define IO_MMU_TDX 0x02 + +UINTN mIoMmuType =3D IO_MMU_LEGACY; + #define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O') =20 typedef struct { @@ -74,7 +80,7 @@ typedef struct { =20 /** Provides the controller-specific addresses required to access system mem= ory - from a DMA bus master. On SEV guest, the DMA operations must be performe= d on + from a DMA bus master. On SEV/TDX guest, the DMA operations must be perf= ormed on shared buffer hence we allocate a bounce buffer to map the HostAddress t= o a DeviceAddress. The Encryption attribute is removed from the DeviceAddress buffer. @@ -246,14 +252,29 @@ IoMmuMap ( goto FreeMapInfo; } =20 - // - // Clear the memory encryption mask on the plaintext buffer. - // - Status =3D MemEncryptSevClearPageEncMask ( - 0, - MapInfo->PlainTextAddress, - MapInfo->NumberOfPages - ); + if (mIoMmuType =3D=3D IO_MMU_SEV) { + // + // Clear the memory encryption mask on the plaintext buffer. + // + Status =3D MemEncryptSevClearPageEncMask ( + 0, + MapInfo->PlainTextAddress, + MapInfo->NumberOfPages + ); + } else if (mIoMmuType =3D=3D IO_MMU_TDX) { + // + // Set the memory shared bit. + // + Status =3D MemEncryptTdxSetPageSharedBit ( + 0, + MapInfo->PlainTextAddress, + MapInfo->NumberOfPages + ); + + } else { + ASSERT (FALSE); + } + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { CpuDeadLoop (); @@ -399,15 +420,30 @@ IoMmuUnmapWorker ( break; } =20 - // - // Restore the memory encryption mask on the area we used to hold the - // plaintext. - // - Status =3D MemEncryptSevSetPageEncMask ( - 0, - MapInfo->PlainTextAddress, - MapInfo->NumberOfPages - ); + if (mIoMmuType =3D=3D IO_MMU_SEV) { + // + // Restore the memory encryption mask on the area we used to hold the + // plaintext. + // + Status =3D MemEncryptSevSetPageEncMask ( + 0, + MapInfo->PlainTextAddress, + MapInfo->NumberOfPages + ); + } else if (mIoMmuType =3D=3D IO_MMU_TDX) { + // + // Restore the memory shared bit mask on the area we used to hold the + // plaintext. + // + Status =3D MemEncryptTdxClearPageSharedBit ( + 0, + MapInfo->PlainTextAddress, + MapInfo->NumberOfPages + ); + } else { + ASSERT (FALSE); + } + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { CpuDeadLoop (); @@ -731,7 +767,7 @@ IoMmuSetAttribute ( return EFI_UNSUPPORTED; } =20 -EDKII_IOMMU_PROTOCOL mAmdSev =3D { +EDKII_IOMMU_PROTOCOL mIoMmu =3D { EDKII_IOMMU_PROTOCOL_REVISION, IoMmuSetAttribute, IoMmuMap, @@ -763,7 +799,7 @@ EDKII_IOMMU_PROTOCOL mAmdSev =3D { STATIC VOID EFIAPI -AmdSevExitBoot ( +IoMmuExitBoot ( IN EFI_EVENT Event, IN VOID *EventToSignal ) @@ -771,11 +807,11 @@ AmdSevExitBoot ( // // (1) The NotifyFunctions of all the events in // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before - // AmdSevExitBoot() is entered. + // IoMmuExitBoot() is entered. // - // (2) AmdSevExitBoot() is executing minimally at TPL_CALLBACK. + // (2) IoMmuExitBoot() is executing minimally at TPL_CALLBACK. // - // (3) AmdSevExitBoot() has been queued in unspecified order relative to= the + // (3) IoMmuExitBoot() has been queued in unspecified order relative to = the // NotifyFunctions of all the other events in // EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as // Event's. @@ -783,13 +819,13 @@ AmdSevExitBoot ( // Consequences: // // - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctio= ns - // queued at TPL_CALLBACK may be invoked after AmdSevExitBoot() return= s. + // queued at TPL_CALLBACK may be invoked after IoMmuExitBoot() returns. // // - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions - // queued at TPL_NOTIFY may be invoked after AmdSevExitBoot() returns;= plus + // queued at TPL_NOTIFY may be invoked after IoMmuExitBoot() returns; = plus // *all* NotifyFunctions queued at TPL_CALLBACK will be invoked strict= ly // after all NotifyFunctions queued at TPL_NOTIFY, including - // AmdSevExitBoot(), have been invoked. + // IoMmuExitBoot(), have been invoked. // // - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we // queue EventToSignal's NotifyFunction after the NotifyFunctions of *= all* @@ -815,7 +851,7 @@ AmdSevExitBoot ( STATIC VOID EFIAPI -AmdSevUnmapAllMappings ( +IoMmuUnmapAllMappings ( IN EFI_EVENT Event, IN VOID *Context ) @@ -834,7 +870,7 @@ AmdSevUnmapAllMappings ( NextNode =3D GetNextNode (&mMapInfos, Node); MapInfo =3D CR (Node, MAP_INFO, Link, MAP_INFO_SIG); IoMmuUnmapWorker ( - &mAmdSev, // This + &mIoMmu, // This MapInfo, // Mapping TRUE // MemoryMapLocked ); @@ -847,7 +883,7 @@ AmdSevUnmapAllMappings ( **/ EFI_STATUS EFIAPI -AmdSevInstallIoMmuProtocol ( +InstallIoMmuProtocol ( VOID ) { @@ -863,7 +899,7 @@ AmdSevInstallIoMmuProtocol ( Status =3D gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, // Type TPL_CALLBACK, // NotifyTpl - AmdSevUnmapAllMappings, // NotifyFunction + IoMmuUnmapAllMappings, // NotifyFunction NULL, // NotifyContext &UnmapAllMappingsEvent // Event ); @@ -878,7 +914,7 @@ AmdSevInstallIoMmuProtocol ( Status =3D gBS->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type TPL_CALLBACK, // NotifyTpl - AmdSevExitBoot, // NotifyFunction + IoMmuExitBoot, // NotifyFunction UnmapAllMappingsEvent, // NotifyContext &ExitBootEvent // Event ); @@ -889,7 +925,7 @@ AmdSevInstallIoMmuProtocol ( Handle =3D NULL; Status =3D gBS->InstallMultipleProtocolInterfaces ( &Handle, - &gEdkiiIoMmuProtocolGuid, &mAmdSev, + &gEdkiiIoMmuProtocolGuid, &mIoMmu, NULL ); if (EFI_ERROR (Status)) { @@ -906,3 +942,31 @@ CloseUnmapAllMappingsEvent: =20 return Status; } + +/** + Initialize Iommu Protocol for Intel TDX. + +**/ +EFI_STATUS +EFIAPI +IntelTdxInstallIoMmuProtocol ( + VOID + ) +{ + mIoMmuType =3D IO_MMU_TDX; + return InstallIoMmuProtocol (); +} + +/** + Initialize Iommu Protocol for Intel TDX. + +**/ +EFI_STATUS +EFIAPI +AmdSevInstallIoMmuProtocol ( + VOID + ) +{ + mIoMmuType =3D IO_MMU_SEV; + return InstallIoMmuProtocol (); +} diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h index 8244f28b57fd..768d18028198 100644 --- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h +++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include =20 @@ -35,4 +36,15 @@ AmdSevInstallIoMmuProtocol ( VOID ); =20 +/** + Install IOMMU protocol to provide the DMA support for PciHostBridge and + MemEncryptSevLib. + +**/ +EFI_STATUS +EFIAPI +IntelTdxInstallIoMmuProtocol ( + VOID + ); + #endif diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c index 13df8ba874c5..698229b16bfa 100644 --- a/OvmfPkg/IoMmuDxe/IoMmuDxe.c +++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c @@ -22,11 +22,13 @@ IoMmuDxeEntryPoint ( EFI_HANDLE Handle; =20 // - // When SEV is enabled, install IoMmu protocol otherwise install the + // When SEV or TDX is enabled, install IoMmu protocol otherwise install = the // placeholder protocol so that other dependent module can run. // if (MemEncryptSevIsEnabled ()) { Status =3D AmdSevInstallIoMmuProtocol (); + } else if (MemEncryptTdxIsEnabled ()) { + Status =3D IntelTdxInstallIoMmuProtocol (); } else { Handle =3D NULL; =20 diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf index 2ebd74e5558c..52ad6f2efdb7 100644 --- a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf +++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf @@ -32,6 +32,7 @@ BaseMemoryLib DebugLib MemEncryptSevLib + MemEncryptTdxLib MemoryAllocationLib UefiBootServicesTableLib UefiDriverEntryPoint diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 2c4a6613b1ea..455e901c2eb8 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -180,6 +180,8 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLi= b.inf + MemEncryptTdxLib|OvmfPkg/Library/BaseMemEncryptTdxLib/BaseMemEncryptTdxL= ib.inf + !if $(SMM_REQUIRE) =3D=3D FALSE LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf !endif --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81499): https://edk2.groups.io/g/devel/message/81499 Mute This Topic: https://groups.io/mt/86085769/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Thu May 16 00:16:05 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+81500+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81500+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1633405273; cv=none; d=zohomail.com; s=zohoarc; b=Pt4xBrnZjay9UyX1p1PLiTczglnp0Q8632L0WtqJ805Op/iYyrIX/AzYga65f7dtLYVSvc6xbp55Uehcg82nqATZuqDcE8iWEerF+quPOPAbT2yyj37AzK8UT1fzYveEwEjIyJ2EREROszfKnTyjg1abPxN0YrEtUHyUHrBSNP4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633405273; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=6qqSXm/xxYyo6nlIKNYIC+PCGbx1jjbiIFU+tZjuQAo=; b=fcoD3VkPYFVch1uYyHtZ2+b9uYOA28QY88OYLBMl+bS6ceXDvRoGQACKrnWRJkW37eI+Pbm4co9Xvna25QyLbP6YLxTiMDaHmixc8lQsJ/XHDseQMZTTuCTqAjK5v26Sd1NK2U32e1MEYnFstkBDQ154aNExAqb1Gjp0DxwXLnQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+81500+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1633405273576995.9619612664086; Mon, 4 Oct 2021 20:41:13 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id BcgwYY1788612xSqkYXJpOKE; Mon, 04 Oct 2021 20:41:13 -0700 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web12.20766.1633405266346904661 for ; Mon, 04 Oct 2021 20:41:12 -0700 X-IronPort-AV: E=McAfee;i="6200,9189,10127"; a="225958320" X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="225958320" X-Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:12 -0700 X-IronPort-AV: E=Sophos;i="5.85,347,1624345200"; d="scan'208";a="487828911" X-Received: from mxu9-mobl1.ccr.corp.intel.com ([10.255.29.239]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Oct 2021 20:41:09 -0700 From: "Min Xu" To: devel@edk2.groups.io Cc: Min Xu , Ard Biesheuvel , Jordan Justen , Brijesh Singh , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: [edk2-devel] [PATCH V2 28/28] OvmfPkg: Add LocalApicTimerDxe Date: Tue, 5 Oct 2021 11:39:39 +0800 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,min.m.xu@intel.com X-Gm-Message-State: X9SrWgHK9rQwwYCMAC8WNpsZx1787277AA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1633405273; bh=TXdgqUg72oODGhhqqcFgtv/LriWXx/ZY8OvGQ7n5TcA=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=HpDwM+A2IKn4gRaqX8UfK//ZlBd1D5GrpRyEmNIkXaC4xUx4BO4a7oRfRZ1XbYY/Uqb lYe57Oe1TwIkzci1Hi5jBM7GCNe48Zj2vHXde9WQC9s7zlxfovQOxW16Uh0a6Kve0prAZ SQKiXsZR5NtFVYgepyZ0bVIHirXJUOUEuV4= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1633405275365100001 RFC=EF=BC=9A https://bugzilla.tianocore.org/show_bug.cgi?id=3D3429 TDX guest supports LocalApicTimer. But in current OvmfPkg the supported timer is 8254TimerDxe. So gUefiOvmfPkgTokenSpaceGuid.PcdTimerSelector is introduced to select the running Timer. The Timer driver will check the TimerSelector in its entry point. The default Timer is 8254. TimerSelector will be set to LocalApicTimer by TdxDxe driver in Tdx guest. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Brijesh Singh Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu --- OvmfPkg/8254TimerDxe/8254Timer.inf | 3 + OvmfPkg/8254TimerDxe/Timer.c | 5 + OvmfPkg/8254TimerDxe/Timer.h | 1 + OvmfPkg/8259InterruptControllerDxe/8259.c | 1 + OvmfPkg/8259InterruptControllerDxe/8259.inf | 1 + OvmfPkg/Include/Protocol/TimerSelector.h | 16 + OvmfPkg/LocalApicTimerDxe/LocalApicTimer.c | 488 ++++++++++++++++++ .../LocalApicTimerDxe/LocalApicTimerDxe.inf | 52 ++ .../LocalApicTimerDxe/LocalApicTimerDxe.uni | 13 + OvmfPkg/OvmfPkg.dec | 14 + OvmfPkg/OvmfPkgX64.dsc | 4 + OvmfPkg/OvmfPkgX64.fdf | 1 + OvmfPkg/TdxDxe/TdxDxe.c | 3 + OvmfPkg/TdxDxe/TdxDxe.inf | 1 + 14 files changed, 603 insertions(+) create mode 100644 OvmfPkg/Include/Protocol/TimerSelector.h create mode 100644 OvmfPkg/LocalApicTimerDxe/LocalApicTimer.c create mode 100644 OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf create mode 100644 OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.uni diff --git a/OvmfPkg/8254TimerDxe/8254Timer.inf b/OvmfPkg/8254TimerDxe/8254= Timer.inf index 8a07c8247ebe..f15792106944 100644 --- a/OvmfPkg/8254TimerDxe/8254Timer.inf +++ b/OvmfPkg/8254TimerDxe/8254Timer.inf @@ -36,6 +36,9 @@ gEfiLegacy8259ProtocolGuid ## CONSUMES gEfiTimerArchProtocolGuid ## PRODUCES =20 +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdTimerSelector + [Depex] gEfiCpuArchProtocolGuid AND gEfiLegacy8259ProtocolGuid [UserExtensions.TianoCore."ExtraFiles"] diff --git a/OvmfPkg/8254TimerDxe/Timer.c b/OvmfPkg/8254TimerDxe/Timer.c index fd1691beb3c7..b8d29acebf39 100644 --- a/OvmfPkg/8254TimerDxe/Timer.c +++ b/OvmfPkg/8254TimerDxe/Timer.c @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ =20 #include "Timer.h" +#include =20 // // The handle onto which the Timer Architectural Protocol will be installed @@ -340,6 +341,10 @@ TimerDriverInitialize ( EFI_STATUS Status; UINT32 TimerVector; =20 + if (PcdGet32 (PcdTimerSelector) !=3D TimerSelector8254) { + return EFI_UNSUPPORTED; + } + // // Initialize the pointer to our notify function. // diff --git a/OvmfPkg/8254TimerDxe/Timer.h b/OvmfPkg/8254TimerDxe/Timer.h index 4c4b720d50dd..2beb7901fefd 100644 --- a/OvmfPkg/8254TimerDxe/Timer.h +++ b/OvmfPkg/8254TimerDxe/Timer.h @@ -13,6 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include =20 #include #include diff --git a/OvmfPkg/8259InterruptControllerDxe/8259.c b/OvmfPkg/8259Interr= uptControllerDxe/8259.c index 1c2ac1039d40..eb69302cc12e 100644 --- a/OvmfPkg/8259InterruptControllerDxe/8259.c +++ b/OvmfPkg/8259InterruptControllerDxe/8259.c @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ =20 #include "8259.h" +#include =20 // // Global for the Legacy 8259 Protocol that is produced by this driver diff --git a/OvmfPkg/8259InterruptControllerDxe/8259.inf b/OvmfPkg/8259Inte= rruptControllerDxe/8259.inf index 7320ff2490a7..fcd245720060 100644 --- a/OvmfPkg/8259InterruptControllerDxe/8259.inf +++ b/OvmfPkg/8259InterruptControllerDxe/8259.inf @@ -22,6 +22,7 @@ [Packages] MdePkg/MdePkg.dec OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec =20 [LibraryClasses] UefiBootServicesTableLib diff --git a/OvmfPkg/Include/Protocol/TimerSelector.h b/OvmfPkg/Include/Pro= tocol/TimerSelector.h new file mode 100644 index 000000000000..b062ab94706e --- /dev/null +++ b/OvmfPkg/Include/Protocol/TimerSelector.h @@ -0,0 +1,16 @@ +/** @file + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef TIMER_SELECTOR_H_ +#define TIMER_SELECTOR_H_ + +typedef enum { + TimerSelector8254, + TimerSelectorLocalApic, +} TIMER_SELECTOR; + +#endif diff --git a/OvmfPkg/LocalApicTimerDxe/LocalApicTimer.c b/OvmfPkg/LocalApic= TimerDxe/LocalApicTimer.c new file mode 100644 index 000000000000..fafb01ec841b --- /dev/null +++ b/OvmfPkg/LocalApicTimerDxe/LocalApicTimer.c @@ -0,0 +1,488 @@ +/** @file + Timer Architectural Protocol module using Local APIC Timer + + Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/** + This function registers the handler NotifyFunction so it is called every= time + the timer interrupt fires. It also passes the amount of time since the = last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS= is + returned. If the CPU does not support registering a timer interrupt han= dler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a h= andler + when a handler is already registered, then EFI_ALREADY_STARTED is return= ed. + If an attempt is made to unregister a handler when a handler is not regi= stered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ER= ROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fire= s. + This function executes at TPL_HIGH_LEVEL. The D= XE + Core will register a handler for the timer inter= rupt, + so it can know how much time has passed. This + information is used to signal timer based events. + NULL will unregister the handler. + + @retval EFI_SUCCESS The timer handler was registered. + @retval EFI_UNSUPPORTED The platform does not support timer inte= rrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handle= r is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler wa= s not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be registere= d. + +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ); + +/** + This function adjusts the period of timer interrupts to the value specif= ied + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + interrupt fires. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS u= nits. + If the timer hardware is not programmable, then + EFI_UNSUPPORTED is returned. If the timer is progr= ammable, + then the timer period will be rounded up to the nea= rest + timer period that is supported by the timer hardwar= e. + If TimerPeriod is set to 0, then the timer interrup= ts + will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period of the = timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed due to = a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ); + +/** + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is + returned, then the timer is currently disabled. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns= units. + If 0 is returned, then the timer is currently disab= led. + + @retval EFI_SUCCESS The timer period was returned in TimerPe= riod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ); + +/** + This function generates a soft timer interrupt. If the platform does not= support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler() + service, then a soft timer interrupt will be generated. If the timer int= errupt is + enabled when this service is called, then the registered handler will be= invoked. The + registered handler should not be able to distinguish a hardware-generate= d timer + interrupt from a software-generated timer interrupt. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation = of soft + timer interrupts. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ); + +/// +/// The handle onto which the Timer Architectural Protocol will be install= ed. +/// +EFI_HANDLE mTimerHandle =3D NULL; + +/// +/// The Timer Architectural Protocol that this driver produces. +/// +EFI_TIMER_ARCH_PROTOCOL mTimer =3D { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +/// +/// Pointer to the CPU Architectural Protocol instance. +/// +EFI_CPU_ARCH_PROTOCOL *mCpu =3D NULL; + +/// +/// The notification function to call on every timer interrupt. +/// +EFI_TIMER_NOTIFY mTimerNotifyFunction =3D NULL; + +/// +/// The current period of the Local APIC timer interrupt in 100 ns units. +/// +UINT64 mTimerPeriod =3D 0; + +/// +/// Counts the number of Local APIC Timer interrupts processed by this dri= ver. +/// Only required for debug. +/// +volatile UINTN mNumTicks; + +/** + The interrupt handler for the Local APIC timer. This handler clears the= Local + APIC interrupt and computes the amount of time that has passed since the= last + Local APIC timer interrupt. If a notification function is registered, t= hen + the amount of time since the last Local APIC timer interrupt is passed t= o that + notification function in 100 ns units. The Local APIC timer is updated = to + generate another interrupt in the required time period. + + @param InterruptType The type of interrupt that occurred. + @param SystemContext A pointer to the system context when the interrup= t occurred. +**/ +VOID +EFIAPI +TimerInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + + EFI_TPL OriginalTPL; + + OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + // + // Count number of ticks + // + DEBUG_CODE (mNumTicks++;); + + // + // Check to see if there is a registered notification function + // + if (mTimerNotifyFunction !=3D NULL) { + mTimerNotifyFunction (mTimerPeriod); + } + + gBS->RestoreTPL (OriginalTPL); + + DisableInterrupts (); + + SendApicEoi(); +} + +/** + This function registers the handler NotifyFunction so it is called every= time + the timer interrupt fires. It also passes the amount of time since the = last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS= is + returned. If the CPU does not support registering a timer interrupt han= dler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a h= andler + when a handler is already registered, then EFI_ALREADY_STARTED is return= ed. + If an attempt is made to unregister a handler when a handler is not regi= stered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ER= ROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param NotifyFunction The function to call when a timer interrupt fire= s. + This function executes at TPL_HIGH_LEVEL. The D= XE + Core will register a handler for the timer inter= rupt, + so it can know how much time has passed. This + information is used to signal timer based events. + NULL will unregister the handler. + + @retval EFI_SUCCESS The timer handler was registered. + @retval EFI_UNSUPPORTED The platform does not support timer inte= rrupts. + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handle= r is already + registered. + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler wa= s not + previously registered. + @retval EFI_DEVICE_ERROR The timer handler could not be registere= d. + +**/ +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + // + // Check for invalid parameters + // + if (NotifyFunction =3D=3D NULL && mTimerNotifyFunction =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + if (NotifyFunction !=3D NULL && mTimerNotifyFunction !=3D NULL) { + return EFI_ALREADY_STARTED; + } + + // + // Cache the registered notification function + // + mTimerNotifyFunction =3D NotifyFunction; + + return EFI_SUCCESS; +} + +/** + This function adjusts the period of timer interrupts to the value specif= ied + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. = If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer inter= rupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust t= he + interrupt controller so that a CPU interrupt is not generated when the t= imer + interrupt fires. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod The rate to program the timer interrupt in 100 nS u= nits. + If the timer hardware is not programmable, then + EFI_UNSUPPORTED is returned. If the timer is progr= ammable, + then the timer period will be rounded up to the nea= rest + timer period that is supported by the timer hardwar= e. + If TimerPeriod is set to 0, then the timer interrup= ts + will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + @retval EFI_UNSUPPORTED The platform cannot change the period of the = timer interrupt. + @retval EFI_DEVICE_ERROR The timer period could not be changed due to = a device error. + +**/ +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + EFI_TPL Tpl; + UINTN Divisor; + UINT64 TimerCount; + + // + // Disable interrupts + // + Tpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (TimerPeriod =3D=3D 0) { + // + // Disable timer interrupt for a TimerPeriod of 0 + // + DisableApicTimerInterrupt (); + } else { + DisableApicTimerInterrupt (); + + // + // Convert TimerPeriod in 100ns units to Local APIC Timer ticks. + // + GetApicTimerState (&Divisor, NULL, NULL); + TimerCount =3D DivU64x32 ( + MultU64x32 (TimerPeriod, PcdGet32(PcdFSBClock)), + (UINT32)Divisor * 10000000 + ); + + // + // Program the local APIC timer + // + InitializeApicTimer (0, (UINT32)TimerCount, TRUE, PcdGet8 (PcdHpetLoca= lApicVector)); + + EnableApicTimerInterrupt (); + } + + // + // Save the new timer period + // + mTimerPeriod =3D TimerPeriod; + + // + // Restore interrupts + // + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +/** + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPer= iod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 = is + returned, then the timer is currently disabled. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns= units. + If 0 is returned, then the timer is currently disab= led. + + @retval EFI_SUCCESS The timer period was returned in TimerPe= riod. + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +{ + if (TimerPeriod =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod =3D mTimerPeriod; + + return EFI_SUCCESS; +} + +/** + This function generates a soft timer interrupt. If the platform does not= support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCE= SS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.Reg= isterHandler() + service, then a soft timer interrupt will be generated. If the timer int= errupt is + enabled when this service is called, then the registered handler will be= invoked. The + registered handler should not be able to distinguish a hardware-generate= d timer + interrupt from a software-generated timer interrupt. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + @retval EFI_UNSUPPORTED The platform does not support the generation = of soft + timer interrupts. + +**/ +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Initialize the Timer Architectural Protocol driver + + @param ImageHandle ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Timer Architectural Protocol created + @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial= ize driver. + @retval EFI_DEVICE_ERROR A device error occurred attempting to ini= tialize the driver. + +**/ +EFI_STATUS +EFIAPI +TimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (PcdGet32 (PcdTimerSelector) !=3D TimerSelectorLocalApic) { + return EFI_UNSUPPORTED; + } + + // + // Make sure the Timer Architectural Protocol is not already installed i= n the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid); + + // + // Find the CPU architectural protocol. + // + Status =3D gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **= ) &mCpu); + ASSERT_EFI_ERROR (Status); + + // + // Install interrupt handler for the Local APIC Timer + // + Status =3D mCpu->RegisterInterruptHandler (mCpu, PcdGet8 (PcdHpetLocalAp= icVector), TimerInterruptHandler); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to register Local APIC interrupt with CPU= Arch Protocol. Unload Local APIC timer driver.\n")); + return EFI_DEVICE_ERROR; + } + + // + // Force the Local APIC timer to be disabled while setting everything up + // + DisableApicTimerInterrupt (); + InitializeApicTimer (0, 0, FALSE, PcdGet8 (PcdHpetLocalApicVector)); + + // + // Force the Local APIC Timer to be enabled at its default period + // + Status =3D TimerDriverSetTimerPeriod (&mTimer, PcdGet64 (PcdHpetDefaultT= imerPeriod)); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to set Local APIC default timer rate. Un= load Local APIC timer driver.\n")); + return EFI_DEVICE_ERROR; + } + + // + // Show state of enabled timer + // + DEBUG_CODE ( + // + // Wait for a few timer interrupts to fire before continuing + // + while (mNumTicks < 10); + ); + + // + // Install the Timer Architectural Protocol onto a new handle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mTimerHandle, + &gEfiTimerArchProtocolGuid, &mTimer, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf b/OvmfPkg/Loca= lApicTimerDxe/LocalApicTimerDxe.inf new file mode 100644 index 000000000000..70bc0ef6b2ea --- /dev/null +++ b/OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf @@ -0,0 +1,52 @@ +## @file +# Timer Architectural Protocol module using Local APIC Timer +# +# Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D LocalApicTimerDxe + MODULE_UNI_FILE =3D LocalApicTimerDxe.uni + FILE_GUID =3D 74EB4D00-E63E-11EA-8B6E-0800200C9A66 + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D TimerDriverInitialize + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 +# +# + +[Sources] + LocalApicTimer.c + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + PcdLib + DebugLib + UefiDriverEntryPoint + UefiBootServicesTableLib + BaseLib + LocalApicLib + +[Protocols] + gEfiTimerArchProtocolGuid ## PRODUCES + gEfiCpuArchProtocolGuid ## CONSUMES + +[Pcd] + gUefiOvmfPkgTokenSpaceGuid.PcdHpetLocalApicVector ## CONSUMES + gUefiOvmfPkgTokenSpaceGuid.PcdHpetDefaultTimerPeriod ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFSBClock + gUefiOvmfPkgTokenSpaceGuid.PcdTimerSelector + +[Depex] + gEfiCpuArchProtocolGuid diff --git a/OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.uni b/OvmfPkg/Loca= lApicTimerDxe/LocalApicTimerDxe.uni new file mode 100644 index 000000000000..7525d9493858 --- /dev/null +++ b/OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.uni @@ -0,0 +1,13 @@ +// /** @file +// Timer Architectural Protocol module using Local APIC Timer +// +// Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Timer Architectur= al Protocol module using Local APIC Timer" + +#string STR_MODULE_DESCRIPTION #language en-US "Timer Architectur= al Protocol module using Local APIC Timer." diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index dda83d81695b..56714d3311ad 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -369,6 +369,15 @@ ## The Tdx accept page size. 0x1000(4k),0x200000(2M) gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize|0x1000|UINT64|0x5a =20 + ## This PCD specifies the Local APIC Interrupt Vector for the HPET Timer. + # @Prompt HPET local APIC vector. + gUefiOvmfPkgTokenSpaceGuid.PcdHpetLocalApicVector|0x40|UINT8|0x5b + + ## This PCD specifies the default period of the HPET Timer in 100 ns uni= ts. + # The default value of 100000 100 ns units is the same as 10 ms. + # @Prompt Default period of HPET timer. + gUefiOvmfPkgTokenSpaceGuid.PcdHpetDefaultTimerPeriod|100000|UINT64|0x5c + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 @@ -411,6 +420,11 @@ ## TDX relocated Mailbox base address gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase|0|UINT64|0x60 =20 + ## Timer selector + # There are multiple timer in Ovmf. This PCD indicates which Timer is i= nstalled. + # The default Timer is 8254 (0x0). See TimerSelector.h for more definit= ion. + gUefiOvmfPkgTokenSpaceGuid.PcdTimerSelector|0|UINT32|0x61 + [PcdsFeatureFlag] gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0= x1c gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN= |0x1d diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 455e901c2eb8..a17d6603af0b 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -777,6 +777,10 @@ OvmfPkg/8259InterruptControllerDxe/8259.inf UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf UefiCpuPkg/CpuDxe/CpuDxe.inf + OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf { + + LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLi= b.inf + } OvmfPkg/8254TimerDxe/8254Timer.inf OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index bbd9303ab14f..716297e52aff 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -236,6 +236,7 @@ INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf INF OvmfPkg/8259InterruptControllerDxe/8259.inf INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf INF UefiCpuPkg/CpuDxe/CpuDxe.inf +INF OvmfPkg/LocalApicTimerDxe/LocalApicTimerDxe.inf INF OvmfPkg/8254TimerDxe/8254Timer.inf INF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.= inf INF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf diff --git a/OvmfPkg/TdxDxe/TdxDxe.c b/OvmfPkg/TdxDxe/TdxDxe.c index eecad8f6e050..fcfb972cc67c 100644 --- a/OvmfPkg/TdxDxe/TdxDxe.c +++ b/OvmfPkg/TdxDxe/TdxDxe.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -131,6 +132,8 @@ TdxDxeEntryPoint ( return EFI_UNSUPPORTED; } =20 + PcdSet32S (PcdTimerSelector, TimerSelectorLocalApic); + PlatformInfo =3D (EFI_HOB_PLATFORM_INFO *) GET_GUID_HOB_DATA (GuidHob); =20 // diff --git a/OvmfPkg/TdxDxe/TdxDxe.inf b/OvmfPkg/TdxDxe/TdxDxe.inf index b77c6e5e9252..045c3c8c2ccc 100644 --- a/OvmfPkg/TdxDxe/TdxDxe.inf +++ b/OvmfPkg/TdxDxe/TdxDxe.inf @@ -60,3 +60,4 @@ gUefiOvmfPkgTokenSpaceGuid.PcdTdRelocatedMailboxBase gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress + gUefiOvmfPkgTokenSpaceGuid.PcdTimerSelector --=20 2.29.2.windows.2 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#81500): https://edk2.groups.io/g/devel/message/81500 Mute This Topic: https://groups.io/mt/86085771/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-