The SEV-SNP firmware provides the SNP_VERIFY_MITIGATION command, which can be used to query the status of currently supported vulnerability mitigations and to initiate mitigations within the firmware. See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for more details. Signed-off-by: Pratik R. Sampat <prsampat@xxxxxxx> --- Documentation/virt/coco/sev-guest.rst | 13 +++++++ drivers/crypto/ccp/sev-dev.c | 55 +++++++++++++++++++++++++++ include/linux/psp-sev.h | 30 +++++++++++++++ include/uapi/linux/psp-sev.h | 34 +++++++++++++++++ 4 files changed, 132 insertions(+) diff --git a/Documentation/virt/coco/sev-guest.rst b/Documentation/virt/coco/sev-guest.rst index 93debceb6eb0..8cc1eb375284 100644 --- a/Documentation/virt/coco/sev-guest.rst +++ b/Documentation/virt/coco/sev-guest.rst @@ -195,6 +195,19 @@ them into the system after obtaining them from the KDS, and corresponds closely to the SNP_VLEK_LOAD firmware command specified in the SEV-SNP spec. +2.8 SNP_VERIFY_MITIGATION +------------------------- +:Technology: sev-snp +:Type: hypervisor ioctl cmd +:Parameters (in): struct sev_user_data_snp_verify_mitigation +:Returns (out): 0 on success, -negative on error + +SNP_VERIFY_MITIGATION enables the host to issue commands to the SEV firmware to +manage vulnerability mitigations. This command provides two subcommands: VERIFY +and STATUS. The VERIFY subcommand instructs the firmware to initiate mitigation +for a specified vulnerability. The STATUS subcommand queries the firmware for +the currently supported and verified mitigations. + 3. SEV-SNP CPUID Enforcement ============================ diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 16a11d5efe46..9f43151bcdfe 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -228,6 +228,7 @@ static int sev_cmd_buffer_len(int cmd) case SEV_CMD_SNP_LAUNCH_FINISH: return sizeof(struct sev_data_snp_launch_finish); case SEV_CMD_SNP_DBG_DECRYPT: return sizeof(struct sev_data_snp_dbg); case SEV_CMD_SNP_DBG_ENCRYPT: return sizeof(struct sev_data_snp_dbg); + case SEV_CMD_SNP_VERIFY_MITIGATION: return sizeof(struct sev_data_snp_verify_mitigation); case SEV_CMD_SNP_PAGE_UNSMASH: return sizeof(struct sev_data_snp_page_unsmash); case SEV_CMD_SNP_PLATFORM_STATUS: return sizeof(struct sev_data_snp_addr); case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); @@ -2201,6 +2202,57 @@ static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable) return ret; } +static int sev_ioctl_do_snp_verify_mitigation(struct sev_issue_cmd *argp, bool writable) +{ + struct sev_user_data_snp_verify_mitigation input; + struct sev_data_snp_verify_mitigation data = {0}; + struct snp_verify_mitigation_dst *mit_dst = NULL; + struct page *page = NULL; + void __user *dst_uaddr; + int ret; + + if (!argp->data) + return -EINVAL; + + if (copy_from_user(&input, u64_to_user_ptr(argp->data), sizeof(input))) + return -EFAULT; + + /* VERIFY command may change system state when applying the mitigation */ + if (!writable && input.subcommand == SNP_MIT_SUBCMD_REQ_VERIFY) + return -EPERM; + + data.length = sizeof(data); + data.subcommand = input.subcommand; + data.vector = input.vector; + + if (!input.dst_uaddr) + goto cmd; + + dst_uaddr = (void __user *)input.dst_uaddr; + + page = __snp_alloc_firmware_pages(GFP_KERNEL | __GFP_ZERO, 0, true); + if (!page) + return -ENOMEM; + + mit_dst = page_address(page); + data.dst_paddr = __psp_pa(mit_dst); + data.dst_paddr_en = true; + +cmd: + ret = __sev_do_cmd_locked(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &argp->error); + if (ret || !data.dst_paddr_en) + goto out; + + if (copy_to_user(dst_uaddr, mit_dst, sizeof(*mit_dst))) + ret = -EFAULT; + +out: + if (page) + __snp_free_firmware_pages(page, 0, true); + + return ret; +} + static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -2264,6 +2316,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) case SNP_VLEK_LOAD: ret = sev_ioctl_do_snp_vlek_load(&input, writable); break; + case SNP_VERIFY_MITIGATION: + ret = sev_ioctl_do_snp_verify_mitigation(&input, writable); + break; default: ret = -EINVAL; goto out; diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 0b3a36bdaa90..ee5d64b0959a 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -96,6 +96,7 @@ enum sev_cmd { SEV_CMD_SNP_LAUNCH_FINISH = 0x0A2, SEV_CMD_SNP_DBG_DECRYPT = 0x0B0, SEV_CMD_SNP_DBG_ENCRYPT = 0x0B1, + SEV_CMD_SNP_VERIFY_MITIGATION = 0x0B2, SEV_CMD_SNP_PAGE_SWAP_OUT = 0x0C0, SEV_CMD_SNP_PAGE_SWAP_IN = 0x0C1, SEV_CMD_SNP_PAGE_MOVE = 0x0C2, @@ -812,6 +813,35 @@ struct sev_data_snp_commit { u32 len; } __packed; +/** + * struct sev_data_snp_verify_mitigation - SNP_VERIFY_MITIGATION command params + * + * @length: Length of the command buffer read by the PSP + * @subcommand: Mitigation sub-command for the firmware to execute. + * @rsvd: Reserved + * @vector: Bit specifying the vulnerability mitigation to process + * @dst_paddr_en: Destination paddr enabled + * @src_paddr_en: Source paddr enabled + * @rsvd1: Reserved + * @rsvd2: Reserved + * @dst_paddr: Destination address to write the result + * @src_paddr: Source address for optional input data + * @rsvd3: Reserved + */ +struct sev_data_snp_verify_mitigation { + u32 length; + u16 subcommand; + u16 rsvd; + u64 vector; + u32 dst_paddr_en : 1, + src_paddr_en : 1, + rsvd1 : 30; + u8 rsvd2[4]; + u64 src_paddr; + u64 dst_paddr; + u8 rsvd3[24]; +} __packed; + #ifdef CONFIG_CRYPTO_DEV_SP_PSP /** diff --git a/include/uapi/linux/psp-sev.h b/include/uapi/linux/psp-sev.h index eeb20dfb1fda..ca0f44fef659 100644 --- a/include/uapi/linux/psp-sev.h +++ b/include/uapi/linux/psp-sev.h @@ -32,6 +32,7 @@ enum { SNP_COMMIT, SNP_SET_CONFIG, SNP_VLEK_LOAD, + SNP_VERIFY_MITIGATION, SEV_MAX, }; @@ -249,6 +250,39 @@ struct sev_user_data_snp_wrapped_vlek_hashstick { __u8 data[432]; /* In */ } __packed; +#define SNP_MIT_SUBCMD_REQ_STATUS 0x0 +#define SNP_MIT_SUBCMD_REQ_VERIFY 0x1 + +/** + * struct sev_user_data_snp_verify_mitigation - vulnerability mitigation op + * + * @subcommand: Mitigation sub-command for the firmware to execute. + * REQ_STATUS: 0x0 - Request status about currently supported and + * verified mitigations + * REQ_VERIFY: 0x1 - Request to initiate verification mitigation + * operation on a specific mitigation + * @vector: A single bit to specify the mitigation to process + * @dst_uaddr: Destination addr to write the result + */ +struct sev_user_data_snp_verify_mitigation { + u16 subcommand; /* In */ + u64 vector; /* In */ + u64 dst_uaddr; /* In */ +} __packed; + +/** + * struct snp_verify_mitigation_dst - mitigation result vectors + * + * @mit_verified_vector: Bit vector of vulnerability mitigations verified + * @mit_supported_vector: Bit vector of vulnerability mitigations supported + * @mit_failure_status: Status of the verification operation + */ +struct snp_verify_mitigation_dst { + u64 mit_verified_vector; /* OUT */ + u64 mit_supported_vector; /* OUT */ + u32 mit_failure_status; /* OUT */ +} __packed; + /** * struct sev_issue_cmd - SEV ioctl parameters * -- 2.49.0