From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM04-DM6-obe.outbound.protection.outlook.com (NAM04-DM6-obe.outbound.protection.outlook.com [40.107.102.56]) by mx.groups.io with SMTP id smtpd.web12.23.1627383405888640191 for ; Tue, 27 Jul 2021 03:56:46 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@amd.com header.s=selector1 header.b=UU9cHx2o; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.102.56, mailfrom: brijesh.singh@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ervqled0XmNiY5xl9BfYVvQ8jQ9Xj5g+YRdmx9AaroyWLS98GhJSLQIgtjTM1gUFpLwq/Cou6gfTkp9ZAGIh4MIEWaEkFDekMRRtDPtXs3LuO3j6izb0KlxPTEv52LlDDnBpq8STbBHXMyxPfy8Yy3bn4PZf6BaanA+vHfL6gnkwlMTTqRKw1VfdNvFPbj1dh46zbsAo+gRSA0MJkz3lR7Jtp7BOv0R9i4fDNxoBKNZVZ5Q004qHG2yLkrDTsxN48z1Hel6cOR9eJBZir7SGIednewcBYMrDtpkaVWKAAXwBssDoxDTGnGO9g+BwG0hOExgS/neHnUycewr6p2NMPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Eu6Ts0u/tdALrk0nlOz+3wqATZg+TTHA7uxQHRWr+qY=; b=ionU0QqvALGOojfJRA7oxWu3WruGb4I7KKR77V5+bfJe9lu8wBj4Oc1+ETCZDExAUhWr2dhVXe8hvp0j4EWhneSuIst5J7Rf1C6HpCZXyYw2jhLnuRn9SvVrJI+lDIQLcGlm7ogvZ4bx8ekC3kCxhEaVvRRBaZh4WaYk/b21pkTS5YYqeJSyzVEBL9gtz5z5eoGokh1cAwSLN45MYNhMk0VWbLW/BZPRk5Uxq18dQsDFrx6ZKUY2mG/Eh6ebwJr4Ra+i/3UeiEDY9J5w5n/BIYXNBq9Qm0y55Pst+prTv85se1owHtQBDpTpazemd+4P+EK42fLw6+DNNCejaCX1kg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Eu6Ts0u/tdALrk0nlOz+3wqATZg+TTHA7uxQHRWr+qY=; b=UU9cHx2oP8JGFkzJxcSOyApgSt4gXGd0A3EVvah4D9FxhpBMGuaG+Sv8RWq1rm5jkrXl6XxkJjEcRlitjr79KQNFkEcC83L0k6gYniEIu1RJh27RrkYDxwqAh3HRKeI3VIdMWD2+By0vTkRPuljqQuQRMuVawJoL7raVEowuczw= Authentication-Results: amd.com; dkim=none (message not signed) header.d=none;amd.com; dmarc=none action=none header.from=amd.com; Received: from SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) by SA0PR12MB4384.namprd12.prod.outlook.com (2603:10b6:806:9f::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4352.25; Tue, 27 Jul 2021 10:56:42 +0000 Received: from SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::a8a9:2aac:4fd1:88fa]) by SN6PR12MB2718.namprd12.prod.outlook.com ([fe80::a8a9:2aac:4fd1:88fa%3]) with mapi id 15.20.4352.031; Tue, 27 Jul 2021 10:56:42 +0000 Cc: brijesh.singh@amd.com, Ard Biesheuvel , Jordan Justen , Erdem Aktas , James Bottomley , Jiewen Yao , Tom Lendacky Subject: Re: [PATCH V3 06/10] OvmfPkg: Add AmdSev.asm in ResetVector To: Min Xu , devel@edk2.groups.io References: From: "Brijesh Singh" Message-ID: Date: Tue, 27 Jul 2021 05:56:35 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.12.0 In-Reply-To: X-ClientProxiedBy: SN1PR12CA0069.namprd12.prod.outlook.com (2603:10b6:802:20::40) To SN6PR12MB2718.namprd12.prod.outlook.com (2603:10b6:805:6f::22) Return-Path: brijesh.singh@amd.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from Brijeshs-MacBook-Pro.local (165.204.77.11) by SN1PR12CA0069.namprd12.prod.outlook.com (2603:10b6:802:20::40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4373.18 via Frontend Transport; Tue, 27 Jul 2021 10:56:37 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5611dbe0-35fe-4d9b-9aab-08d950ed37fa X-MS-TrafficTypeDiagnostic: SA0PR12MB4384: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5236; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dBzCnXD4dESoCw2Sje6phCTIvugITIGDypaiqWbCfFG5Hni5+cj7LdjDC+fCZqG5F4Zk8HDk+I+0Dk1lHMf8OAh77IBez+UKz5EkI75pBgQmb8bv3af1smbFQTnJ18F7K1t3ETiGIxt83rKdVIzhkBB5d6KgsI6XH0qnauoVHo7MjZXDXMuGxLHCSmcZBMzvSo+T0Ayib4v/2olmTevToo4wnYBdorQKvwccKoZ4C5BgIWzpPM32knNmyyxbmE6q+tvi3IrvdIc4N2wp68EeQMgLlG6oMzvWvxSJ+1SdCubHCJ+HNWFCT1WjIJbaEbZHtEZKah0Ny67jra6UlqDqWNFQzXMeUHaQJxKu0SQLbnWG3YipgOhxktoWUNpx24t8LrQTIzd/Tjj7zcOvQe4CBairqQh9fTZ0KmBAc/Nm2Z9dRvrZjmeDRyI8catGCT9V4fMfer1pUD9bHjvSeTCC//jmrXAq/c1nGpeEGMbOnv52xaKeGssnJL9C+W/mZJwsy15LdOAP88e7yoC5xsmMnNfBuqJZ3k1lda3uzfeK/krQEntlzfXG7iTxX9WVcucV1ipKtl7o8OLcPhX/UkbptC17Yxwav1RyCDTPSF8iDReuAjb8B9I8bcCNs7rKOxrA2kCFJ5xUr9CRDDlcq7TUhNbvKNOeI3AWXWCThxJiHeUevjL4Mv+F43+W1/z6N2aS6EMXoXkbBh8fdCGlv9858iR/e0fzAQfjSD0ltMGLTnmdj8fO/TFrZLDBpxEoJPe+zCMhuJTfw6XitfMX5HeumD3Y1VAK/qPZGl6RmMHX2WCclPFE6NJrQNYsio0ZF01EcUCkhI30Cix4IwzW37VmDlbirSNGtbgWOVFZGw2q+rU= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SN6PR12MB2718.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(346002)(366004)(39860400002)(396003)(136003)(2616005)(31686004)(6512007)(53546011)(478600001)(4326008)(36756003)(38100700002)(30864003)(31696002)(52116002)(6506007)(2906002)(186003)(966005)(8936002)(956004)(86362001)(83380400001)(316002)(38350700002)(6486002)(66946007)(44832011)(54906003)(19627235002)(8676002)(26005)(5660300002)(66556008)(66476007)(45980500001)(43740500002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?cGRSWjhqc2RnRVpIdm1CMjAvN2pjQWxCS0JnN3RBbHI5YXhheERMVk94MnFk?= =?utf-8?B?aGVhRDBaQ0NnMmxSVjNPekZlYTFwUHhQTmtGYTNSOEpEM0RWYVBQam5NVjN4?= =?utf-8?B?T0dUOHNPd0lDRGRPWDVBT2plNXNJSWxUcGNONFJNR0NvTjRQYUV5VC9hRWwz?= =?utf-8?B?WlNIZHB5NGM4SzQ2Skc1MFBQSkplU2taNFlSUTBTWlY2ZmUvbUExejNiZm4r?= =?utf-8?B?QVNuSk9YWm5tOEpWcFZtV3JZQ2JYVmR3aklRUnlXWHVhQ2E4Y1ZtWjJPck5I?= =?utf-8?B?MDlOSW54aUFqT0g5dGgxL3pPa1hhU0xZVjFLbXRONkd3MnBTVDNtdUxOcXo5?= =?utf-8?B?NTJKU3JBVEVRS1FPN2xOS0U1TG9weHdpdEo4d3lTQ25FNHJrL1N2N0NKZVdF?= =?utf-8?B?TWVNTDgvbFIyZWVIdFdQOGM2RlRIZUNHd3B2YldUZWpuTXhtdi9jTmxqQzM5?= =?utf-8?B?emdRNEVES1QwSEdaT1FLeUtSalZlZmY4MlQzNU9Lb0l2QzJLYUp5ZVpTRGpl?= =?utf-8?B?K1U2Y2lIL3doaDZHVTdSakVMMGx6Vno3ZzFSOUpPMzd3dFF6K05jT1M3TXAr?= =?utf-8?B?MVVoUk5BOHdkZ3FNTjFDTDR6cnJYY0dZTmJRM2wzcGN2RFAvbUgwb0ZtM3lE?= =?utf-8?B?VjVoVXlKVWV5Nk52OWUyeEF5aUw3ZWx1VnJVWlFFM2EvQ0hRckVyYVlpd1Bs?= =?utf-8?B?R1hLSW8wSTRvazNTTWQ2V1FDNVEzWVFVc3FlWE1odXhudDd3T3h2Y1NGb1Ur?= =?utf-8?B?ZlhOWjdqY0RvN0pJQy9aYzM3c1RnTWlaTVBqbHVBUGNFa2V5QUx4RGMwWkNT?= =?utf-8?B?WDArdHh0d05PdkRyTWlBenN5MFl0cWh2bm1hNTV5N1NscUlkQnUyaXcyV2R3?= =?utf-8?B?VEVDM2dmcDNQS2ZkRi9KL1BpeHN6MVZabXhUUDlGa0VKR2cyTm5jOVFySU9F?= =?utf-8?B?L3ozSnNlVmYvNEt1VmxvWmFGekQ3bHc5WDRaUmRmYUUvdlNHaW5Lc3BzWVBM?= =?utf-8?B?c0VMOU1Ic1RRYkdxSVJGdFRRWW1MM3hNMVVKWTBoZW8yeXliRnQyb3FBdG9R?= =?utf-8?B?QmdSNDRlVEVVYlViRklJZmJMTHRkeE5PRTVVbDdhSER6S241N0lDOENIM09o?= =?utf-8?B?SlNXMjBuM3JXWXBNU1IzakVCaXNhZ1FldGZYQldNYVN5d2JyV05JejkzS2x6?= =?utf-8?B?NkU0K3V3M3lPb1ZrRWJHaHBuSGo2dUFOZ2NzeW5PUEozSk1HRGI5R21LQUtD?= =?utf-8?B?b2czdW9pWVN3S0djOTVxdlRaUnFXVmdLVllhU1ZueDdleWxJMlg5R2drMnlv?= =?utf-8?B?Uzd3VDJUcXRqbCtYdjNkVEY4YUgzYTdGSnFyeXhPell1b1NveTFQcXV3a3lI?= =?utf-8?B?dTREemlhYUtyM1Z4akFqOTNjSjIwUXdsY0hSRE51dnBmTjRxVEhveitubjVk?= =?utf-8?B?RmZEUVh2WVhUQTZKYVV1M0ZoV0lzaktKTW11MDdUenpXRlhjSVFyeTc4UUl1?= =?utf-8?B?Q240WnJDYzZldGhNREVZTmI1WUJGUjlCaWx2eTg5S0JXUWUvVTRLZ3I1VW03?= =?utf-8?B?Tm0yT0Fsc2d3RFBMVGpMSm9HNVdobDM5RFdHSzBIbjhSN0RBbGl4MzNLSVEx?= =?utf-8?B?UGlWdmNadm1KcUdTd2lvdmk1ME1DbEtUSVNyUzhuMGlnRWJJU0lQa0FQSEps?= =?utf-8?B?RkQwSkVBdG9ORzNWejVONTdJZmFIb1VUakUvOEEzZXRKWkN6N2FrdG9YSWhv?= =?utf-8?Q?xf6hHGewigpw1PAmvwy60bAcMFvmvDx4WLDcscA?= X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5611dbe0-35fe-4d9b-9aab-08d950ed37fa X-MS-Exchange-CrossTenant-AuthSource: SN6PR12MB2718.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jul 2021 10:56:42.8466 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: q1MW5CieM4FwKY6Xqc8HVcWWdG85omORohQwKQQSeLiGFYQwXGnTUqhY03/G2hAj+rFqEq0xkgmCzD5eXwUZBg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA0PR12MB4384 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-Language: en-US Hi Min, This refactoring is already done by the SNP patch series. https://edk2.groups.io/g/devel/message/77336?p=,,,20,0,0,0::Created,,posterid%3A5969970,20,2,20,83891510 It appears that you are also pulling in some of TDX logic inside the AMDSev.asm such as ; +PostJump64BitAndLandHereSev: + + ; + ; If it is Tdx guest, jump to exit point directly. + ; This is because following code may access the memory region which has + ; not been accepted. It is not allowed in Tdx guests. + ; + mov eax, dword[TDX_WORK_AREA] + cmp eax, 0x47584454 ; 'TDXG' + jz GoodCompare Why we are referring the TDX workarea inside the AmdSev.asm ? I will take out my refactoring patch outside of the SNP series and submit it so that you can build on top of. This will simplify review process. thanks On 7/27/21 12:42 AM, Min Xu wrote: > RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429 > > AmdSev.asm includes below routines: > - CheckSevFeatures > Check if Secure Encrypted Virtualization (SEV) features are enabled. > - PreSetCr3ForPageTables64Sev > It is called before SetCr3ForPageTables64 in SEV guests. > - PostSetCr3PageTables64Sev > It is called after SetCr3PageTables64 in SEV guests. > - PostJump64BitAndLandHereSev > It is called after Jump64BitAndLandHere in SEV guests. > - #VC exception handling routines > > These routines are extracted from PageTables64.asm and Flat32ToFlat64.asm > Need AMD engineers' help to review/validate the patch so that there is > no regression. Thanks in advance! > > Note: > In above Pre/Post routines, dword[TDX_WORK_AREA] should be checked > to see if it is 'TDXG' (Tdx guests). This is because some memory region > for example, byte[SEV_ES_WORK_AREA] cannot be accessed in Tdx guests. > Tdx requires that any memory region to be accessed should be accepted > first or initialized by host VMM before Td guest is launched. > > 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/ResetVector/Ia32/AmdSev.asm | 526 ++++++++++++++++++++++++++++ > 1 file changed, 526 insertions(+) > create mode 100644 OvmfPkg/ResetVector/Ia32/AmdSev.asm > > diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm > new file mode 100644 > index 000000000000..962b7e169c61 > --- /dev/null > +++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm > @@ -0,0 +1,526 @@ > +;------------------------------------------------------------------------------ > +; @file > +; AMD SEV routines > +; > +; Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
> +; Copyright (c) 2021, Intel Corporation. All rights reserved.
> +; > +; SPDX-License-Identifier: BSD-2-Clause-Patent > +; > +;------------------------------------------------------------------------------ > + > + > +BITS 32 > +; > +; SEV-ES #VC exception handler support > +; > +; #VC handler local variable locations > +; > +%define VC_CPUID_RESULT_EAX 0 > +%define VC_CPUID_RESULT_EBX 4 > +%define VC_CPUID_RESULT_ECX 8 > +%define VC_CPUID_RESULT_EDX 12 > +%define VC_GHCB_MSR_EDX 16 > +%define VC_GHCB_MSR_EAX 20 > +%define VC_CPUID_REQUEST_REGISTER 24 > +%define VC_CPUID_FUNCTION 28 > + > +; #VC handler total local variable size > +; > +%define VC_VARIABLE_SIZE 32 > + > +; #VC handler GHCB CPUID request/response protocol values > +; > +%define GHCB_CPUID_REQUEST 4 > +%define GHCB_CPUID_RESPONSE 5 > +%define GHCB_CPUID_REGISTER_SHIFT 30 > +%define CPUID_INSN_LEN 2 > + > +; > +; Check if Secure Encrypted Virtualization (SEV) features are enabled. > +; > +; Register usage is tight in this routine, so multiple calls for the > +; same CPUID and MSR data are performed to keep things simple. > +; > +; Modified: EAX, EBX, ECX, EDX, ESP > +; > +; If SEV is enabled then EAX will be at least 32. > +; If SEV is disabled then EAX will be zero. > +; > +CheckSevFeatures: > + ; Set the first byte of the workarea to zero to communicate to the SEC > + ; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID > + ; instruction will trigger a #VC exception where the first byte of the > + ; workarea will be set to one or, if CPUID is not being intercepted, > + ; the MSR check below will set the first byte of the workarea to one. > + mov byte[SEV_ES_WORK_AREA], 0 > + > + ; > + ; Set up exception handlers to check for SEV-ES > + ; Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for > + ; stack usage) > + ; Establish exception handlers > + ; > + mov esp, SEV_ES_VC_TOP_OF_STACK > + mov eax, ADDR_OF(Idtr) > + lidt [cs:eax] > + > + ; Check if we have a valid (0x8000_001F) CPUID leaf > + ; CPUID raises a #VC exception if running as an SEV-ES guest > + mov eax, 0x80000000 > + cpuid > + > + ; This check should fail on Intel or Non SEV AMD CPUs. In future if > + ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact > + ; same bit definition. > + cmp eax, 0x8000001f > + jl NoSev > + > + ; Check for SEV memory encryption feature: > + ; CPUID Fn8000_001F[EAX] - Bit 1 > + ; CPUID raises a #VC exception if running as an SEV-ES guest > + mov eax, 0x8000001f > + cpuid > + bt eax, 1 > + jnc NoSev > + > + ; Check if SEV memory encryption is enabled > + ; MSR_0xC0010131 - Bit 0 (SEV enabled) > + mov ecx, 0xc0010131 > + rdmsr > + bt eax, 0 > + jnc NoSev > + > + ; Check for SEV-ES memory encryption feature: > + ; CPUID Fn8000_001F[EAX] - Bit 3 > + ; CPUID raises a #VC exception if running as an SEV-ES guest > + mov eax, 0x8000001f > + cpuid > + bt eax, 3 > + jnc GetSevEncBit > + > + ; Check if SEV-ES is enabled > + ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled) > + mov ecx, 0xc0010131 > + rdmsr > + bt eax, 1 > + jnc GetSevEncBit > + > + ; Set the first byte of the workarea to one to communicate to the SEC > + ; phase that SEV-ES is enabled. > + mov byte[SEV_ES_WORK_AREA], 1 > + > +GetSevEncBit: > + ; Get pte bit position to enable memory encryption > + ; CPUID Fn8000_001F[EBX] - Bits 5:0 > + ; > + and ebx, 0x3f > + mov eax, ebx > + > + ; The encryption bit position is always above 31 > + sub ebx, 32 > + jns SevSaveMask > + > + ; Encryption bit was reported as 31 or below, enter a HLT loop > +SevEncBitLowHlt: > + cli > + hlt > + jmp SevEncBitLowHlt > + > +SevSaveMask: > + xor edx, edx > + bts edx, ebx > + > + mov dword[SEV_ES_WORK_AREA_ENC_MASK], 0 > + mov dword[SEV_ES_WORK_AREA_ENC_MASK + 4], edx > + jmp SevExit > + > +NoSev: > + ; > + ; Perform an SEV-ES sanity check by seeing if a #VC exception occurred. > + ; > + cmp byte[SEV_ES_WORK_AREA], 0 > + jz NoSevPass > + > + ; > + ; A #VC was received, yet CPUID indicates no SEV-ES support, something > + ; isn't right. > + ; > +NoSevEsVcHlt: > + cli > + hlt > + jmp NoSevEsVcHlt > + > +NoSevPass: > + xor eax, eax > + > +SevExit: > + ; > + ; Clear exception handlers and stack > + ; > + push eax > + mov eax, ADDR_OF(IdtrClear) > + lidt [cs:eax] > + pop eax > + mov esp, 0 > + > + OneTimeCallRet CheckSevFeatures > + > +; > +; Called before SetCr3ForPageTables64 in SEV guests > +; > +; Modified: EAX, EBX, ECX, EDX, ESP > +; > +PreSetCr3ForPageTables64Sev: > + ; In Tdx TDX_WORK_AREA was set to 'TDXG'. > + ; CheckSevFeatures cannot be called in Tdx guest because SEV_ES_WORK_AREA > + ; cannot be accessed in this situation. Any memory region to be accessed > + ; in Td guest should be accepted first. > + cmp dword[TDX_WORK_AREA], 0x47584454 ; 'TDXG' > + jz ExitPreSetCr3ForPageTables64Sev > + > + OneTimeCall CheckSevFeatures > + > +ExitPreSetCr3ForPageTables64Sev: > + OneTimeCallRet PreSetCr3ForPageTables64Sev > + > +; > +; It is called in SEV after SetCr3PageTables64 > +; > +; Modified: EAX, EBX, ECX, EDX, ESP > +; > +PostSetCr3PageTables64Sev: > + ; In Tdx TDX_WORK_AREA was set to 'TDXG'. > + ; CheckSevFeatures cannot be called in Tdx because SEV_ES_WORK_AREA > + ; cannot be accessed in this situation. Any memory region to be accessed > + ; in Td guest should be accepted first. > + cmp dword[TDX_WORK_AREA], 0x47584454 ; 'TDXG' > + jz ExitPostSetCr3PageTables64Sev > + > + mov eax, cr4 > + bts eax, 5 ; enable PAE > + mov cr4, eax > + > + mov ecx, 0xc0000080 > + rdmsr > + bts eax, 8 ; set LME > + wrmsr > + > + ; > + ; SEV-ES mitigation check support > + ; > + xor ebx, ebx > + > + cmp byte[SEV_ES_WORK_AREA], 0 > + jz EnablePaging > + > + ; > + ; SEV-ES is active, perform a quick sanity check against the reported > + ; encryption bit position. This is to help mitigate against attacks where > + ; the hypervisor reports an incorrect encryption bit position. > + ; > + ; This is the first step in a two step process. Before paging is enabled > + ; writes to memory are encrypted. Using the RDRAND instruction (available > + ; on all SEV capable processors), write 64-bits of random data to the > + ; SEV_ES_WORK_AREA and maintain the random data in registers (register > + ; state is protected under SEV-ES). This will be used in the second step. > + ; > +RdRand1: > + rdrand ecx > + jnc RdRand1 > + mov dword[SEV_ES_WORK_AREA_RDRAND], ecx > +RdRand2: > + rdrand edx > + jnc RdRand2 > + mov dword[SEV_ES_WORK_AREA_RDRAND + 4], edx > + > + ; > + ; Use EBX instead of the SEV_ES_WORK_AREA memory to determine whether to > + ; perform the second step. > + ; > + mov ebx, 1 > + > +EnablePaging: > + mov eax, cr0 > + bts eax, 31 ; set PG > + mov cr0, eax ; enable paging > + > +ExitPostSetCr3PageTables64Sev: > + > + OneTimeCallRet PostSetCr3PageTables64Sev > + > +; > +; Start of #VC exception handling routines > +; > + > +SevEsIdtNotCpuid: > + ; > + ; Use VMGEXIT to request termination. > + ; 1 - #VC was not for CPUID > + ; > + mov eax, 1 > + jmp SevEsIdtTerminate > + > +SevEsIdtNoCpuidResponse: > + ; > + ; Use VMGEXIT to request termination. > + ; 2 - GHCB_CPUID_RESPONSE not received > + ; > + mov eax, 2 > + > +SevEsIdtTerminate: > + ; > + ; Use VMGEXIT to request termination. At this point the reason code is > + ; located in EAX, so shift it left 16 bits to the proper location. > + ; > + ; EAX[11:0] => 0x100 - request termination > + ; EAX[15:12] => 0x1 - OVMF > + ; EAX[23:16] => 0xXX - REASON CODE > + ; > + shl eax, 16 > + or eax, 0x1100 > + xor edx, edx > + mov ecx, 0xc0010130 > + wrmsr > + ; > + ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit > + ; mode, so work around this by temporarily switching to 64-bit mode. > + ; > +BITS 64 > + rep vmmcall > +BITS 32 > + > + ; > + ; We shouldn't come back from the VMGEXIT, but if we do, just loop. > + ; > +SevEsIdtHlt: > + hlt > + jmp SevEsIdtHlt > + iret > + > + ; > + ; Total stack usage for the #VC handler is 44 bytes: > + ; - 12 bytes for the exception IRET (after popping error code) > + ; - 32 bytes for the local variables. > + ; > +SevEsIdtVmmComm: > + ; > + ; If we're here, then we are an SEV-ES guest and this > + ; was triggered by a CPUID instruction > + ; > + ; Set the first byte of the workarea to one to communicate that > + ; a #VC was taken. > + mov byte[SEV_ES_WORK_AREA], 1 > + > + pop ecx ; Error code > + cmp ecx, 0x72 ; Be sure it was CPUID > + jne SevEsIdtNotCpuid > + > + ; Set up local variable room on the stack > + ; CPUID function : + 28 > + ; CPUID request register : + 24 > + ; GHCB MSR (EAX) : + 20 > + ; GHCB MSR (EDX) : + 16 > + ; CPUID result (EDX) : + 12 > + ; CPUID result (ECX) : + 8 > + ; CPUID result (EBX) : + 4 > + ; CPUID result (EAX) : + 0 > + sub esp, VC_VARIABLE_SIZE > + > + ; Save the CPUID function being requested > + mov [esp + VC_CPUID_FUNCTION], eax > + > + ; The GHCB CPUID protocol uses the following mapping to request > + ; a specific register: > + ; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX > + ; > + ; Set EAX as the first register to request. This will also be used as a > + ; loop variable to request all register values (EAX to EDX). > + xor eax, eax > + mov [esp + VC_CPUID_REQUEST_REGISTER], eax > + > + ; Save current GHCB MSR value > + mov ecx, 0xc0010130 > + rdmsr > + mov [esp + VC_GHCB_MSR_EAX], eax > + mov [esp + VC_GHCB_MSR_EDX], edx > + > +NextReg: > + ; > + ; Setup GHCB MSR > + ; GHCB_MSR[63:32] = CPUID function > + ; GHCB_MSR[31:30] = CPUID register > + ; GHCB_MSR[11:0] = CPUID request protocol > + ; > + mov eax, [esp + VC_CPUID_REQUEST_REGISTER] > + cmp eax, 4 > + jge VmmDone > + > + shl eax, GHCB_CPUID_REGISTER_SHIFT > + or eax, GHCB_CPUID_REQUEST > + mov edx, [esp + VC_CPUID_FUNCTION] > + mov ecx, 0xc0010130 > + wrmsr > + > + ; > + ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit > + ; mode, so work around this by temporarily switching to 64-bit mode. > + ; > +BITS 64 > + rep vmmcall > +BITS 32 > + > + ; > + ; Read GHCB MSR > + ; GHCB_MSR[63:32] = CPUID register value > + ; GHCB_MSR[31:30] = CPUID register > + ; GHCB_MSR[11:0] = CPUID response protocol > + ; > + mov ecx, 0xc0010130 > + rdmsr > + mov ecx, eax > + and ecx, 0xfff > + cmp ecx, GHCB_CPUID_RESPONSE > + jne SevEsIdtNoCpuidResponse > + > + ; Save returned value > + shr eax, GHCB_CPUID_REGISTER_SHIFT > + mov [esp + eax * 4], edx > + > + ; Next register > + inc word [esp + VC_CPUID_REQUEST_REGISTER] > + > + jmp NextReg > + > +VmmDone: > + ; > + ; At this point we have all CPUID register values. Restore the GHCB MSR, > + ; set the return register values and return. > + ; > + mov eax, [esp + VC_GHCB_MSR_EAX] > + mov edx, [esp + VC_GHCB_MSR_EDX] > + mov ecx, 0xc0010130 > + wrmsr > + > + mov eax, [esp + VC_CPUID_RESULT_EAX] > + mov ebx, [esp + VC_CPUID_RESULT_EBX] > + mov ecx, [esp + VC_CPUID_RESULT_ECX] > + mov edx, [esp + VC_CPUID_RESULT_EDX] > + > + add esp, VC_VARIABLE_SIZE > + > + ; Update the EIP value to skip over the now handled CPUID instruction > + ; (the CPUID instruction has a length of 2) > + add word [esp], CPUID_INSN_LEN > + iret > + > +ALIGN 2 > + > +Idtr: > + dw IDT_END - IDT_BASE - 1 ; Limit > + dd ADDR_OF(IDT_BASE) ; Base > + > +IdtrClear: > + dw 0 ; Limit > + dd 0 ; Base > + > +ALIGN 16 > + > +; > +; The Interrupt Descriptor Table (IDT) > +; This will be used to determine if SEV-ES is enabled. Upon execution > +; of the CPUID instruction, a VMM Communication Exception will occur. > +; This will tell us if SEV-ES is enabled. We can use the current value > +; of the GHCB MSR to determine the SEV attributes. > +; > +IDT_BASE: > +; > +; Vectors 0 - 28 (No handlers) > +; > +%rep 29 > + dw 0 ; Offset low bits 15..0 > + dw 0x10 ; Selector > + db 0 ; Reserved > + db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32) > + dw 0 ; Offset high bits 31..16 > +%endrep > +; > +; Vector 29 (VMM Communication Exception) > +; > + dw (ADDR_OF(SevEsIdtVmmComm) & 0xffff) ; Offset low bits 15..0 > + dw 0x10 ; Selector > + db 0 ; Reserved > + db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32) > + dw (ADDR_OF(SevEsIdtVmmComm) >> 16) ; Offset high bits 31..16 > +; > +; Vectors 30 - 31 (No handlers) > +; > +%rep 2 > + dw 0 ; Offset low bits 15..0 > + dw 0x10 ; Selector > + db 0 ; Reserved > + db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32) > + dw 0 ; Offset high bits 31..16 > +%endrep > +IDT_END: > + > +BITS 64 > + > +; > +; Called after Jump64BitAndLandHere > +; > +PostJump64BitAndLandHereSev: > + > + ; > + ; If it is Tdx guest, jump to exit point directly. > + ; This is because following code may access the memory region which has > + ; not been accepted. It is not allowed in Tdx guests. > + ; > + mov eax, dword[TDX_WORK_AREA] > + cmp eax, 0x47584454 ; 'TDXG' > + jz GoodCompare > + > + ; > + ; Check if the second step of the SEV-ES mitigation is to be performed. > + ; > + test ebx, ebx > + jz InsnCompare > + > + ; > + ; SEV-ES is active, perform the second step of the encryption bit postion > + ; mitigation check. The ECX and EDX register contain data from RDRAND that > + ; was stored to memory in encrypted form. If the encryption bit position is > + ; valid, the contents of ECX and EDX will match the memory location. > + ; > + cmp dword[SEV_ES_WORK_AREA_RDRAND], ecx > + jne SevEncBitHlt > + cmp dword[SEV_ES_WORK_AREA_RDRAND + 4], edx > + jne SevEncBitHlt > + > + ; > + ; If SEV or SEV-ES is active, perform a quick sanity check against > + ; the reported encryption bit position. This is to help mitigate > + ; against attacks where the hypervisor reports an incorrect encryption > + ; bit position. If SEV is not active, this check will always succeed. > + ; > + ; The cmp instruction compares the first four bytes of the cmp instruction > + ; itself (which will be read decrypted if SEV or SEV-ES is active and the > + ; encryption bit position is valid) against the immediate within the > + ; instruction (an instruction fetch is always decrypted correctly by > + ; hardware) based on RIP relative addressing. > + ; > +InsnCompare: > + cmp dword[rel InsnCompare], 0xFFF63D81 > + je GoodCompare > + > + ; > + ; The hypervisor provided an incorrect encryption bit position, do not > + ; proceed. > + ; > +SevEncBitHlt: > + cli > + hlt > + jmp SevEncBitHlt > + > +GoodCompare: > + OneTimeCallRet PostJump64BitAndLandHereSev