From nobody Sat Feb 7 21:48:09 2026 Received: from CY3PR05CU001.outbound.protection.outlook.com (mail-westcentralusazon11013043.outbound.protection.outlook.com [40.93.201.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC5C426E71E; Fri, 9 Jan 2026 23:18:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.201.43 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768000724; cv=fail; b=FGIWeomdnxpfN21V4nH38lvyOhKjxlcjaztUjaOltoc+091UnQRvQq7RGZKyMg4L4IJmaY2nlU6joXt+DygXmVH7SH5mRdwNc23RjAFItlpTi9MJ9mipd3yq85gpxcH9QjE0C2zkOIMOtcsW92CZlLwp0c557wqBk3/MSnVmQ7s= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768000724; c=relaxed/simple; bh=HS4dGD4DO6r3zG1qjj8X+6TajspIvgXx9kdwVAmD2P8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cUfaRmTv4HfJBksQXkz9o3A8PxsF1v+39M1ZWQPNHbytGp/ad7pRTaiAa1MvB35YEO1S1+6BZ/sqMDJIlU/fok7hszmdTXbNItuqEQQ9sJhKKhXnO4vH1M6lcgNPvAioTgVsgeewMhj9jx/6zbjEcR05cionXWOYF99BReHiykk= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=4G4ZXYDI; arc=fail smtp.client-ip=40.93.201.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="4G4ZXYDI" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=x/KjGm5FxmOhDTxnUOJz1nWV1eYhibzmDZ922RGHnDAvpT+ziOOuDCa97pBROL6jFmc/qF4s8sYYJe64fANGrrpP5AResBdVheQktRW9T+a+qkoOjsss4BeNYdVT2HmebZ/sh8VU5DDrLs1GJ6yheNbk8MS1dcBgKal8QYX9s+cyYdiCO6c+kQ1QpjswCg9vXMuztl9X67kCJNLiqfrrEl8veLhgaYkFz6Rr/eUVQmA9kSB2PKHH/OgY9FDRGT8MEqZnTo2iSeWNQtcQyRK4B7a6vWbHS00ewMDZ8j7kXqxHkQi1jklML2ZyO6t9P7eNTKVa/7itPe8USQw7OvnqZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Axc3rals8qbiJHSWdLCpnPzoDIyaa43dVNbP3EZC01k=; b=gumzi5rCCBC3Bx+YCyFhVa4o5H8nZ6aAfB7MDX5WQmk/YoCL95MMlEOWrLPk2fHXs3fUBJn1EBEtxBpETsEYCZ8EKpkMDnnPFtqi3XDnRrZqgAzH3Dado1FFiC7yyFvvAoWTjE7Q+v7/ONa86mg5ke64VH5m/3cq4tP5OubOvkjnwVscHuG+6keM4CDSTe49QqmAmeB/5GXtTjVPbccDei1uw73WSl0aFL/O6kZ+cecg2YG+z6HuEuuW6rYY6ipBKknKGi39nMje23Sd8moGY0lw44vhEvVcrfuN5rVMzqZM7X0r1GYXrAbngCmuhJ6p1sVr3QlHGwSKgnd63uWCPg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=vger.kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) 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=Axc3rals8qbiJHSWdLCpnPzoDIyaa43dVNbP3EZC01k=; b=4G4ZXYDI9UNKCWermVim0tuhLA89ZknOfAmjbA49KhAcFWp7XKx308cMSrgJt0sn1NujY/7HZVCH13UHJq2gnlRsEk7gLexCpChNc7Ba4Ov3nhoFlbQYD2BzFc1AxEmf2e2R3HnmRm+0jsqrg/RCY800cqFE2hNaTsS4eEv+4x4= Received: from BLAPR03CA0008.namprd03.prod.outlook.com (2603:10b6:208:32b::13) by SN7PR12MB7979.namprd12.prod.outlook.com (2603:10b6:806:32a::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9499.4; Fri, 9 Jan 2026 23:18:38 +0000 Received: from MN1PEPF0000F0DE.namprd04.prod.outlook.com (2603:10b6:208:32b:cafe::77) by BLAPR03CA0008.outlook.office365.com (2603:10b6:208:32b::13) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9499.5 via Frontend Transport; Fri, 9 Jan 2026 23:18:38 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb07.amd.com; pr=C Received: from satlexmb07.amd.com (165.204.84.17) by MN1PEPF0000F0DE.mail.protection.outlook.com (10.167.242.36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9520.1 via Frontend Transport; Fri, 9 Jan 2026 23:18:38 +0000 Received: from localhost (10.180.168.240) by satlexmb07.amd.com (10.181.42.216) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Fri, 9 Jan 2026 17:18:37 -0600 From: Michael Roth To: CC: , , , , , , , , Dionna Glaze Subject: [PATCH v7 1/2] KVM: Introduce KVM_EXIT_SNP_REQ_CERTS for SNP certificate-fetching Date: Fri, 9 Jan 2026 17:17:32 -0600 Message-ID: <20260109231732.1160759-2-michael.roth@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260109231732.1160759-1-michael.roth@amd.com> References: <20260109231732.1160759-1-michael.roth@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: satlexmb07.amd.com (10.181.42.216) To satlexmb07.amd.com (10.181.42.216) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0DE:EE_|SN7PR12MB7979:EE_ X-MS-Office365-Filtering-Correlation-Id: 1d0f64a1-314b-452e-9651-08de4fd56b54 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700013|1800799024|82310400026|376014; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?ELWcwAhRd6SN1Aa9CI6CuZthV0kH9SoZNRIKIarEk4153pBdCmnfLnjnnTU2?= =?us-ascii?Q?dWTjQSTZ9+3aNHEw5KB/J3PuzG2hPT1He8+pmclcwoGaDFp8wHBqIfh/eT9C?= =?us-ascii?Q?yFqI+a4fdVmHGZRGQPq29HlnLXkqC1Cqy+qFMG53H9JjWE7U2Zr095UxCNup?= =?us-ascii?Q?KH46vGGGThQCqhEFoKpwqCTPk6VQKUf+PXT/2y/6zyV8TC4ccTuYIVPUmE0/?= =?us-ascii?Q?cPyDbTupMpOkC2MGo9BpJGDCLqg+Em4ApDMCx/MRYBvQMEUwlQq/PbY5AMRJ?= =?us-ascii?Q?tnsshYioQr5UhWwkMDhxRFgqe8LOcl34ITd+DiXw0pQQirWCtzHFuk5MrN+k?= =?us-ascii?Q?jyZl9pV4uahLXRmvlNBnYLKzdlx5OVXPrdWuzIcMzA0SfqcNSDn+X4pVcT+X?= =?us-ascii?Q?4snh3HYrkPsRy2XfmPF607WCmo23g5mgM/QpY7mInVe/ctRjqQS0o8oFx6Jn?= =?us-ascii?Q?woUpiIPuYiwXGmAtXZKvcLoJH8YrTzt8+YcQBZWhXKH7dx1lVbiO276yErtS?= =?us-ascii?Q?sG7eUDfMircpeAB/FXuq+yiUF7h9OtFACYVfPyXzTjbOOIjeLATcWFP5WrtO?= =?us-ascii?Q?ZM+CEkB+RrcYnXsPZevpSuq1Rjce9X3iyjQes95dueoMRo5rim5rI1KQVV0N?= =?us-ascii?Q?MLMFLt1eKYFu9lh9tz5vKfd/uT6H4CnQvf5cbZqbtPLvOWzrR6ZPXAMSZixz?= =?us-ascii?Q?owQpKxfeve+UlDuiK2rE34b/rvHxkN3Gl0EdDhvrO5v9Ylmvhl4ZcKOY01bh?= =?us-ascii?Q?biWg/qEBrOsFCFEgWhhPB0uTl1UCcxqfALALmtlSt1Xxlp9NffDuz0yeXyPH?= =?us-ascii?Q?1K7OCirRCmWh2sq+IkwYJCpINU6T6UOfcwNd2I6W+rstOqQl40HMsxKWLqJI?= =?us-ascii?Q?EwWhmjMlQyH/Vtm9mi+zc6CQWok6iGxL857DFS1zRCwKsSDrGiPpVIRWT1+s?= =?us-ascii?Q?LMjMs0ASSoYuhzGAUorYxLveiPXkrluXnhpNanihF7WJ2P6vo40aNE4Stm8j?= =?us-ascii?Q?+Ddd5K98mQyGQmCD8mLzNtmB1tt2nFIHARSyNumh4kRa0aKNbRso+gQT8pzN?= =?us-ascii?Q?UEhrM04sbySmnHgiC0LzC8bWPmXjcVUUg7VV/ibiu9qHZC3qxI6v131QA46u?= =?us-ascii?Q?/6HjjOj4eVhqKYkAAXHL9neq4iaHXE3aIoxCyAsVwF8JbUf86GNCPm9Ur5S9?= =?us-ascii?Q?kdDUzv3UXtr5+pUdfemPim75JwHgFKPLVnlp7JAOmGv2hb2w2h8G/35Yvkqv?= =?us-ascii?Q?dSFBzYyKVfR319Q1qE7zYpx/H0T/GRWxG+357qGuJ+SM+ZQNv324uDwd9gpX?= =?us-ascii?Q?UE46CGnAmIryP8dbELPDsCjIsQoNMWFNcOTeKKB4ZmtlgwhSYnSSv+ia7s3b?= =?us-ascii?Q?MwLtXE8aiNZAJSRUwG33YJl1owl8H1JasbzyUwLLZBsRoVlwvI/E5tIENWyK?= =?us-ascii?Q?5dHF+HqLdAObbeDdjhj2uaosxclUgLO6OgxYqgjBixoxtiwzVk8S5NO1wDVo?= =?us-ascii?Q?DgwxNJ+Kcp+T9zgwzmcR/JC8xH8a8MDxOUoiXA5pXABQjycE8tHpAbNdewNo?= =?us-ascii?Q?1IUdku5uSEyjnWtiTno=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb07.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(36860700013)(1800799024)(82310400026)(376014);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Jan 2026 23:18:38.0086 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1d0f64a1-314b-452e-9651-08de4fd56b54 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb07.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0DE.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7979 Content-Type: text/plain; charset="utf-8" For SEV-SNP, the host can optionally provide a certificate table to the guest when it issues an attestation request to firmware (see GHCB 2.0 specification regarding "SNP Extended Guest Requests"). This certificate table can then be used to verify the endorsement key used by firmware to sign the attestation report. While it is possible for guests to obtain the certificates through other means, handling it via the host provides more flexibility in being able to keep the certificate data in sync with the endorsement key throughout host-side operations that might resulting in the endorsement key changing. In the case of KVM, userspace will be responsible for fetching the certificate table and keeping it in sync with any modifications to the endorsement key by other userspace management tools. Define a new KVM_EXIT_SNP_REQ_CERTS event where userspace is provided with the GPA of the buffer the guest has provided as part of the attestation request so that userspace can write the certificate data into it while relying on filesystem-based locking to keep the certificates up-to-date relative to the endorsement keys installed/utilized by firmware at the time the certificates are fetched. Reviewed-by: Liam Merwick Tested-by: Liam Merwick Tested-by: Dionna Glaze Signed-off-by: Michael Roth [Melody: Update the documentation scheme about how file locking is expected to happen.] Signed-off-by: Melody Wang Signed-off-by: Michael Roth --- Documentation/virt/kvm/api.rst | 44 ++++++++++++++++++++++++ arch/x86/kvm/svm/sev.c | 62 ++++++++++++++++++++++++++++++---- arch/x86/kvm/svm/svm.h | 1 + include/uapi/linux/kvm.h | 9 +++++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 01a3abef8abb..aa8b192179c2 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -7353,6 +7353,50 @@ Please note that the kernel is allowed to use the kv= m_run structure as the primary storage for certain register types. Therefore, the kernel may use = the values in kvm_run even if the corresponding bit in kvm_dirty_regs is not s= et. =20 +:: + + /* KVM_EXIT_SNP_REQ_CERTS */ + struct kvm_exit_snp_req_certs { + __u64 gpa; + __u64 npages; + __u64 ret; + }; + +KVM_EXIT_SNP_REQ_CERTS indicates an SEV-SNP guest with certificate-fetching +enabled (see KVM_SEV_SNP_ENABLE_REQ_CERTS) has generated an Extended Guest +Request NAE #VMGEXIT (SNP_GUEST_REQUEST) with message type MSG_REPORT_REQ, +i.e. has requested an attestation report from firmware, and would like the +certificate data corresponding the attestation report signature to be +provided by the hypervisor as part of the request. + +To allow for userspace to provide the certificate, the 'gpa' and 'npages' +are forwarded verbatim from the guest request (the RAX and RBX GHCB fields +respectively). 'ret' is not an "output" from KVM, and is always '0' on +exit. KVM verifies the 'gpa' is 4KiB aligned prior to exiting to userspac= e, +but otherwise the information from the guest isn't validated. + +Upon the next KVM_RUN, e.g. after userspace has serviced the request (or n= ot), +KVM will complete the #VMGEXIT, using the 'ret' field to determine whether= to +signal success or failure to the guest, and on failure, what reason code w= ill +be communicated via SW_EXITINFO2. If 'ret' is set to an unsupported value= (see +the table below), KVM_RUN will fail with -EINVAL. For a 'ret' of 'ENOSPC'= , KVM +also consumes the 'npages' field, i.e. userspace can use the field to info= rm +the guest of the number of pages needed to hold all the certificate data. + +The supported 'ret' values and their respective SW_EXITINFO2 encodings: + + =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + 0 0x0, i.e. success. KVM will emit an SNP_GUEST_REQUEST command + to SNP firmware. + ENOSPC 0x0000000100000000, i.e. not enough guest pages to hold the + certificate table and certificate data. KVM will also set the + RBX field in the GHBC to 'npages'. + EAGAIN 0x0000000200000000, i.e. the host is busy and the guest should + retry the request. + EIO 0xffffffff00000000, for all other errors (this return code is + a KVM-defined hypervisor value, as allowed by the GHCB) + =3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + =20 .. _cap_enable: =20 diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index f59c65abe3cf..2405c6fad95c 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -41,6 +41,16 @@ =20 #define GHCB_HV_FT_SUPPORTED (GHCB_HV_FT_SNP | GHCB_HV_FT_SNP_AP_CREATION) =20 +/* + * The GHCB spec essentially states that all non-zero error codes other th= an + * those explicitly defined above should be treated as an error by the gue= st. + * Define a generic error to cover that case, and choose a value that is n= ot + * likely to overlap with new explicit error codes should more be added to + * the GHCB spec later. KVM will use this to report generic errors when + * handling SNP guest requests. + */ +#define SNP_GUEST_VMM_ERR_GENERIC (~0U) + /* enable/disable SEV support */ static bool sev_enabled =3D true; module_param_named(sev, sev_enabled, bool, 0444); @@ -4155,6 +4165,36 @@ static int snp_handle_guest_req(struct vcpu_svm *svm= , gpa_t req_gpa, gpa_t resp_ return ret; } =20 +static int snp_req_certs_err(struct vcpu_svm *svm, u32 vmm_error) +{ + ghcb_set_sw_exit_info_2(svm->sev_es.ghcb, SNP_GUEST_ERR(vmm_error, 0)); + + return 1; /* resume guest */ +} + +static int snp_complete_req_certs(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + struct vmcb_control_area *control =3D &svm->vmcb->control; + + switch (READ_ONCE(vcpu->run->snp_req_certs.ret)) { + case 0: + return snp_handle_guest_req(svm, control->exit_info_1, + control->exit_info_2); + case ENOSPC: + vcpu->arch.regs[VCPU_REGS_RBX] =3D vcpu->run->snp_req_certs.npages; + return snp_req_certs_err(svm, SNP_GUEST_VMM_ERR_INVALID_LEN); + case EAGAIN: + return snp_req_certs_err(svm, SNP_GUEST_VMM_ERR_BUSY); + case EIO: + return snp_req_certs_err(svm, SNP_GUEST_VMM_ERR_GENERIC); + default: + break; + } + + return -EINVAL; +} + static int snp_handle_ext_guest_req(struct vcpu_svm *svm, gpa_t req_gpa, g= pa_t resp_gpa) { struct kvm *kvm =3D svm->vcpu.kvm; @@ -4170,14 +4210,15 @@ static int snp_handle_ext_guest_req(struct vcpu_svm= *svm, gpa_t req_gpa, gpa_t r /* * As per GHCB spec, requests of type MSG_REPORT_REQ also allow for * additional certificate data to be provided alongside the attestation - * report via the guest-provided data pages indicated by RAX/RBX. The - * certificate data is optional and requires additional KVM enablement - * to provide an interface for userspace to provide it, but KVM still - * needs to be able to handle extended guest requests either way. So - * provide a stub implementation that will always return an empty - * certificate table in the guest-provided data pages. + * report via the guest-provided data pages indicated by RAX/RBX. If + * userspace enables KVM_EXIT_SNP_REQ_CERTS, then exit to userspace + * to give userspace an opportunity to provide the certificate data + * before issuing/completing the attestation request. Otherwise, return + * an empty certificate table in the guest-provided data pages and + * handle the attestation request immediately. */ if (msg_type =3D=3D SNP_MSG_REPORT_REQ) { + struct kvm_sev_info *sev =3D &to_kvm_svm(kvm)->sev_info; struct kvm_vcpu *vcpu =3D &svm->vcpu; u64 data_npages; gpa_t data_gpa; @@ -4191,6 +4232,15 @@ static int snp_handle_ext_guest_req(struct vcpu_svm = *svm, gpa_t req_gpa, gpa_t r if (!PAGE_ALIGNED(data_gpa)) goto request_invalid; =20 + if (sev->snp_certs_enabled) { + vcpu->run->exit_reason =3D KVM_EXIT_SNP_REQ_CERTS; + vcpu->run->snp_req_certs.gpa =3D data_gpa; + vcpu->run->snp_req_certs.npages =3D data_npages; + vcpu->run->snp_req_certs.ret =3D 0; + vcpu->arch.complete_userspace_io =3D snp_complete_req_certs; + return 0; + } + /* * As per GHCB spec (see "SNP Extended Guest Request"), the * certificate table is terminated by 24-bytes of zeroes. diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 01be93a53d07..eac1cbd3debe 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -115,6 +115,7 @@ struct kvm_sev_info { void *guest_resp_buf; /* Bounce buffer for SNP Guest Request output */ struct mutex guest_req_mutex; /* Must acquire before using bounce buffers= */ cpumask_var_t have_run_cpus; /* CPUs that have done VMRUN for this VM. */ + bool snp_certs_enabled; /* SNP certificate-fetching support. */ }; =20 struct kvm_svm { diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index dddb781b0507..8cd107cdcf0b 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -135,6 +135,12 @@ struct kvm_xen_exit { } u; }; =20 +struct kvm_exit_snp_req_certs { + __u64 gpa; + __u64 npages; + __u64 ret; +}; + #define KVM_S390_GET_SKEYS_NONE 1 #define KVM_S390_SKEYS_MAX 1048576 =20 @@ -180,6 +186,7 @@ struct kvm_xen_exit { #define KVM_EXIT_MEMORY_FAULT 39 #define KVM_EXIT_TDX 40 #define KVM_EXIT_ARM_SEA 41 +#define KVM_EXIT_SNP_REQ_CERTS 42 =20 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -482,6 +489,8 @@ struct kvm_run { __u64 gva; __u64 gpa; } arm_sea; + /* KVM_EXIT_SNP_REQ_CERTS */ + struct kvm_exit_snp_req_certs snp_req_certs; /* Fix the size of the union. */ char padding[256]; }; --=20 2.25.1 From nobody Sat Feb 7 21:48:09 2026 Received: from BL0PR03CU003.outbound.protection.outlook.com (mail-eastusazon11012033.outbound.protection.outlook.com [52.101.53.33]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7308726E71E; Fri, 9 Jan 2026 23:19:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.53.33 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768000759; cv=fail; b=dVSR+xFADTqCOlvsSSVpIbGvLqYNJdDlFfDTscV4poe0C50+KAys67J2eHuYmXTyIeknry0D92Yvjnzt5UYtJNpNglZmOxC/rxEg7FXnz/ut1C9jfh6Ma/t/8CB3jmm8bzbEU9Onsd6DUQhdEGYvDo8CSYId3f9a94w9FIwbHSQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768000759; c=relaxed/simple; bh=lQ6uK0UOu4zfWkxcGb67bjw1bGkFTw+Zpi9m5yqVUOM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ny1exaIxf7SuXHDmDbPTNz2RWwg9XrroR1NvoLNK1Brta4l8c8TPzt1CBf3IRQRD0Tc3lpW11kcCHB8hI5GwKlWtbtBxYHShp7ADSPPq6i56MPhU/ICtL54LpboWMYMnV7uM3/LJtBMLGZ4Wwt7fa8SmZFJvg/ETMZVzN7NpNC8= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=vcrnPNJE; arc=fail smtp.client-ip=52.101.53.33 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="vcrnPNJE" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=tBHMN79kGa44k3/olEqwraOhI0/yG6NEtY8/7ChlaHrJPLOS3i8wyTuksNpRdlAlRBzpFix1oQdPv51MS/n12LnrukYN0KYbQTOizalaL+LimNPl6WONF62jPGQI241sn1t+X8n731FS96x8gk+EJxGUXY3Ya3Kcej+AsBqXbgNs3zRmGpfAiHXTFacy2A62MVteay486FyU4NKJ8fI2tDXVNHRkD2Npidkfcyj/DVs705trtCTlQ/4XxFqhEM9BoaN4eCSgej8ol90llIRJceVqyTEwohPoPQmKnhLI3ERW5sylIXNmAUWguWqiPrIqkXwJpbu1uZrCH9BN7qJNbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=8/zZfcXYHWnvgAZRHCAl/SBnBIbOGpORUjKHESvIY4M=; b=rZ2xd8GMNWXoVLG19zUruZXRMHGPUseP2qZSiNWNOk3RF502/7Kmipq3Vli+Oni41SzBcrj/Op6MngBoaWUif6Pi2JnCDCAhASyRZ57sZRSmb90c/VRKjpFQducfImbvcEnOFfNqiWJjoPLafiE4vz9lnOiXUwsdwUPCfjUIM5Gv3PD0ZW7PGjTYufQkcfC7RG8qn+1Xz6jHSqfxJchBCLLqkhM0mhEOn5xcmho9tywefvrRRFusQOErRV81+cTVHQYjnD/z1ZwyXAmLdkY9laO1sAdNgaPCbZx4xyKCxghG1m1AZlKZkbYcHm68ZJ9UqANbDa3Dab//NOwLlXl1WA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=vger.kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) 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=8/zZfcXYHWnvgAZRHCAl/SBnBIbOGpORUjKHESvIY4M=; b=vcrnPNJEmP++TC1GYsX0vPCTTKb2mbBKjHCO7lYMRPpJaYYBYzIq7p0xcAi+pHI5zgmx9XqkIfIcuY0NcwrDSOzOS53CkmD8qupUjKZts2uTlLe2dqpNqJ6WfSs87D3PMcZd/+GaX2XQH8Dup8uZxoYLpk30HqeZ0JD2QsT5emw= Received: from BYAPR08CA0014.namprd08.prod.outlook.com (2603:10b6:a03:100::27) by MN0PR12MB6318.namprd12.prod.outlook.com (2603:10b6:208:3c1::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9499.5; Fri, 9 Jan 2026 23:19:14 +0000 Received: from SJ1PEPF00002316.namprd03.prod.outlook.com (2603:10b6:a03:100:cafe::c0) by BYAPR08CA0014.outlook.office365.com (2603:10b6:a03:100::27) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9499.5 via Frontend Transport; Fri, 9 Jan 2026 23:19:13 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb07.amd.com; pr=C Received: from satlexmb07.amd.com (165.204.84.17) by SJ1PEPF00002316.mail.protection.outlook.com (10.167.242.170) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9520.1 via Frontend Transport; Fri, 9 Jan 2026 23:19:12 +0000 Received: from localhost (10.180.168.240) by satlexmb07.amd.com (10.181.42.216) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Fri, 9 Jan 2026 17:18:58 -0600 From: Michael Roth To: CC: , , , , , , , Subject: [PATCH v7 2/2] KVM: SEV: Add KVM_SEV_SNP_ENABLE_REQ_CERTS command Date: Fri, 9 Jan 2026 17:17:33 -0600 Message-ID: <20260109231732.1160759-3-michael.roth@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260109231732.1160759-1-michael.roth@amd.com> References: <20260109231732.1160759-1-michael.roth@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: satlexmb07.amd.com (10.181.42.216) To satlexmb07.amd.com (10.181.42.216) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ1PEPF00002316:EE_|MN0PR12MB6318:EE_ X-MS-Office365-Filtering-Correlation-Id: 0081eafa-fd40-4bf7-6d01-08de4fd5802f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|376014|36860700013|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?qHtrC5DGFrhwS5NxWHEOhz9FqPYlADqrmFqOnRYsWLqqk6RGSmJHPrm7d3ld?= =?us-ascii?Q?HzP9WlxbvdL1JGdog3o/F+i2JqYYCIKgy3EQI/0nfAEg2YMwegF4kSa4WSbR?= =?us-ascii?Q?t2LPFAegaXmvuVR18obNC1uBW0FUR8RNEsMG5ikF7AOMQqPSmBigl1KrRwN2?= =?us-ascii?Q?DEynofZIMMm0faKAP8dTv7YAISKRAAA9m9yxeYJEe8XBuVYBREeBRqdAKlvo?= =?us-ascii?Q?g/Tg+ZTK50JvLjIlyTWPwNWY9jjwgWUiS3hQXtE9sbFZxk+YRlidiNeiS//2?= =?us-ascii?Q?OBi1QVG9q6o3hAIZ13h40aBaWkHNI5cQGkM2UFbV+qaf8XC4bHcZbapVK47Q?= =?us-ascii?Q?gvo+Z55TTcRkxwL/bA+Wnwjv+BlCnV1UfqLb8pxAJKtcvPBZjR2gAhyGaPOS?= =?us-ascii?Q?Ru5hQPSdmFv7nFWjFwC8N9krzBoMtQgOC5CkCKOpv+ULJnSn9Jm8U3SkfNe0?= =?us-ascii?Q?WNEukaW44F587rS2o+LXUvPrVC+cltjn35I1BpiNFS7Eu23z9E9m9WygRks1?= =?us-ascii?Q?hoo7m1C7Zzb1TxrGBx2YMrpSFi3wrijdehADcdoWcnyW7DDYDOR09hxTfBlI?= =?us-ascii?Q?azKOI6qWmhg4AIo4dYDPtlcOIqUEXSYKaY+OBzDpaeFxJY8Vl10SmQI5Xc9H?= =?us-ascii?Q?lQl4x56Oo1xg/c9L8mvutC6ItabNB9+9Vn8lTXgzr0vR9a8+uGTmCrqmcu0y?= =?us-ascii?Q?+BltvqByQ4yGQdek3mSL2WIg4r0la34PeEvAXFq7cPGXwSJPe2TL4CIdrKpN?= =?us-ascii?Q?i/dFIxjaXB4x7WW8nLDGXfgxq+X6k2AhbzCgrEOa4Lqnw5a6lBBoyw9sTm1I?= =?us-ascii?Q?MMOBntoJwB46ifhUajkG+qd5EELkwT0iUxYJmc0sr+LWFgEeqiXExgKjj07K?= =?us-ascii?Q?jALSd+BLq0IC+HGPwP4sqQooJup3pg86RMv5Kl96/X89c7UBezl6MzjpxAkx?= =?us-ascii?Q?dNFE3k+7ywqw1o/e8BIuk2LVAiVlGk/jvtOTuy2KrxcFtYNP6igOrkPhjRm7?= =?us-ascii?Q?F9v+bVugZRzIwkSEZW6B0pHC7IeaemF5s4AFA7/FlelanKfr72eAADt2tjei?= =?us-ascii?Q?ox4pxZqE+Zi5Y/sWEuSsM3oxEZWsU5fBcRtBwgGWZoBVy1nBey+CzitpbKVT?= =?us-ascii?Q?35OlGoGZUr6t0wRBIPCaT5sSZNgRvsdEcsONV/0So5YmPVzk2JowirVyfTZR?= =?us-ascii?Q?rVvcCbjZFKIGps/gfkUDHqgGPenl/WzrsESgJOW6waL1Kd49awZ3xU854mOK?= =?us-ascii?Q?70tXoHsZoQaIKuWYrkk33pEMxNGRao/PxVO6G1pdRy/Xm4Q2DMxMdOTcl8hv?= =?us-ascii?Q?8+Jn2pFfJPwFByslt6woFsRWDH5udnnBwm5lvMyV6eOuPrloYHJvcoKchsWU?= =?us-ascii?Q?gcTwkhSwbwoOfL3rMcBzfEx0SyXqJwiIWBSfnlCO6HMUH7IaScpP5BkP8KMr?= =?us-ascii?Q?eXVrT0PXwOjKxZGiHuISIUmz0Ogg6NK0Q36as/frIfE/eqAu81Z9EkzHp5yA?= =?us-ascii?Q?rSJ2lKn+94HVAnv1xo4nd+15Wp7pLE/hyLDshfgglA5MWHj9quOGqK1b+6Mw?= =?us-ascii?Q?lnFMBWnSgJeq9wBhmjA=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb07.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(82310400026)(376014)(36860700013)(1800799024);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Jan 2026 23:19:12.9064 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 0081eafa-fd40-4bf7-6d01-08de4fd5802f X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb07.amd.com] X-MS-Exchange-CrossTenant-AuthSource: SJ1PEPF00002316.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN0PR12MB6318 Content-Type: text/plain; charset="utf-8" Introduce a new command for KVM_MEMORY_ENCRYPT_OP ioctl that can be used to enable fetching of endorsement key certificates from userspace via the new KVM_EXIT_SNP_REQ_CERTS exit type. Also introduce a new KVM_X86_SEV_SNP_REQ_CERTS KVM device attribute so that userspace can query whether the kernel supports the new command/exit. Suggested-by: Sean Christopherson Reviewed-by: Liam Merwick Tested-by: Liam Merwick Signed-off-by: Michael Roth --- .../virt/kvm/x86/amd-memory-encryption.rst | 52 ++++++++++++++++++- arch/x86/include/uapi/asm/kvm.h | 2 + arch/x86/kvm/svm/sev.c | 16 ++++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/Documentation/virt/kvm/x86/amd-memory-encryption.rst b/Documen= tation/virt/kvm/x86/amd-memory-encryption.rst index 1ddb6a86ce7f..543b5e5dd8d4 100644 --- a/Documentation/virt/kvm/x86/amd-memory-encryption.rst +++ b/Documentation/virt/kvm/x86/amd-memory-encryption.rst @@ -572,6 +572,52 @@ Returns: 0 on success, -negative on error See SNP_LAUNCH_FINISH in the SEV-SNP specification [snp-fw-abi]_ for furth= er details on the input parameters in ``struct kvm_sev_snp_launch_finish``. =20 +21. KVM_SEV_SNP_ENABLE_REQ_CERTS +-------------------------------- + +The KVM_SEV_SNP_ENABLE_REQ_CERTS command will configure KVM to exit to +userspace with a ``KVM_EXIT_SNP_REQ_CERTS`` exit type as part of handling +a guest attestation report, which will to allow userspace to provide a +certificate corresponding to the endorsement key used by firmware to sign +that attestation report. + +Returns: 0 on success, -negative on error + +NOTE: The endorsement key used by firmware may change as a result of +management activities like updating SEV-SNP firmware or loading new +endorsement keys, so some care should be taken to keep the returned +certificate data in sync with the actual endorsement key in use by +firmware at the time the attestation request is sent to SNP firmware. The +recommended scheme to do this is to use file locking (e.g. via fcntl()'s +F_OFD_SETLK) in the following manner: + + - Prior to obtaining/providing certificate data as part of servicing an + exit type of ``KVM_EXIT_SNP_REQ_CERTS``, the VMM should obtain a + shared/read or exclusive/write lock on the certificate blob file before + reading it and returning it to KVM, and continue to hold the lock until + the attestation request is actually sent to firmware. To facilitate + this, the VMM can set the ``immediate_exit`` flag of kvm_run just after + supplying the certificate data, and just before resuming the vCPU. + This will ensure the vCPU will exit again to userspace with ``-EINTR`` + after it finishes fetching the attestation request from firmware, at + which point the VMM can safely drop the file lock. + + - Tools/libraries that perform updates to SNP firmware TCB values or + endorsement keys (e.g. via /dev/sev interfaces such as ``SNP_COMMIT``, + ``SNP_SET_CONFIG``, or ``SNP_VLEK_LOAD``, see + Documentation/virt/coco/sev-guest.rst for more details) in such a way + that the certificate blob needs to be updated, should similarly take an + exclusive lock on the certificate blob for the duration of any updates + to endorsement keys or the certificate blob contents to ensure that + VMMs using the above scheme will not return certificate blob data that + is out of sync with the endorsement key used by firmware at the time + the attestation request is actually issued. + +This scheme is recommended so that tools can use a fairly generic/natural +approach to synchronizing firmware/certificate updates via file-locking, +which should make it easier to maintain interoperability across +tools/VMMs/vendors. + Device attribute API =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 @@ -579,11 +625,15 @@ Attributes of the SEV implementation can be retrieved= through the ``KVM_HAS_DEVICE_ATTR`` and ``KVM_GET_DEVICE_ATTR`` ioctls on the ``/dev/k= vm`` device node, using group ``KVM_X86_GRP_SEV``. =20 -Currently only one attribute is implemented: +The following attributes are currently implemented: =20 * ``KVM_X86_SEV_VMSA_FEATURES``: return the set of all bits that are accepted in the ``vmsa_features`` of ``KVM_SEV_INIT2``. =20 +* ``KVM_X86_SEV_SNP_REQ_CERTS``: return a value of 1 if the kernel support= s the + ``KVM_EXIT_SNP_REQ_CERTS`` exit, which allows for fetching endorsement k= ey + certificates from userspace for each SNP attestation request the guest i= ssues. + Firmware Management =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kv= m.h index 7ceff6583652..b2c928c5965d 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -503,6 +503,7 @@ struct kvm_sync_regs { #define KVM_X86_GRP_SEV 1 # define KVM_X86_SEV_VMSA_FEATURES 0 # define KVM_X86_SNP_POLICY_BITS 1 +# define KVM_X86_SEV_SNP_REQ_CERTS 2 =20 struct kvm_vmx_nested_state_data { __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; @@ -743,6 +744,7 @@ enum sev_cmd_id { KVM_SEV_SNP_LAUNCH_START =3D 100, KVM_SEV_SNP_LAUNCH_UPDATE, KVM_SEV_SNP_LAUNCH_FINISH, + KVM_SEV_SNP_ENABLE_REQ_CERTS, =20 KVM_SEV_NR_MAX, }; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 2405c6fad95c..695463bc6c5b 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2161,6 +2161,9 @@ int sev_dev_get_attr(u32 group, u64 attr, u64 *val) *val =3D snp_supported_policy_bits; return 0; =20 + case KVM_X86_SEV_SNP_REQ_CERTS: + *val =3D sev_snp_enabled ? 1 : 0; + return 0; default: return -ENXIO; } @@ -2577,6 +2580,16 @@ static int snp_launch_finish(struct kvm *kvm, struct= kvm_sev_cmd *argp) return ret; } =20 +static int snp_enable_certs(struct kvm *kvm) +{ + if (kvm->created_vcpus || !sev_snp_guest(kvm)) + return -EINVAL; + + to_kvm_sev_info(kvm)->snp_certs_enabled =3D true; + + return 0; +} + int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp) { struct kvm_sev_cmd sev_cmd; @@ -2682,6 +2695,9 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *a= rgp) case KVM_SEV_SNP_LAUNCH_FINISH: r =3D snp_launch_finish(kvm, &sev_cmd); break; + case KVM_SEV_SNP_ENABLE_REQ_CERTS: + r =3D snp_enable_certs(kvm); + break; default: r =3D -EINVAL; goto out; --=20 2.25.1