[PATCH v9 09/24] virt: sev-guest: Carve out SNP guest messaging init/exit

From: Nikunj A Dadhania
Date: Fri May 31 2024 - 00:34:26 EST


In preparation for the movement of common code required for both SEV guest
driver and Secure TSC, carve out initializaton and cleanup routines.

While at it, the device pointer in alloc_shared_pages() is used only in the
print routines, replace dev_err() with pr_err() and drop the device pointer
from the function prototype.

Signed-off-by: Nikunj A Dadhania <nikunj@xxxxxxx>
---
drivers/virt/coco/sev-guest/sev-guest.c | 152 ++++++++++++++----------
1 file changed, 88 insertions(+), 64 deletions(-)

diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index 19ee85fcfd08..0ec376f7edec 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -150,6 +150,11 @@ static struct aesgcm_ctx *snp_init_crypto(struct snp_guest_dev *snp_dev)
struct aesgcm_ctx *ctx;
u8 *key;

+ if (is_vmpck_empty(snp_dev)) {
+ pr_err("VM communication key VMPCK%u is invalid\n", snp_dev->vmpck_id);
+ return NULL;
+ }
+
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL_ACCOUNT);
if (!ctx)
return NULL;
@@ -629,7 +634,7 @@ static void free_shared_pages(void *buf, size_t sz)
__free_pages(virt_to_page(buf), get_order(sz));
}

-static void *alloc_shared_pages(struct device *dev, size_t sz)
+static void *alloc_shared_pages(size_t sz)
{
unsigned int npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
struct page *page;
@@ -641,7 +646,7 @@ static void *alloc_shared_pages(struct device *dev, size_t sz)

ret = set_memory_decrypted((unsigned long)page_address(page), npages);
if (ret) {
- dev_err(dev, "failed to mark page shared, ret=%d\n", ret);
+ pr_err("failed to mark page shared, ret=%d\n", ret);
__free_pages(page, get_order(sz));
return NULL;
}
@@ -786,14 +791,80 @@ static void unregister_sev_tsm(void *data)
tsm_unregister(&sev_tsm_ops);
}

+static int snp_guest_messaging_init(struct snp_guest_dev *snp_dev, u64 secrets_gpa)
+{
+ int ret = -ENOMEM;
+
+ snp_dev->secrets = (__force void *)ioremap_encrypted(secrets_gpa, PAGE_SIZE);
+ if (!snp_dev->secrets) {
+ pr_err("Failed to map SNP secrets page.\n");
+ return ret;
+ }
+
+ /* Allocate secret request and response message for double buffering */
+ snp_dev->secret_request = kzalloc(SNP_GUEST_MSG_SIZE, GFP_KERNEL);
+ if (!snp_dev->secret_request)
+ goto e_unmap;
+
+ snp_dev->secret_response = kzalloc(SNP_GUEST_MSG_SIZE, GFP_KERNEL);
+ if (!snp_dev->secret_response)
+ goto e_free_secret_req;
+
+ /* Allocate the shared page used for the request and response message. */
+ snp_dev->request = alloc_shared_pages(SNP_GUEST_MSG_SIZE);
+ if (!snp_dev->request)
+ goto e_free_secret_resp;
+
+ snp_dev->response = alloc_shared_pages(SNP_GUEST_MSG_SIZE);
+ if (!snp_dev->response)
+ goto e_free_request;
+
+ /* Initialize the input addresses for guest request */
+ snp_dev->input.req_gpa = __pa(snp_dev->request);
+ snp_dev->input.resp_gpa = __pa(snp_dev->response);
+
+ ret = -EIO;
+ snp_dev->ctx = snp_init_crypto(snp_dev);
+ if (!snp_dev->ctx) {
+ pr_err("SNP crypto context initialization failed\n");
+ goto e_free_response;
+ }
+
+ return 0;
+
+e_free_response:
+ free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg));
+e_free_request:
+ free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg));
+e_free_secret_resp:
+ kfree(snp_dev->secret_response);
+e_free_secret_req:
+ kfree(snp_dev->secret_request);
+e_unmap:
+ iounmap(snp_dev->secrets);
+
+ return ret;
+}
+
+static void snp_guest_messaging_exit(struct snp_guest_dev *snp_dev)
+{
+ if (!snp_dev)
+ return;
+
+ kfree(snp_dev->ctx);
+ free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg));
+ free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg));
+ kfree(snp_dev->secret_response);
+ kfree(snp_dev->secret_request);
+ iounmap(snp_dev->secrets);
+}
+
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 miscdevice *misc;
- void __iomem *mapping;
int ret;

if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
@@ -803,69 +874,36 @@ static int __init sev_guest_probe(struct platform_device *pdev)
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;
+ return -ENOMEM;

ret = -EINVAL;
- snp_dev->secrets = secrets;
if (!assign_vmpck(snp_dev, vmpck_id)) {
dev_err(dev, "Invalid VMPCK%d communication key\n", vmpck_id);
- goto e_unmap;
+ return ret;
}

- /* Verify that VMPCK is not zero. */
- if (is_vmpck_empty(snp_dev)) {
- dev_err(dev, "Empty VMPCK%d communication key\n", snp_dev->vmpck_id);
- goto e_unmap;
+ if (snp_guest_messaging_init(snp_dev, data->secrets_gpa)) {
+ dev_err(dev, "Unable to setup SNP Guest messaging using VMPCK%u\n",
+ snp_dev->vmpck_id);
+ return ret;
}

platform_set_drvdata(pdev, snp_dev);
snp_dev->dev = dev;

- /* Allocate secret request and response message for double buffering */
- snp_dev->secret_request = kzalloc(SNP_GUEST_MSG_SIZE, GFP_KERNEL);
- if (!snp_dev->secret_request)
- goto e_unmap;
-
- snp_dev->secret_response = kzalloc(SNP_GUEST_MSG_SIZE, GFP_KERNEL);
- if (!snp_dev->secret_response)
- goto e_free_secret_req;
-
- /* Allocate the shared page used for the request and response message. */
- snp_dev->request = alloc_shared_pages(dev, SNP_GUEST_MSG_SIZE);
- if (!snp_dev->request)
- goto e_free_secret_resp;
-
- snp_dev->response = alloc_shared_pages(dev, SNP_GUEST_MSG_SIZE);
- if (!snp_dev->response)
- goto e_free_request;
-
- snp_dev->certs_data = alloc_shared_pages(dev, SEV_FW_BLOB_MAX_SIZE);
+ ret = -ENOMEM;
+ snp_dev->certs_data = alloc_shared_pages(SEV_FW_BLOB_MAX_SIZE);
if (!snp_dev->certs_data)
- goto e_free_response;
-
- ret = -EIO;
- snp_dev->ctx = snp_init_crypto(snp_dev);
- if (!snp_dev->ctx)
- goto e_free_cert_data;
+ goto e_cleanup_msg_init;

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 */
- snp_dev->input.req_gpa = __pa(snp_dev->request);
- snp_dev->input.resp_gpa = __pa(snp_dev->response);
-
ret = tsm_register(&sev_tsm_ops, snp_dev, &tsm_report_extra_type);
if (ret)
goto e_free_cert_data;
@@ -876,25 +914,15 @@ static int __init sev_guest_probe(struct platform_device *pdev)

ret = misc_register(misc);
if (ret)
- goto e_free_ctx;
+ goto e_free_cert_data;

dev_info(dev, "Initialized SEV guest driver (using VMPCK%d communication key)\n", vmpck_id);
return 0;

-e_free_ctx:
- kfree(snp_dev->ctx);
e_free_cert_data:
free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE);
-e_free_response:
- free_shared_pages(snp_dev->response, SNP_GUEST_MSG_SIZE);
-e_free_request:
- free_shared_pages(snp_dev->request, SNP_GUEST_MSG_SIZE);
-e_free_secret_resp:
- kfree(snp_dev->secret_response);
-e_free_secret_req:
- kfree(snp_dev->secret_request);
-e_unmap:
- iounmap(mapping);
+e_cleanup_msg_init:
+ snp_guest_messaging_exit(snp_dev);
return ret;
}

@@ -903,11 +931,7 @@ static void __exit sev_guest_remove(struct platform_device *pdev)
struct snp_guest_dev *snp_dev = platform_get_drvdata(pdev);

free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE);
- free_shared_pages(snp_dev->response, SNP_GUEST_MSG_SIZE);
- free_shared_pages(snp_dev->request, SNP_GUEST_MSG_SIZE);
- kfree(snp_dev->secret_response);
- kfree(snp_dev->secret_request);
- kfree(snp_dev->ctx);
+ snp_guest_messaging_exit(snp_dev);
misc_deregister(&snp_dev->misc);
}

--
2.34.1