Currently, the SEV guest driver is the only user of SNP guest messaging.
All routines for initializing SNP guest messaging are implemented within
the SEV guest driver. To add Secure TSC guest support, these initialization
routines need to be available during early boot.
Carve out common SNP guest messaging buffer allocations and message
initialization routines to core/sev.c and export them. These newly added
APIs set up the SNP message context (snp_msg_desc), which contains all the
necessary details for sending SNP guest messages.
At present, the SEV guest platform data structure is used to pass the
secrets page physical address to SEV guest driver. Since the secrets page
address is locally available to the initialization routine, use the cached
address. Remove the unused SEV guest platform data structure.
Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
---
arch/x86/include/asm/sev.h | 71 ++++++++-
arch/x86/coco/sev/core.c | 133 +++++++++++++++-
drivers/virt/coco/sev-guest/sev-guest.c | 195 +++---------------------
3 files changed, 215 insertions(+), 184 deletions(-)
diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
index 2e49c4a9e7fe..63c30f4d44d7 100644
--- a/arch/x86/include/asm/sev.h
+++ b/arch/x86/include/asm/sev.h
@@ -14,6 +14,7 @@
#include <asm/insn.h>
#include <asm/sev-common.h>
#include <asm/coco.h>
+#include <asm/set_memory.h>
#define GHCB_PROTOCOL_MIN 1ULL
#define GHCB_PROTOCOL_MAX 2ULL
@@ -170,10 +171,6 @@ struct snp_guest_msg {
u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)];
} __packed;
-struct sev_guest_platform_data {
- u64 secrets_gpa;
-};
-
struct snp_guest_req {
void *req_buf;
size_t req_sz;
@@ -253,6 +250,7 @@ struct snp_msg_desc {
u32 *os_area_msg_seqno;
u8 *vmpck;
+ int vmpck_id;
};
/*
@@ -438,6 +436,63 @@ u64 sev_get_status(void);
void sev_show_status(void);
void snp_update_svsm_ca(void);
+static inline void free_shared_pages(void *buf, size_t sz)
+{
+ unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
+ int ret;
+
+ if (!buf)
+ return;
+
+ ret = set_memory_encrypted((unsigned long)buf, npages);
+ if (ret) {
+ WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
+ return;
+ }
+
+ __free_pages(virt_to_page(buf), get_order(sz));
+}
+
+static inline void *alloc_shared_pages(size_t sz)
+{
+ unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
+ struct page *page;
+ int ret;
+
+ page = alloc_pages(GFP_KERNEL_ACCOUNT, get_order(sz));
+ if (!page)
+ return NULL;
+
+ ret = set_memory_decrypted((unsigned long)page_address(page), npages);
+ if (ret) {
+ pr_err("failed to mark page shared, ret=%d\n", ret);
+ __free_pages(page, get_order(sz));
+ return NULL;
+ }
+
+ return page_address(page);
+}
+
+static inline bool is_vmpck_empty(struct snp_msg_desc *mdesc)
+{
+ static const char zero_key[VMPCK_KEY_LEN] = {0};
+
+ if (mdesc->vmpck)
+ return !memcmp(mdesc->vmpck, zero_key, VMPCK_KEY_LEN);
+
+ return true;
+}
+
+int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id);
+struct snp_msg_desc *snp_msg_alloc(void);
+
+static inline void snp_msg_cleanup(struct snp_msg_desc *mdesc)
+{
+ mdesc->vmpck = NULL;
+ mdesc->os_area_msg_seqno = NULL;
+ kfree(mdesc->ctx);
+}
+
#else /* !CONFIG_AMD_MEM_ENCRYPT */
#define snp_vmpl 0
@@ -474,6 +529,14 @@ static inline u64 snp_get_unsupported_features(u64 status) { return 0; }
static inline u64 sev_get_status(void) { return 0; }
static inline void sev_show_status(void) { }
static inline void snp_update_svsm_ca(void) { }
+static inline void free_shared_pages(void *buf, size_t sz) { }
+static inline void *alloc_shared_pages(size_t sz) { return NULL; }
+static inline bool is_vmpck_empty(struct snp_msg_desc *mdesc) { return false; }
+
+static inline int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id) { return -1; }
+static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; }
+
+static inline void snp_msg_cleanup(struct snp_msg_desc *mdesc) { }
#endif /* CONFIG_AMD_MEM_ENCRYPT */
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index c7b4270d0e18..6ba13ae0b153 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -25,6 +25,7 @@
#include <linux/psp-sev.h>
#include <linux/dmi.h>
#include <uapi/linux/sev-guest.h>
+#include <crypto/gcm.h>
#include <asm/init.h>
#include <asm/cpu_entry_area.h>
@@ -95,6 +96,8 @@ static u64 sev_hv_features __ro_after_init;
/* Secrets page physical address from the CC blob */
static u64 secrets_pa __ro_after_init;
+static struct snp_msg_desc *snp_mdesc;
+
/* #VC handler runtime per-CPU data */
struct sev_es_runtime_data {
struct ghcb ghcb_page;
@@ -2445,15 +2448,9 @@ static struct platform_device sev_guest_device = {
static int __init snp_init_platform_device(void)
{
- struct sev_guest_platform_data data;
-
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return -ENODEV;
- data.secrets_gpa = secrets_pa;
- if (platform_device_add_data(&sev_guest_device, &data, sizeof(data)))
- return -ENODEV;
-
if (platform_device_register(&sev_guest_device))
return -ENODEV;
@@ -2532,3 +2529,127 @@ static int __init sev_sysfs_init(void)
}
arch_initcall(sev_sysfs_init);
#endif // CONFIG_SYSFS
+
+static u8 *get_vmpck(int id, struct snp_secrets_page *secrets, u32 **seqno)
+{
+ u8 *key = NULL;
+
+ switch (id) {
+ case 0:
+ *seqno = &secrets->os_area.msg_seqno_0;
+ key = secrets->vmpck0;
+ break;
+ case 1:
+ *seqno = &secrets->os_area.msg_seqno_1;
+ key = secrets->vmpck1;
+ break;
+ case 2:
+ *seqno = &secrets->os_area.msg_seqno_2;
+ key = secrets->vmpck2;
+ break;
+ case 3:
+ *seqno = &secrets->os_area.msg_seqno_3;
+ key = secrets->vmpck3;
+ break;
+ default:
+ break;
+ }
+
+ return key;
+}
+
+static struct aesgcm_ctx *snp_init_crypto(u8 *key, size_t keylen)
+{
+ struct aesgcm_ctx *ctx;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
+ if (!ctx)
+ return NULL;
+
+ if (aesgcm_expandkey(ctx, key, keylen, AUTHTAG_LEN)) {
+ pr_err("Crypto context initialization failed\n");
+ kfree(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id)
+{
+ /* Adjust the default VMPCK key based on the executing VMPL level */
+ if (vmpck_id == -1)
+ vmpck_id = snp_vmpl;
+
+ mdesc->vmpck = get_vmpck(vmpck_id, mdesc->secrets, &mdesc->os_area_msg_seqno);
+ if (!mdesc->vmpck) {
+ pr_err("Invalid VMPCK%d communication key\n", vmpck_id);
+ return -EINVAL;
+ }
+
+ /* Verify that VMPCK is not zero. */
+ if (is_vmpck_empty(mdesc)) {
+ pr_err("Empty VMPCK%d communication key\n", vmpck_id);
+ return -EINVAL;
+ }
+
+ mdesc->vmpck_id = vmpck_id;
+
+ mdesc->ctx = snp_init_crypto(mdesc->vmpck, VMPCK_KEY_LEN);
+ if (!mdesc->ctx)
+ return -ENOMEM;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snp_msg_init);
+
+struct snp_msg_desc *snp_msg_alloc(void)
+{
+ struct snp_msg_desc *mdesc;
+
+ BUILD_BUG_ON(sizeof(struct snp_guest_msg) > PAGE_SIZE);
+
+ if (snp_mdesc)
+ return snp_mdesc;
+
+ mdesc = kzalloc(sizeof(struct snp_msg_desc), GFP_KERNEL);
+ if (!mdesc)
+ return ERR_PTR(-ENOMEM);
+
+ mdesc->secrets = (__force struct snp_secrets_page *)ioremap_encrypted(secrets_pa,
+ PAGE_SIZE);
+ if (!mdesc->secrets)
+ return ERR_PTR(-ENODEV);
+
+ /* Allocate the shared page used for the request and response message. */
+ mdesc->request = alloc_shared_pages(sizeof(struct snp_guest_msg));
+ if (!mdesc->request)
+ goto e_unmap;
+
+ mdesc->response = alloc_shared_pages(sizeof(struct snp_guest_msg));
+ if (!mdesc->response)
+ goto e_free_request;
+
+ mdesc->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE);
+ if (!mdesc->certs_data)
+ goto e_free_response;
+
+ /* initial the input address for guest request */
+ mdesc->input.req_gpa = __pa(mdesc->request);
+ mdesc->input.resp_gpa = __pa(mdesc->response);
+ mdesc->input.data_gpa = __pa(mdesc->certs_data);
+
+ snp_mdesc = mdesc;
+
+ return mdesc;
+
+e_free_response:
+ free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
+e_free_request:
+ free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
+e_unmap:
+ iounmap((__force void __iomem *)mdesc->secrets);
+
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(snp_msg_alloc);
diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index fca5c45ed5cd..862fc74452ac 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -63,16 +63,6 @@ MODULE_PARM_DESC(vmpck_id, "The VMPCK ID to use when communicating with the PSP.
/* Mutex to serialize the shared buffer access and command handling. */
static DEFINE_MUTEX(snp_cmd_mutex);
-static bool is_vmpck_empty(struct snp_msg_desc *mdesc)
-{
- char zero_key[VMPCK_KEY_LEN] = {0};
-
- if (mdesc->vmpck)
- return !memcmp(mdesc->vmpck, zero_key, VMPCK_KEY_LEN);
-
- return true;
-}
-
/*
* If an error is received from the host or AMD Secure Processor (ASP) there
* are two options. Either retry the exact same encrypted request or discontinue
@@ -93,7 +83,7 @@ static bool is_vmpck_empty(struct snp_msg_desc *mdesc)
static void snp_disable_vmpck(struct snp_msg_desc *mdesc)
{
pr_alert("Disabling VMPCK%d communication key to prevent IV reuse.\n",
- vmpck_id);
+ mdesc->vmpck_id);
memzero_explicit(mdesc->vmpck, VMPCK_KEY_LEN);
mdesc->vmpck = NULL;
}
@@ -147,23 +137,6 @@ static inline struct snp_guest_dev *to_snp_dev(struct file *file)
return container_of(dev, struct snp_guest_dev, misc);
}
-static struct aesgcm_ctx *snp_init_crypto(u8 *key, size_t keylen)
-{
- struct aesgcm_ctx *ctx;
-
- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
- if (!ctx)
- return NULL;
-
- if (aesgcm_expandkey(ctx, key, keylen, AUTHTAG_LEN)) {
- pr_err("Crypto context initialization failed\n");
- kfree(ctx);
- return NULL;
- }
-
- return ctx;
-}
-
static int verify_and_dec_payload(struct snp_msg_desc *mdesc, struct snp_guest_req *req)
{
struct snp_guest_msg *resp_msg = &mdesc->secret_response;
@@ -414,7 +387,7 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io
req.msg_version = arg->msg_version;
req.msg_type = SNP_MSG_REPORT_REQ;
- req.vmpck_id = vmpck_id;
+ req.vmpck_id = mdesc->vmpck_id;
req.req_buf = report_req;
req.req_sz = sizeof(*report_req);
req.resp_buf = report_resp->data;
@@ -461,7 +434,7 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque
req.msg_version = arg->msg_version;
req.msg_type = SNP_MSG_KEY_REQ;
- req.vmpck_id = vmpck_id;
+ req.vmpck_id = mdesc->vmpck_id;
req.req_buf = derived_key_req;
req.req_sz = sizeof(*derived_key_req);
req.resp_buf = buf;
@@ -539,7 +512,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
req.msg_version = arg->msg_version;
req.msg_type = SNP_MSG_REPORT_REQ;
- req.vmpck_id = vmpck_id;
+ req.vmpck_id = mdesc->vmpck_id;
req.req_buf = &report_req->data;
req.req_sz = sizeof(report_req->data);
req.resp_buf = report_resp->data;
@@ -616,76 +589,11 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
return ret;
}
-static void free_shared_pages(void *buf, size_t sz)
-{
- unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
- int ret;
-
- if (!buf)
- return;
-
- ret = set_memory_encrypted((unsigned long)buf, npages);
- if (ret) {
- WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
- return;
- }
-
- __free_pages(virt_to_page(buf), get_order(sz));
-}
-
-static void *alloc_shared_pages(struct device *dev, size_t sz)
-{
- unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
- struct page *page;
- int ret;
-
- page = alloc_pages(GFP_KERNEL_ACCOUNT, get_order(sz));
- if (!page)
- return NULL;
-
- ret = set_memory_decrypted((unsigned long)page_address(page), npages);
- if (ret) {
- dev_err(dev, "failed to mark page shared, ret=%d\n", ret);
- __free_pages(page, get_order(sz));
- return NULL;
- }
-
- return page_address(page);
-}
-
static const struct file_operations snp_guest_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = snp_guest_ioctl,
};
-static u8 *get_vmpck(int id, struct snp_secrets_page *secrets, u32 **seqno)
-{
- u8 *key = NULL;
-
- switch (id) {
- case 0:
- *seqno = &secrets->os_area.msg_seqno_0;
- key = secrets->vmpck0;
- break;
- case 1:
- *seqno = &secrets->os_area.msg_seqno_1;
- key = secrets->vmpck1;
- break;
- case 2:
- *seqno = &secrets->os_area.msg_seqno_2;
- key = secrets->vmpck2;
- break;
- case 3:
- *seqno = &secrets->os_area.msg_seqno_3;
- key = secrets->vmpck3;
- break;
- default:
- break;
- }
-
- return key;
-}
-
struct snp_msg_report_resp_hdr {
u32 status;
u32 report_size;
@@ -979,13 +887,10 @@ static void unregister_sev_tsm(void *data)
static int __init sev_guest_probe(struct platform_device *pdev)
{
- struct sev_guest_platform_data *data;
- struct snp_secrets_page *secrets;
struct device *dev = &pdev->dev;
struct snp_guest_dev *snp_dev;
struct snp_msg_desc *mdesc;
struct miscdevice *misc;
- void __iomem *mapping;
int ret;
BUILD_BUG_ON(sizeof(struct snp_guest_msg) > PAGE_SIZE);
@@ -993,115 +898,57 @@ static int __init sev_guest_probe(struct platform_device *pdev)
if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
return -ENODEV;
- if (!dev->platform_data)
- return -ENODEV;
-
- data = (struct sev_guest_platform_data *)dev->platform_data;
- mapping = ioremap_encrypted(data->secrets_gpa, PAGE_SIZE);
- if (!mapping)
- return -ENODEV;
-
- secrets = (__force void *)mapping;
-
- ret = -ENOMEM;
snp_dev = devm_kzalloc(&pdev->dev, sizeof(struct snp_guest_dev), GFP_KERNEL);
if (!snp_dev)
- goto e_unmap;
-
- mdesc = devm_kzalloc(&pdev->dev, sizeof(struct snp_msg_desc), GFP_KERNEL);
- if (!mdesc)
- goto e_unmap;
-
- /* Adjust the default VMPCK key based on the executing VMPL level */
- if (vmpck_id == -1)
- vmpck_id = snp_vmpl;
+ return -ENOMEM;
- ret = -EINVAL;
- mdesc->vmpck = get_vmpck(vmpck_id, secrets, &mdesc->os_area_msg_seqno);
- if (!mdesc->vmpck) {
- dev_err(dev, "Invalid VMPCK%d communication key\n", vmpck_id);
- goto e_unmap;
- }
+ mdesc = snp_msg_alloc();
+ if (IS_ERR_OR_NULL(mdesc))
+ return -ENOMEM;
- /* Verify that VMPCK is not zero. */
- if (is_vmpck_empty(mdesc)) {
- dev_err(dev, "Empty VMPCK%d communication key\n", vmpck_id);
- goto e_unmap;
- }
+ ret = snp_msg_init(mdesc, vmpck_id);
+ if (ret)
+ return -EIO;
platform_set_drvdata(pdev, snp_dev);
snp_dev->dev = dev;
- mdesc->secrets = secrets;
-
- /* Allocate the shared page used for the request and response message. */
- mdesc->request = alloc_shared_pages(dev, sizeof(struct snp_guest_msg));
- if (!mdesc->request)
- goto e_unmap;
-
- mdesc->response = alloc_shared_pages(dev, sizeof(struct snp_guest_msg));
- if (!mdesc->response)
- goto e_free_request;
-
- mdesc->certs_data = alloc_shared_pages(dev, SEV_FW_BLOB_MAX_SIZE);
- if (!mdesc->certs_data)
- goto e_free_response;
-
- ret = -EIO;
- mdesc->ctx = snp_init_crypto(mdesc->vmpck, VMPCK_KEY_LEN);
- if (!mdesc->ctx)
- goto e_free_cert_data;
misc = &snp_dev->misc;
misc->minor = MISC_DYNAMIC_MINOR;
misc->name = DEVICE_NAME;
misc->fops = &snp_guest_fops;
- /* Initialize the input addresses for guest request */
- mdesc->input.req_gpa = __pa(mdesc->request);
- mdesc->input.resp_gpa = __pa(mdesc->response);
- mdesc->input.data_gpa = __pa(mdesc->certs_data);
-
/* Set the privlevel_floor attribute based on the vmpck_id */
- sev_tsm_ops.privlevel_floor = vmpck_id;
+ sev_tsm_ops.privlevel_floor = mdesc->vmpck_id;
ret = tsm_register(&sev_tsm_ops, snp_dev);
if (ret)
- goto e_free_cert_data;
+ goto e_msg_init;
ret = devm_add_action_or_reset(&pdev->dev, unregister_sev_tsm, NULL);
if (ret)
- goto e_free_cert_data;
+ goto e_msg_init;
ret = misc_register(misc);
if (ret)
- goto e_free_ctx;
+ goto e_msg_init;
snp_dev->msg_desc = mdesc;
- dev_info(dev, "Initialized SEV guest driver (using VMPCK%d communication key)\n", vmpck_id);
+ dev_info(dev, "Initialized SEV guest driver (using VMPCK%d communication key)\n",
+ mdesc->vmpck_id);
return 0;
-e_free_ctx:
- kfree(mdesc->ctx);
-e_free_cert_data:
- free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE);
-e_free_response:
- free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
-e_free_request:
- free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
-e_unmap:
- iounmap(mapping);
+e_msg_init:
+ snp_msg_cleanup(mdesc);
+
return ret;
}
static void __exit sev_guest_remove(struct platform_device *pdev)
{
struct snp_guest_dev *snp_dev = platform_get_drvdata(pdev);
- struct snp_msg_desc *mdesc = snp_dev->msg_desc;
- free_shared_pages(mdesc->certs_data, SEV_FW_BLOB_MAX_SIZE);
- free_shared_pages(mdesc->response, sizeof(struct snp_guest_msg));
- free_shared_pages(mdesc->request, sizeof(struct snp_guest_msg));
- kfree(mdesc->ctx);
+ snp_msg_cleanup(snp_dev->msg_desc);
misc_deregister(&snp_dev->misc);
}
--
2.34.1
On Mon, Oct 28, 2024 at 11:04:19AM +0530, Nikunj A Dadhania wrote: > Currently, the SEV guest driver is the only user of SNP guest messaging. > All routines for initializing SNP guest messaging are implemented within > the SEV guest driver. To add Secure TSC guest support, these initialization > routines need to be available during early boot. > > Carve out common SNP guest messaging buffer allocations and message > initialization routines to core/sev.c and export them. These newly added > APIs set up the SNP message context (snp_msg_desc), which contains all the > necessary details for sending SNP guest messages. > > At present, the SEV guest platform data structure is used to pass the > secrets page physical address to SEV guest driver. Since the secrets page > address is locally available to the initialization routine, use the cached > address. Remove the unused SEV guest platform data structure. Do not talk about *what* the patch is doing in the commit message - that should be obvious from the diff itself. Rather, concentrate on the *why* it needs to be done. Imagine one fine day you're doing git archeology, you find the place in the code about which you want to find out why it was changed the way it is now. You do git annotate <filename> ... find the line, see the commit id and you do: git show <commit id> You read the commit message and there's just gibberish and nothing's explaining *why* that change was done. And you start scratching your head, trying to figure out why. See what I mean? > Signed-off-by: Nikunj A Dadhania <nikunj@amd.com> > Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> > --- > arch/x86/include/asm/sev.h | 71 ++++++++- > arch/x86/coco/sev/core.c | 133 +++++++++++++++- > drivers/virt/coco/sev-guest/sev-guest.c | 195 +++--------------------- > 3 files changed, 215 insertions(+), 184 deletions(-) > > diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h > index 2e49c4a9e7fe..63c30f4d44d7 100644 > --- a/arch/x86/include/asm/sev.h > +++ b/arch/x86/include/asm/sev.h > @@ -14,6 +14,7 @@ > #include <asm/insn.h> > #include <asm/sev-common.h> > #include <asm/coco.h> > +#include <asm/set_memory.h> > > #define GHCB_PROTOCOL_MIN 1ULL > #define GHCB_PROTOCOL_MAX 2ULL > @@ -170,10 +171,6 @@ struct snp_guest_msg { > u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)]; > } __packed; > > -struct sev_guest_platform_data { > - u64 secrets_gpa; > -}; > - > struct snp_guest_req { > void *req_buf; > size_t req_sz; > @@ -253,6 +250,7 @@ struct snp_msg_desc { > > u32 *os_area_msg_seqno; > u8 *vmpck; > + int vmpck_id; > }; > > /* > @@ -438,6 +436,63 @@ u64 sev_get_status(void); > void sev_show_status(void); > void snp_update_svsm_ca(void); > > +static inline void free_shared_pages(void *buf, size_t sz) A function with a generic name exported in a header?! First of all, why is it in a header? Then, why isn't it called something "sev_" or so...? Same holds true for all the below. > + unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT; > + int ret; > + > + if (!buf) > + return; > + > + ret = set_memory_encrypted((unsigned long)buf, npages); > + if (ret) { > + WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n"); > + return; > + } > + > + __free_pages(virt_to_page(buf), get_order(sz)); > +} ... > +static struct aesgcm_ctx *snp_init_crypto(u8 *key, size_t keylen) > +{ > + struct aesgcm_ctx *ctx; > + > + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); > + if (!ctx) > + return NULL; > + > + if (aesgcm_expandkey(ctx, key, keylen, AUTHTAG_LEN)) { ld: vmlinux.o: in function `snp_init_crypto': /home/boris/kernel/2nd/linux/arch/x86/coco/sev/core.c:2700:(.text+0x1fa3): undefined reference to `aesgcm_expandkey' make[2]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1 make[1]: *** [/mnt/kernel/kernel/2nd/linux/Makefile:1166: vmlinux] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:224: __sub-make] Error 2 I'll stop here until you fix those. Btw, tip patches are done against tip/master - not against the branch they get queued in. Thx. -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette
Hi Boris, On 10/29/2024 11:13 PM, Borislav Petkov wrote: > On Mon, Oct 28, 2024 at 11:04:19AM +0530, Nikunj A Dadhania wrote: >> Currently, the SEV guest driver is the only user of SNP guest messaging. >> All routines for initializing SNP guest messaging are implemented within >> the SEV guest driver. To add Secure TSC guest support, these initialization >> routines need to be available during early boot. The above paragraph explains why the change is being done. >> >> Carve out common SNP guest messaging buffer allocations and message >> initialization routines to core/sev.c and export them. These newly added >> APIs set up the SNP message context (snp_msg_desc), which contains all the >> necessary details for sending SNP guest messages. This explains how it is being done, which I think is useful. However, if you think otherwise, I can remove. >> At present, the SEV guest platform data structure is used to pass the >> secrets page physical address to SEV guest driver. Since the secrets page >> address is locally available to the initialization routine, use the cached >> address. Remove the unused SEV guest platform data structure. In the above paragraph I tried to explains why I have removed sev_guest_platform_data. > > Do not talk about *what* the patch is doing in the commit message - that > should be obvious from the diff itself. Rather, concentrate on the *why* > it needs to be done. > > Imagine one fine day you're doing git archeology, you find the place in > the code about which you want to find out why it was changed the way it > is now. > > You do git annotate <filename> ... find the line, see the commit id and > you do: > > git show <commit id> > > You read the commit message and there's just gibberish and nothing's > explaining *why* that change was done. And you start scratching your > head, trying to figure out why. > > See what I mean? People have different styles of writing, as long as we are capturing the required information, IMHO, it should be fine. Let me try to repharse the commit message again: x86/sev: Carve out and export SNP guest messaging init routines Currently, the sev-guest driver is the only user of SNP guest messaging. All routines for initializing SNP guest messaging are implemented within the sev-guest driver and are not available during early boot. In prepratation for adding Secure TSC guest support, carve out APIs to allocate and initialize guest messaging descriptor context and make it part of coco/sev/core.c. As there is no user of sev_guest_platform_data anymore, remove the structure. Signed-off-by: Nikunj A Dadhania <nikunj@amd.com> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> > >> Signed-off-by: Nikunj A Dadhania <nikunj@amd.com> >> Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com> >> --- >> arch/x86/include/asm/sev.h | 71 ++++++++- >> arch/x86/coco/sev/core.c | 133 +++++++++++++++- >> drivers/virt/coco/sev-guest/sev-guest.c | 195 +++--------------------- >> 3 files changed, 215 insertions(+), 184 deletions(-) >> >> diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h >> index 2e49c4a9e7fe..63c30f4d44d7 100644 >> --- a/arch/x86/include/asm/sev.h >> +++ b/arch/x86/include/asm/sev.h >> @@ -14,6 +14,7 @@ >> #include <asm/insn.h> >> #include <asm/sev-common.h> >> #include <asm/coco.h> >> +#include <asm/set_memory.h> >> >> #define GHCB_PROTOCOL_MIN 1ULL >> #define GHCB_PROTOCOL_MAX 2ULL >> @@ -170,10 +171,6 @@ struct snp_guest_msg { >> u8 payload[PAGE_SIZE - sizeof(struct snp_guest_msg_hdr)]; >> } __packed; >> >> -struct sev_guest_platform_data { >> - u64 secrets_gpa; >> -}; >> - >> struct snp_guest_req { >> void *req_buf; >> size_t req_sz; >> @@ -253,6 +250,7 @@ struct snp_msg_desc { >> >> u32 *os_area_msg_seqno; >> u8 *vmpck; >> + int vmpck_id; >> }; >> >> /* >> @@ -438,6 +436,63 @@ u64 sev_get_status(void); >> void sev_show_status(void); >> void snp_update_svsm_ca(void); >> >> +static inline void free_shared_pages(void *buf, size_t sz) > > A function with a generic name exported in a header?! > > First of all, why is it in a header? > > Then, why isn't it called something "sev_" or so...? > > Same holds true for all the below. Sure, will update it accordingly in my next version. > >> + unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT; >> + int ret; >> + >> + if (!buf) >> + return; >> + >> + ret = set_memory_encrypted((unsigned long)buf, npages); >> + if (ret) { >> + WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n"); >> + return; >> + } >> + >> + __free_pages(virt_to_page(buf), get_order(sz)); >> +} > > ... > >> +static struct aesgcm_ctx *snp_init_crypto(u8 *key, size_t keylen) >> +{ >> + struct aesgcm_ctx *ctx; >> + >> + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT); >> + if (!ctx) >> + return NULL; >> + >> + if (aesgcm_expandkey(ctx, key, keylen, AUTHTAG_LEN)) { > > ld: vmlinux.o: in function `snp_init_crypto': > /home/boris/kernel/2nd/linux/arch/x86/coco/sev/core.c:2700:(.text+0x1fa3): undefined reference to `aesgcm_expandkey' > make[2]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1 > make[1]: *** [/mnt/kernel/kernel/2nd/linux/Makefile:1166: vmlinux] Error 2 > make[1]: *** Waiting for unfinished jobs.... > make: *** [Makefile:224: __sub-make] Error 2 > > I'll stop here until you fix those. Sorry for this, I had sev-guest driver as in-built module in my config, so wasn't able to catch this in my per patch build script. The corresponding fix is in the following patch[1], during patch juggling it had landed there: diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2852fcd82cbd..6426b6d469a4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1556,6 +1556,7 @@ config AMD_MEM_ENCRYPT select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select UNACCEPTED_MEMORY + select CRYPTO_LIB_AESGCM help Say yes to enable support for the encryption of system memory. This requires an AMD processor that supports Secure Memory diff --git a/drivers/virt/coco/sev-guest/Kconfig b/drivers/virt/coco/sev-guest/Kconfig index 0b772bd921d8..a6405ab6c2c3 100644 --- a/drivers/virt/coco/sev-guest/Kconfig +++ b/drivers/virt/coco/sev-guest/Kconfig @@ -2,7 +2,6 @@ config SEV_GUEST tristate "AMD SEV Guest driver" default m depends on AMD_MEM_ENCRYPT - select CRYPTO_LIB_AESGCM select TSM_REPORTS help SEV-SNP firmware provides the guest a mechanism to communicate with > Btw, tip patches are done against tip/master - not against the branch they get > queued in. Sure, I will keep that in mind. Thanks for the review, Nikunj 1. https://lore.kernel.org/all/20241028053431.3439593-3-nikunj@amd.com/#Z31arch:x86:Kconfig
On Wed, Oct 30, 2024 at 10:14:45AM +0530, Nikunj A. Dadhania wrote: > >> Carve out common SNP guest messaging buffer allocations and message > >> initialization routines to core/sev.c and export them. These newly added > >> APIs set up the SNP message context (snp_msg_desc), which contains all the > >> necessary details for sending SNP guest messages. > > This explains how it is being done, which I think is useful. However, if you > think otherwise, I can remove. Useful why? It should be visible from the diff itself. Why do you have to explain your diff? If you feel the need to have to explain it, then *maybe* it needs splitting or simplifying or whatnot. > >> At present, the SEV guest platform data structure is used to pass the > >> secrets page physical address to SEV guest driver. Since the secrets page > >> address is locally available to the initialization routine, use the cached > >> address. Remove the unused SEV guest platform data structure. > > In the above paragraph I tried to explains why I have removed > sev_guest_platform_data. Probably ok. > People have different styles of writing, as long as we are capturing the > required information, IMHO, it should be fine. "... as long we are not writing what the patch does - which is visible from the diff itself, it should be fine." is what I would say. > Let me try to repharse the commit message again: > > x86/sev: Carve out and export SNP guest messaging init routines > > Currently, the sev-guest driver is the only user of SNP guest messaging. > All routines for initializing SNP guest messaging are implemented within > the sev-guest driver and are not available during early boot. In > prepratation for adding Secure TSC guest support, carve out APIs to > allocate and initialize guest messaging descriptor context and make it part > of coco/sev/core.c. As there is no user of sev_guest_platform_data anymore, > remove the structure. Yap, better. Btw, you can even use AI for help rephrasing it: -> Please simpliify this code change description by concentrating only on why the change is being done: <insert commit message here> ChatGPT: "This change is being made to allow the Secure TSC guest feature to access SNP guest messaging routines earlier in the boot process. By moving common SNP message initialization routines to a central location (core/sev.c) and exporting them, these routines become accessible for early boot needs. Additionally, since the secrets page address is now accessible within the initialization, the redundant SEV guest platform data structure has been removed." -> Do the same as the above but write it in imperative tone ChatGPT: "Enable Secure TSC guest support by moving the SNP guest messaging routines to core/sev.c, making them available during early boot. Export these routines to set up the SNP message context (snp_msg_desc) needed for guest messaging. Use the cached secrets page address in the initialization routine, and remove the unused SEV guest platform data structure." I think that's a good help to use at least as a starter for the final commit message. To sum up: I'd like the commit message to contain enough information to know *why* a change has been done. No rambling about what the patch does. > > ld: vmlinux.o: in function `snp_init_crypto': > > /home/boris/kernel/2nd/linux/arch/x86/coco/sev/core.c:2700:(.text+0x1fa3): undefined reference to `aesgcm_expandkey' > > make[2]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 1 > > make[1]: *** [/mnt/kernel/kernel/2nd/linux/Makefile:1166: vmlinux] Error 2 > > make[1]: *** Waiting for unfinished jobs.... > > make: *** [Makefile:224: __sub-make] Error 2 > > > > I'll stop here until you fix those. > > Sorry for this, I had sev-guest driver as in-built module in my config, so wasn't > able to catch this in my per patch build script. The corresponding fix is in the > following patch[1], during patch juggling it had landed there: > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index 2852fcd82cbd..6426b6d469a4 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -1556,6 +1556,7 @@ config AMD_MEM_ENCRYPT > select ARCH_HAS_CC_PLATFORM > select X86_MEM_ENCRYPT > select UNACCEPTED_MEMORY > + select CRYPTO_LIB_AESGCM Right, that is debatable. AMD memory encryption support cannot really depend on a crypto library - you can get it without it too - just won't get secure TSC but for simplicity's sake let's leave it that way for now. Because looking at this: config AMD_MEM_ENCRYPT bool "AMD Secure Memory Encryption (SME) support" depends on X86_64 && CPU_SUP_AMD depends on EFI_STUB select DMA_COHERENT_POOL select ARCH_USE_MEMREMAP_PROT select INSTRUCTION_DECODER select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select UNACCEPTED_MEMORY select CRYPTO_LIB_AESGCM that symbol is pulling in a lot of other stuff. I guess it is ok for now... -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette
© 2016 - 2024 Red Hat, Inc.