crypto: ccp: Add the SNP_PLATFORM_STATUS command

This command is used to query the SNP platform status. See the SEV-SNP
spec for more details.

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@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-24-michael.roth@amd.com
This commit is contained in:
Brijesh Singh 2024-01-25 22:11:23 -06:00 committed by Borislav Petkov (AMD)
parent c3b86e61b7
commit f5db8841eb
3 changed files with 80 additions and 0 deletions

View file

@ -67,6 +67,22 @@ counter (e.g. counter overflow), then -EIO will be returned.
}; };
}; };
The host ioctls are issued to a file descriptor of the /dev/sev device.
The ioctl accepts the command ID/input structure documented below.
::
struct sev_issue_cmd {
/* Command ID */
__u32 cmd;
/* Command request structure */
__u64 data;
/* Firmware error code on failure (see psp-sev.h) */
__u32 error;
};
2.1 SNP_GET_REPORT 2.1 SNP_GET_REPORT
------------------ ------------------
@ -124,6 +140,17 @@ be updated with the expected value.
See GHCB specification for further detail on how to parse the certificate blob. See GHCB specification for further detail on how to parse the certificate blob.
2.4 SNP_PLATFORM_STATUS
-----------------------
:Technology: sev-snp
:Type: hypervisor ioctl cmd
:Parameters (out): struct sev_user_data_snp_status
:Returns (out): 0 on success, -negative on error
The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The
status includes API major, minor version and more. See the SEV-SNP
specification for further details.
3. SEV-SNP CPUID Enforcement 3. SEV-SNP CPUID Enforcement
============================ ============================

View file

@ -1941,6 +1941,55 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
return ret; return ret;
} }
static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
{
struct sev_device *sev = psp_master->sev_data;
struct sev_data_snp_addr buf;
struct page *status_page;
void *data;
int ret;
if (!sev->snp_initialized || !argp->data)
return -EINVAL;
status_page = alloc_page(GFP_KERNEL_ACCOUNT);
if (!status_page)
return -ENOMEM;
data = page_address(status_page);
/*
* Firmware expects status page to be in firmware-owned state, otherwise
* it will report firmware error code INVALID_PAGE_STATE (0x1A).
*/
if (rmp_mark_pages_firmware(__pa(data), 1, true)) {
ret = -EFAULT;
goto cleanup;
}
buf.address = __psp_pa(data);
ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error);
/*
* Status page will be transitioned to Reclaim state upon success, or
* left in Firmware state in failure. Use snp_reclaim_pages() to
* transition either case back to Hypervisor-owned state.
*/
if (snp_reclaim_pages(__pa(data), 1, true))
return -EFAULT;
if (ret)
goto cleanup;
if (copy_to_user((void __user *)argp->data, data,
sizeof(struct sev_user_data_snp_status)))
ret = -EFAULT;
cleanup:
__free_pages(status_page, 0);
return ret;
}
static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
@ -1992,6 +2041,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
case SEV_GET_ID2: case SEV_GET_ID2:
ret = sev_ioctl_do_get_id2(&input); ret = sev_ioctl_do_get_id2(&input);
break; break;
case SNP_PLATFORM_STATUS:
ret = sev_ioctl_do_snp_platform_status(&input);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;

View file

@ -28,6 +28,7 @@ enum {
SEV_PEK_CERT_IMPORT, SEV_PEK_CERT_IMPORT,
SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */ SEV_GET_ID, /* This command is deprecated, use SEV_GET_ID2 */
SEV_GET_ID2, SEV_GET_ID2,
SNP_PLATFORM_STATUS,
SEV_MAX, SEV_MAX,
}; };