[PATCH Part1 RFC v4 33/36] x86/sev: Register SNP guest request platform device

Brijesh Singh
2021-07-07T18:18:42Z

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.

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 location is passed through the setup_data.

Create a platform device that the SNP guest driver can bind to get the
platform resources such as encryption key and message id to use to
communicate with the PSP. The SNP guest driver can provide userspace
interface to get the attestation report, key derivation, extended
attestation report etc.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
arch/x86/kernel/sev.c | 68 +++++++++++++++++++++++++++++++++++++++
include/linux/sev-guest.h | 5 +++
2 files changed, 73 insertions(+)

diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index 663cfe96c186..566625707132 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -22,6 +22,8 @@
#include <linux/log2.h>
#include <linux/efi.h>
#include <linux/sev-guest.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>

#include <asm/cpu_entry_area.h>
#include <asm/stacktrace.h>
@@ -37,6 +39,7 @@
#include <asm/apic.h>
#include <asm/efi.h>
#include <asm/cpuid-indexed.h>
+#include <asm/setup.h>

#include "sev-internal.h"

@@ -2160,3 +2163,68 @@ int snp_issue_guest_request(int type, struct snp_guest_request_data *input, unsi
return ret;
}
EXPORT_SYMBOL_GPL(snp_issue_guest_request);
+
+static struct platform_device guest_req_device = {
+ .name = "snp-guest",
+ .id = -1,
+};
+
+static u64 find_secrets_paddr(void)
+{
+ u64 pa_data = boot_params.cc_blob_address;
+ struct cc_blob_sev_info info;
+ void *map;
+
+ /*
+ * The CC blob contains the address of the secrets page, check if the
+ * blob is present.
+ */
+ if (!pa_data)
+ return 0;
+
+ map = early_memremap(pa_data, sizeof(info));
+ memcpy(&info, map, sizeof(info));
+ early_memunmap(map, sizeof(info));
+
+ /* Verify that secrets page address is passed */
+ if ((info.secrets_phys && (info.secrets_len == PAGE_SIZE)))
+ return info.secrets_phys;
+
+ return 0;
+}
+
+static int __init add_snp_guest_request(void)
+{
+ struct snp_secrets_page_layout *layout;
+ struct snp_guest_platform_data data;
+
+ if (!sev_feature_enabled(SEV_SNP))
+ return -ENODEV;
+
+ snp_secrets_phys = find_secrets_paddr();
+ if (!snp_secrets_phys)
+ return -ENODEV;
+
+ layout = snp_map_secrets_page();
+ if (layout == NULL)
+ return -ENODEV;
+
+ /*
+ * The secrets page contains three VMPCK that can be used for
+ * communicating with the PSP. We choose the VMPCK0 to encrypt guest
+ * messages send and receive by the Linux. Provide the key and
+ * id through the platform data to the driver.
+ */
+ data.vmpck_id = 0;
+ memcpy_fromio(data.vmpck, layout->vmpck0, sizeof(data.vmpck));
+
+ iounmap(layout);
+
+ platform_device_add_data(&guest_req_device, &data, sizeof(data));
+
+ if (!platform_device_register(&guest_req_device))
+ dev_info(&guest_req_device.dev, "secret phys 0x%llx\n", snp_secrets_phys);
+
+ return 0;
+}
+device_initcall(add_snp_guest_request);
diff --git a/include/linux/sev-guest.h b/include/linux/sev-guest.h
index 5f6c4d634e1f..d13f2e2cd367 100644
--- a/include/linux/sev-guest.h
+++ b/include/linux/sev-guest.h
@@ -68,6 +68,11 @@ struct snp_guest_request_data {
unsigned int data_npages;
};

+struct snp_guest_platform_data {
+ u8 vmpck_id;
+ char vmpck[VMPCK_KEY_LEN];
+};
+
#ifdef CONFIG_AMD_MEM_ENCRYPT
int snp_issue_guest_request(int vmgexit_type, struct snp_guest_request_data *input,
unsigned long *fw_err);
--
2.17.1