linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.singh@amd.com>
To: x86@kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: tglx@linutronix.de, bp@alien8.de, jroedel@suse.de,
	thomas.lendacky@amd.com, pbonzini@redhat.com, mingo@redhat.com,
	dave.hansen@intel.com, rientjes@google.com, seanjc@google.com,
	peterz@infradead.org, hpa@zytor.com, tony.luck@intel.com,
	Brijesh Singh <brijesh.singh@amd.com>
Subject: [PATCH Part1 RFC v2 19/20] x86/sev: Register SNP guest request platform device
Date: Fri, 30 Apr 2021 07:16:15 -0500	[thread overview]
Message-ID: <20210430121616.2295-20-brijesh.singh@amd.com> (raw)
In-Reply-To: <20210430121616.2295-1-brijesh.singh@amd.com>

Version 2 of GHCB specification provides NAEs that can be used by the SNP
guest to communicate with the PSP without risk from a malicious hypervisor
who wishes to read, alter, drop or replay the messages sent.

The hypervisor uses the SNP_GUEST_REQUEST command interface provided by
the SEV-SNP firmware to forward the guest messages to the PSP.

In order to communicate with the PSP, the guest need to locate the secrets
page inserted by the hypervisor during the SEV-SNP guest launch. The
secrets page contains the communication keys used to send and receive the
encrypted messages between the guest and the PSP.

The secrets page is located either through the setup_data cc_blob_address
or EFI configuration table.

Create a platform device that the SNP guest driver will bind to get the
platform resources. The SNP guest driver will provide interface to get
the attestation report, key derivation etc.

See SEV-SNP and GHCB spec for more details.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 arch/x86/kernel/sev.c       | 124 ++++++++++++++++++++++++++++++++++++
 arch/x86/platform/efi/efi.c |   2 +
 include/linux/efi.h         |   1 +
 include/linux/snp-guest.h   | 124 ++++++++++++++++++++++++++++++++++++
 4 files changed, 251 insertions(+)
 create mode 100644 include/linux/snp-guest.h

diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index f28fd8605e63..6fd1f82f473a 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt)	"SEV-ES: " fmt
 
+#include <linux/platform_device.h>
 #include <linux/sched/debug.h>	/* For show_regs() */
 #include <linux/percpu-defs.h>
 #include <linux/mem_encrypt.h>
@@ -16,9 +17,12 @@
 #include <linux/printk.h>
 #include <linux/mm_types.h>
 #include <linux/set_memory.h>
+#include <linux/snp-guest.h>
 #include <linux/memblock.h>
 #include <linux/kernel.h>
+#include <linux/efi.h>
 #include <linux/mm.h>
+#include <linux/io.h>
 
 #include <asm/cpu_entry_area.h>
 #include <asm/stacktrace.h>
@@ -31,6 +35,7 @@
 #include <asm/svm.h>
 #include <asm/smp.h>
 #include <asm/cpu.h>
+#include <asm/setup.h>		/* For struct boot_params */
 
 #define DR7_RESET_VALUE        0x400
 
@@ -101,6 +106,21 @@ struct ghcb_state {
 	struct ghcb *ghcb;
 };
 
+/* Confidential computing blob information */
+#define CC_BLOB_SEV_HDR_MAGIC	0x414d4445
+struct cc_blob_sev_info {
+	u32 magic;
+	u16 version;
+	u64 secrets_phys;
+	u32 secrets_len;
+	u64 cpuid_phys;
+	u32 cpuid_len;
+};
+
+#ifdef CONFIG_EFI
+extern unsigned long cc_blob_phys;
+#endif
+
 static DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data);
 DEFINE_STATIC_KEY_FALSE(sev_es_enable_key);
 
@@ -1685,3 +1705,107 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
 	while (true)
 		halt();
 }
+
+static struct resource guest_req_res[0];
+static struct platform_device guest_req_device = {
+	.name		= "snp-guest",
+	.id		= -1,
+	.resource	= guest_req_res,
+	.num_resources	= 1,
+};
+
+static int get_snp_secrets_resource(struct resource *res)
+{
+	struct setup_header *hdr = &boot_params.hdr;
+	struct cc_blob_sev_info *info;
+	unsigned long paddr;
+	int ret = -ENODEV;
+
+	/*
+	 * The secret page contains the VM encryption key used for encrypting the
+	 * messages between the guest and the PSP. The secrets page location is
+	 * available either through the setup_data or EFI configuration table.
+	 */
+	if (hdr->cc_blob_address) {
+		paddr = hdr->cc_blob_address;
+	} else if (efi_enabled(EFI_CONFIG_TABLES)) {
+#ifdef CONFIG_EFI
+		paddr = cc_blob_phys;
+#else
+		return -ENODEV;
+#endif
+	} else {
+		return -ENODEV;
+	}
+
+	info = memremap(paddr, sizeof(*info), MEMREMAP_WB);
+	if (!info)
+		return -ENOMEM;
+
+	if (info->magic == CC_BLOB_SEV_HDR_MAGIC && info->secrets_phys && info->secrets_len) {
+		res->start = info->secrets_phys;
+		res->end = info->secrets_phys + info->secrets_len;
+		res->flags = IORESOURCE_MEM;
+		ret = 0;
+	}
+
+	memunmap(info);
+	return ret;
+}
+
+static int __init add_snp_guest_request(void)
+{
+	if (!sev_snp_active())
+		return -ENODEV;
+
+	if (get_snp_secrets_resource(&guest_req_res[0]))
+		return -ENODEV;
+
+	platform_device_register(&guest_req_device);
+	dev_info(&guest_req_device.dev, "registered [secret 0x%016llx - 0x%016llx]\n",
+		guest_req_res[0].start, guest_req_res[0].end);
+
+	return 0;
+}
+device_initcall(add_snp_guest_request);
+
+unsigned long snp_issue_guest_request(int type, struct snp_guest_request_data *input)
+{
+	struct ghcb_state state;
+	struct ghcb *ghcb;
+	unsigned long id;
+	int ret;
+
+	if (type == SNP_GUEST_REQUEST)
+		id = SVM_VMGEXIT_SNP_GUEST_REQUEST;
+	else if (type == SNP_EXTENDED_GUEST_REQUEST)
+		id = SVM_VMGEXIT_SNP_EXT_GUEST_REQUEST;
+	else
+		return -EINVAL;
+
+	if (!sev_snp_active())
+		return -ENODEV;
+
+	ghcb = sev_es_get_ghcb(&state);
+	if (!ghcb)
+		return -ENODEV;
+
+	vc_ghcb_invalidate(ghcb);
+	ghcb_set_rax(ghcb, input->data_gpa);
+	ghcb_set_rbx(ghcb, input->data_npages);
+
+	ret = sev_es_ghcb_hv_call(ghcb, NULL, id, input->req_gpa, input->resp_gpa);
+
+	if (ret)
+		goto e_put;
+
+	if (ghcb->save.sw_exit_info_2) {
+		ret = ghcb->save.sw_exit_info_2;
+		goto e_put;
+	}
+
+e_put:
+	sev_es_put_ghcb(&state);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snp_issue_guest_request);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 8a26e705cb06..2cca9ee6e1d4 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -57,6 +57,7 @@ static unsigned long efi_systab_phys __initdata;
 static unsigned long prop_phys = EFI_INVALID_TABLE_ADDR;
 static unsigned long uga_phys = EFI_INVALID_TABLE_ADDR;
 static unsigned long efi_runtime, efi_nr_tables;
+unsigned long cc_blob_phys;
 
 unsigned long efi_fw_vendor, efi_config_table;
 
@@ -66,6 +67,7 @@ static const efi_config_table_type_t arch_tables[] __initconst = {
 #ifdef CONFIG_X86_UV
 	{UV_SYSTEM_TABLE_GUID,		&uv_systab_phys,	"UVsystab"	},
 #endif
+	{EFI_CC_BLOB_GUID,		&cc_blob_phys,		"CC blob"	},
 	{},
 };
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 6b5d36babfcc..75aeb2a56888 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -344,6 +344,7 @@ void efi_native_runtime_setup(void);
 #define EFI_CERT_SHA256_GUID			EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28)
 #define EFI_CERT_X509_GUID			EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72)
 #define EFI_CERT_X509_SHA256_GUID		EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
+#define EFI_CC_BLOB_GUID			EFI_GUID(0x067b1f5f, 0xcf26, 0x44c5, 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42)
 
 /*
  * This GUID is used to pass to the kernel proper the struct screen_info
diff --git a/include/linux/snp-guest.h b/include/linux/snp-guest.h
new file mode 100644
index 000000000000..32f70605b52c
--- /dev/null
+++ b/include/linux/snp-guest.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AMD Secure Encrypted Virtualization (SEV) driver interface
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Brijesh Singh <brijesh.singh@amd.com>
+ *
+ * SEV API spec is available at https://developer.amd.com/sev
+ */
+
+#ifndef __LINUX_SNP_GUEST_H_
+#define __LINUX_SNP_GUEST_H_
+
+#include <linux/types.h>
+
+#define MAX_AUTHTAG_LEN		32
+#define VMPCK_KEY_LEN		32
+
+/*
+ * The secrets page contains 96-bytes of reserved field that can be used by
+ * the guest OS. The guest OS uses the area to save the message sequence
+ * number for each VMPL level.
+ */
+struct secrets_guest_priv {
+	u64 msg_seqno_0;
+	u64 msg_seqno_1;
+	u64 msg_seqno_2;
+	u64 msg_seqno_3;
+	u8 rsvd[64];
+} __packed;
+
+/* See the SNP spec secrets page layout section for the structure */
+struct snp_data_secrets_layout {
+	u32 version;
+	u32 imiEn:1;
+	u32 rsvd1:31;
+	u32 fms;
+	u32 rsvd2;
+	u8 gosvw[16];
+	u8 vmpck0[VMPCK_KEY_LEN];
+	u8 vmpck1[VMPCK_KEY_LEN];
+	u8 vmpck2[VMPCK_KEY_LEN];
+	u8 vmpck3[VMPCK_KEY_LEN];
+	struct secrets_guest_priv guest_priv;
+	u8 rsvd3[3840];
+} __packed;
+
+/* See SNP spec SNP_GUEST_REQUEST section for the structure */
+enum msg_type {
+	SNP_MSG_TYPE_INVALID = 0,
+	SNP_MSG_CPUID_REQ,
+	SNP_MSG_CPUID_RSP,
+	SNP_MSG_KEY_REQ,
+	SNP_MSG_KEY_RSP,
+	SNP_MSG_REPORT_REQ,
+	SNP_MSG_REPORT_RSP,
+	SNP_MSG_EXPORT_REQ,
+	SNP_MSG_EXPORT_RSP,
+	SNP_MSG_IMPORT_REQ,
+	SNP_MSG_IMPORT_RSP,
+	SNP_MSG_ABSORB_REQ,
+	SNP_MSG_ABSORB_RSP,
+	SNP_MSG_VMRK_REQ,
+	SNP_MSG_VMRK_RSP,
+
+	SNP_MSG_TYPE_MAX
+};
+
+enum aead_algo {
+	SNP_AEAD_INVALID,
+	SNP_AEAD_AES_256_GCM,
+};
+
+struct snp_guest_msg_hdr {
+	u8 authtag[MAX_AUTHTAG_LEN];
+	u64 msg_seqno;
+	u8 rsvd1[8];
+	u8 algo;
+	u8 hdr_version;
+	u16 hdr_sz;
+	u8 msg_type;
+	u8 msg_version;
+	u16 msg_sz;
+	u32 rsvd2;
+	u8 msg_vmpck;
+	u8 rsvd3[35];
+} __packed;
+
+struct snp_guest_msg {
+	struct snp_guest_msg_hdr hdr;
+	u8 payload[4000];
+} __packed;
+
+struct snp_msg_report_req {
+	u8 data[64];
+	u32 vmpl;
+	u8 rsvd[28];
+} __packed;
+
+enum vmgexit_type {
+	SNP_GUEST_REQUEST,
+	SNP_EXTENDED_GUEST_REQUEST,
+
+	GUEST_REQUEST_MAX
+};
+
+struct snp_guest_request_data {
+	unsigned long req_gpa;
+	unsigned long resp_gpa;
+	unsigned long data_gpa;
+	unsigned int data_npages;
+};
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+unsigned long snp_issue_guest_request(int vmgexit_type, struct snp_guest_request_data *input);
+#else
+
+static inline unsigned long snp_issue_guest_request(int type, struct snp_guest_request_data *input)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_AMD_MEM_ENCRYPT */
+#endif /* __LINUX_SNP_GUEST_H__ */
-- 
2.17.1


  parent reply	other threads:[~2021-04-30 12:18 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-30 12:15 [PATCH Part1 RFC v2 00/20] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
2021-04-30 12:15 ` [PATCH Part1 RFC v2 01/20] x86/sev: Define the GHCB MSR protocol for AP reset hold Brijesh Singh
2021-04-30 12:15 ` [PATCH Part1 RFC v2 02/20] x86/sev: Save the negotiated GHCB version Brijesh Singh
2021-05-11  9:23   ` Borislav Petkov
2021-05-11 18:29     ` Brijesh Singh
2021-05-11 18:41       ` Borislav Petkov
2021-05-12 14:03         ` Brijesh Singh
2021-05-12 14:31           ` Borislav Petkov
2021-05-12 15:03             ` Brijesh Singh
2021-04-30 12:15 ` [PATCH Part1 RFC v2 03/20] x86/sev: Add support for hypervisor feature VMGEXIT Brijesh Singh
2021-05-11 10:01   ` Borislav Petkov
2021-05-11 18:53     ` Brijesh Singh
2021-05-17 14:40       ` Borislav Petkov
2021-04-30 12:16 ` [PATCH Part1 RFC v2 04/20] x86/sev: Increase the GHCB protocol version Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 05/20] x86/sev: Define SNP Page State Change VMGEXIT structure Brijesh Singh
2021-05-18 10:41   ` Borislav Petkov
2021-05-18 15:06     ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 06/20] x86/sev: Define SNP guest request NAE events Brijesh Singh
2021-05-18 10:45   ` Borislav Petkov
2021-05-18 13:42     ` Brijesh Singh
2021-05-18 13:54       ` Borislav Petkov
2021-05-18 14:13         ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 07/20] x86/sev: Define error codes for reason set 1 Brijesh Singh
2021-05-18 11:05   ` Borislav Petkov
2021-04-30 12:16 ` [PATCH Part1 RFC v2 08/20] x86/mm: Add sev_snp_active() helper Brijesh Singh
2021-05-18 18:11   ` Borislav Petkov
2021-05-19 17:28     ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 09/20] x86/sev: check SEV-SNP features support Brijesh Singh
2021-05-20 16:02   ` Borislav Petkov
2021-05-20 17:40     ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 10/20] x86/sev: Add a helper for the PVALIDATE instruction Brijesh Singh
2021-04-30 13:05   ` Brijesh Singh
2021-05-20 17:32     ` Borislav Petkov
2021-05-20 17:44       ` Brijesh Singh
2021-05-20 17:51         ` Borislav Petkov
2021-05-20 17:57           ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 11/20] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
2021-05-20 17:52   ` Borislav Petkov
2021-05-20 18:05     ` Brijesh Singh
2021-05-25 10:18       ` Borislav Petkov
2021-04-30 12:16 ` [PATCH Part1 RFC v2 12/20] x86/compressed: Register GHCB memory when SEV-SNP is active Brijesh Singh
2021-05-25 10:41   ` Borislav Petkov
2021-04-30 12:16 ` [PATCH Part1 RFC v2 13/20] x86/sev: " Brijesh Singh
2021-05-25 11:11   ` Borislav Petkov
2021-05-25 14:28     ` Brijesh Singh
2021-05-25 14:35       ` Borislav Petkov
2021-05-25 14:47         ` Brijesh Singh
2021-05-26  9:57           ` Borislav Petkov
2021-05-26 13:23             ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 14/20] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
2021-05-26 10:39   ` Borislav Petkov
2021-05-26 13:34     ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 15/20] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 16/20] x86/kernel: Validate rom memory before accessing when SEV-SNP is active Brijesh Singh
2021-05-27 11:49   ` Borislav Petkov
2021-05-27 12:12     ` Brijesh Singh
2021-05-27 12:23       ` Borislav Petkov
2021-05-27 12:56         ` Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 17/20] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
2021-04-30 12:16 ` [PATCH Part1 RFC v2 18/20] x86/boot: Add Confidential Computing address to setup_header Brijesh Singh
2021-04-30 12:16 ` Brijesh Singh [this message]
2021-04-30 12:16 ` [PATCH Part1 RFC v2 20/20] virt: Add SEV-SNP guest driver Brijesh Singh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210430121616.2295-20-brijesh.singh@amd.com \
    --to=brijesh.singh@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=hpa@zytor.com \
    --cc=jroedel@suse.de \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rientjes@google.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=thomas.lendacky@amd.com \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).