Skip to content

Commit 7364a6f

Browse files
tlendackybp3tk0v
authored andcommitted
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 <[email protected]> Co-developed-by: Michael Roth <[email protected]> Signed-off-by: Michael Roth <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 24512af commit 7364a6f

File tree

1 file changed

+48
-19
lines changed

1 file changed

+48
-19
lines changed

drivers/crypto/ccp/sev-dev.c

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,48 @@ static void __sev_platform_init_handle_tmr(struct sev_device *sev)
775775
}
776776
}
777777

778+
/*
779+
* If an init_ex_path is provided allocate a buffer for the file and
780+
* read in the contents. Additionally, if SNP is initialized, convert
781+
* the buffer pages to firmware pages.
782+
*/
783+
static int __sev_platform_init_handle_init_ex_path(struct sev_device *sev)
784+
{
785+
struct page *page;
786+
int rc;
787+
788+
if (!init_ex_path)
789+
return 0;
790+
791+
if (sev_init_ex_buffer)
792+
return 0;
793+
794+
page = alloc_pages(GFP_KERNEL, get_order(NV_LENGTH));
795+
if (!page) {
796+
dev_err(sev->dev, "SEV: INIT_EX NV memory allocation failed\n");
797+
return -ENOMEM;
798+
}
799+
800+
sev_init_ex_buffer = page_address(page);
801+
802+
rc = sev_read_init_ex_file();
803+
if (rc)
804+
return rc;
805+
806+
/* If SEV-SNP is initialized, transition to firmware page. */
807+
if (sev->snp_initialized) {
808+
unsigned long npages;
809+
810+
npages = 1UL << get_order(NV_LENGTH);
811+
if (rmp_mark_pages_firmware(__pa(sev_init_ex_buffer), npages, false)) {
812+
dev_err(sev->dev, "SEV: INIT_EX NV memory page state change failed.\n");
813+
return -ENOMEM;
814+
}
815+
}
816+
817+
return 0;
818+
}
819+
778820
static int __sev_platform_init_locked(int *error)
779821
{
780822
int rc, psp_ret = SEV_RET_NO_FW_CALL;
@@ -790,11 +832,9 @@ static int __sev_platform_init_locked(int *error)
790832

791833
__sev_platform_init_handle_tmr(sev);
792834

793-
if (sev_init_ex_buffer) {
794-
rc = sev_read_init_ex_file();
795-
if (rc)
796-
return rc;
797-
}
835+
rc = __sev_platform_init_handle_init_ex_path(sev);
836+
if (rc)
837+
return rc;
798838

799839
rc = __sev_do_init_locked(&psp_ret);
800840
if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) {
@@ -1693,8 +1733,9 @@ static void sev_firmware_shutdown(struct sev_device *sev)
16931733
}
16941734

16951735
if (sev_init_ex_buffer) {
1696-
free_pages((unsigned long)sev_init_ex_buffer,
1697-
get_order(NV_LENGTH));
1736+
__snp_free_firmware_pages(virt_to_page(sev_init_ex_buffer),
1737+
get_order(NV_LENGTH),
1738+
true);
16981739
sev_init_ex_buffer = NULL;
16991740
}
17001741

@@ -1748,18 +1789,6 @@ void sev_pci_init(void)
17481789
if (sev_update_firmware(sev->dev) == 0)
17491790
sev_get_api_version();
17501791

1751-
/* If an init_ex_path is provided rely on INIT_EX for PSP initialization
1752-
* instead of INIT.
1753-
*/
1754-
if (init_ex_path) {
1755-
sev_init_ex_buffer = sev_fw_alloc(NV_LENGTH);
1756-
if (!sev_init_ex_buffer) {
1757-
dev_err(sev->dev,
1758-
"SEV: INIT_EX NV memory allocation failed\n");
1759-
goto err;
1760-
}
1761-
}
1762-
17631792
/* Initialize the platform */
17641793
args.probe = true;
17651794
rc = sev_platform_init(&args);

0 commit comments

Comments
 (0)