summaryrefslogtreecommitdiff
path: root/drivers/crypto/ccp/sev-dev.c
diff options
context:
space:
mode:
authorTom Lendacky <thomas.lendacky@amd.com>2024-01-26 07:11:17 +0300
committerBorislav Petkov (AMD) <bp@alien8.de>2024-01-29 22:34:18 +0300
commit7364a6fbca45f826952ea932699fb2171d06ee73 (patch)
tree795fec83f49062057dc885fbb0260c55c2f639fb /drivers/crypto/ccp/sev-dev.c
parent24512afa4336a1c14de750238abe32759cfba4b0 (diff)
downloadlinux-7364a6fbca45f826952ea932699fb2171d06ee73.tar.xz
crypto: ccp: Handle non-volatile INIT_EX data when SNP is enabled
For SEV/SEV-ES, a buffer can be used to access non-volatile data so it can be initialized from a file specified by the init_ex_path CCP module parameter instead of relying on the SPI bus for NV storage, and afterward the buffer can be read from to sync new data back to the file. When SNP is enabled, the pages comprising this buffer need to be set to firmware-owned in the RMP table before they can be accessed by firmware for subsequent updates to the initial contents. Implement that handling here. [ bp: Carve out allocation into a helper. ] Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Co-developed-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Michael Roth <michael.roth@amd.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20240126041126.1927228-18-michael.roth@amd.com
Diffstat (limited to 'drivers/crypto/ccp/sev-dev.c')
-rw-r--r--drivers/crypto/ccp/sev-dev.c67
1 files changed, 48 insertions, 19 deletions
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index 70aabd1d3d5f..5ec563611953 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -775,6 +775,48 @@ static void __sev_platform_init_handle_tmr(struct sev_device *sev)
}
}
+/*
+ * If an init_ex_path is provided allocate a buffer for the file and
+ * read in the contents. Additionally, if SNP is initialized, convert
+ * the buffer pages to firmware pages.
+ */
+static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
+{
+ struct page *page;
+ int rc;
+
+ if (!init_ex_path)
+ return 0;
+
+ if (sev_init_ex_buffer)
+ return 0;
+
+ page = alloc_pages(GFP_KERNEL, get_order(NV_LENGTH));
+ if (!page) {
+ dev_err(sev->dev, "SEV: INIT_EX NV memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ sev_init_ex_buffer = page_address(page);
+
+ rc = sev_read_init_ex_file();
+ if (rc)
+ return rc;
+
+ /* If SEV-SNP is initialized, transition to firmware page. */
+ if (sev->snp_initialized) {
+ unsigned long npages;
+
+ npages = 1UL << get_order(NV_LENGTH);
+ if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) {
+ dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
static int __sev_platform_init_locked(int *error)
{
int rc, psp_ret = SEV_RET_NO_FW_CALL;
@@ -790,11 +832,9 @@ static int __sev_platform_init_locked(int *error)
__sev_platform_init_handle_tmr(sev);
- if (sev_init_ex_buffer) {
- rc = sev_read_init_ex_file();
- if (rc)
- return rc;
- }
+ rc = __sev_platform_init_handle_init_ex_path(sev);
+ if (rc)
+ return rc;
rc = __sev_do_init_locked(&psp_ret);
if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) {
@@ -1693,8 +1733,9 @@ static void sev_firmware_shutdown(struct sev_device *sev)
}
if (sev_init_ex_buffer) {
- free_pages((unsigned long)sev_init_ex_buffer,
- get_order(NV_LENGTH));
+ __snp_free_firmware_pages(virt_to_page(sev_init_ex_buffer),
+ get_order(NV_LENGTH),
+ true);
sev_init_ex_buffer = NULL;
}
@@ -1748,18 +1789,6 @@ void sev_pci_init(void)
if (sev_update_firmware(sev->dev) == 0)
sev_get_api_version();
- /* If an init_ex_path is provided rely on INIT_EX for PSP initialization
- * instead of INIT.
- */
- if (init_ex_path) {
- sev_init_ex_buffer = sev_fw_alloc(NV_LENGTH);
- if (!sev_init_ex_buffer) {
- dev_err(sev->dev,
- "SEV: INIT_EX NV memory allocation failed\n");
- goto err;
- }
- }
-
/* Initialize the platform */
args.probe = true;
rc = sev_platform_init(&args);