[PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command

Pratik R. Sampat posted 1 patch 5 days, 4 hours ago
.../sysfs-firmware-sev-vulnerabilities        |  17 ++
drivers/crypto/ccp/sev-dev.c                  | 172 ++++++++++++++++++
drivers/crypto/ccp/sev-dev.h                  |   3 +
include/linux/psp-sev.h                       |  51 ++++++
4 files changed, 243 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
[PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Pratik R. Sampat 5 days, 4 hours ago
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.

This command is an explicit mechanism to ascertain if a firmware
mitigation is applied without needing a full RMP re-build, which is most
useful in a live firmware update scenario.

The firmware supports two subcommands: STATUS and VERIFY. The STATUS
subcommand is used to query the supported and verified mitigation bits.
The VERIFY subcommand initiates the mitigation process within the FW for
the specified vulnerability. Expose a userspace interface under:
/sys/firmware/sev/vulnerabilities/
  - supported_mitigations (read-only): supported mitigation vector mask
  - verified_mitigations (read/write): current verified mask; write a
    vector to request VERIFY for that bit

The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
it are bug-specific. Information about supported mitigations and its
corresponding vector is to be published as part of the AMD Security
Bulletin.

See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
more details.

Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
---
 .../sysfs-firmware-sev-vulnerabilities        |  17 ++
 drivers/crypto/ccp/sev-dev.c                  | 172 ++++++++++++++++++
 drivers/crypto/ccp/sev-dev.h                  |   3 +
 include/linux/psp-sev.h                       |  51 ++++++
 4 files changed, 243 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities

diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
new file mode 100644
index 000000000000..cc84adbac3c0
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
@@ -0,0 +1,17 @@
+What:		/sys/firmware/sev/vulnerabilities/
+		/sys/firmware/sev/vulnerabilities/supported_mitigations
+		/sys/firmware/sev/vulnerabilities/verified_mitigations
+Date:		May 2026
+Contact:	linux-crypto@vger.kernel.org
+Description:	Information about SEV-SNP firmware vulnerability mitigations.
+		supported_mitigations: Read-only interface that reports
+				       the vector of mitigations supported by
+				       the firmware.
+		verified_mitigations: Read/write interface that reports
+				      the vector of mitigations already verified
+				      by the firmware. Writing a vector value
+				      requests the firmware to VERIFY the
+				      corresponding mitigation bit(s).
+		The list of supported mitigations and the meaning of each
+		vector bit are both platform- and bug-specific and are
+		published as part of the AMD Security Bulletin.
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
index d1e9e0ac63b6..eec4864c6597 100644
--- a/drivers/crypto/ccp/sev-dev.c
+++ b/drivers/crypto/ccp/sev-dev.c
@@ -57,6 +57,7 @@
 #define CMD_BUF_DESC_MAX (CMD_BUF_FW_WRITABLE_MAX + 1)
 
 static DEFINE_MUTEX(sev_cmd_mutex);
+static DEFINE_MUTEX(sev_mit_sysfs_mutex);
 static struct sev_misc_dev *misc_dev;
 
 static int psp_cmd_timeout = 100;
@@ -245,6 +246,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);
@@ -1351,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
 	return 0;
 }
 
+static int snp_verify_mitigation(u16 command, u64 vector,
+				 struct sev_data_snp_verify_mitigation_dst *dst)
+{
+	struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
+	struct sev_data_snp_verify_mitigation data = {0};
+	struct sev_device *sev = psp_master->sev_data;
+	int ret, error = 0;
+
+	mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
+	if (!mit_dst)
+		return -ENOMEM;
+
+	data.length = sizeof(data);
+	data.subcommand = command;
+	data.vector = vector;
+	data.dst_paddr = __psp_pa(mit_dst);
+	data.dst_paddr_en = true;
+
+	ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
+	if (!ret)
+		memcpy(dst, mit_dst, sizeof(*mit_dst));
+	else
+		dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
+			ret, error);
+
+	snp_free_firmware_page(mit_dst);
+
+	return ret;
+}
+
+#ifdef CONFIG_SYSFS
+static ssize_t supported_mitigations_show(struct kobject *kobj,
+					  struct kobj_attribute *attr, char *buf)
+{
+	struct sev_data_snp_verify_mitigation_dst dst;
+	int ret;
+
+	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
+}
+
+static struct kobj_attribute supported_attr =
+		__ATTR_RO_MODE(supported_mitigations, 0400);
+
+static ssize_t verified_mitigations_show(struct kobject *kobj,
+					 struct kobj_attribute *attr, char *buf)
+{
+	struct sev_data_snp_verify_mitigation_dst dst;
+	int ret;
+
+	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
+}
+
+static ssize_t verified_mitigations_store(struct kobject *kobj,
+					  struct kobj_attribute *attr,
+					  const char *buf, size_t count)
+{
+	struct sev_data_snp_verify_mitigation_dst dst;
+	struct sev_device *sev = psp_master->sev_data;
+	u64 vector;
+	int ret;
+
+	ret = kstrtoull(buf, 0, &vector);
+	if (ret)
+		return ret;
+
+	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
+	if (ret)
+		return ret;
+
+	if (dst.mit_failure_status) {
+		dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
+			dst.mit_failure_status);
+		return -EIO;
+	}
+
+	return count;
+}
+
+static struct kobj_attribute verified_attr =
+		__ATTR_RW_MODE(verified_mitigations, 0600);
+
+static struct attribute *mitigation_attrs[] = {
+	&supported_attr.attr,
+	&verified_attr.attr,
+	NULL
+};
+
+static const struct attribute_group mit_attr_group = {
+	.attrs = mitigation_attrs,
+};
+
+static void sev_snp_register_verify_mitigation(struct sev_device *sev)
+{
+	int rc;
+
+	if (!sev->snp_initialized || !sev->snp_plat_status.feature_info ||
+	    !(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED))
+		return;
+
+	guard(mutex)(&sev_mit_sysfs_mutex);
+
+	if (sev->verify_mit)
+		return;
+
+	if (!sev->sev_kobj) {
+		sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
+		if (!sev->sev_kobj)
+			return;
+	}
+
+	sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
+	if (!sev->verify_mit)
+		goto err_sev_kobj;
+
+	rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
+	if (rc)
+		goto err_verify_mit;
+
+	return;
+
+err_verify_mit:
+	kobject_put(sev->verify_mit);
+	sev->verify_mit = NULL;
+err_sev_kobj:
+	kobject_put(sev->sev_kobj);
+	sev->sev_kobj = NULL;
+}
+
+static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
+{
+	guard(mutex)(&sev_mit_sysfs_mutex);
+
+	if (sev->verify_mit) {
+		sysfs_remove_group(sev->verify_mit, &mit_attr_group);
+		kobject_put(sev->verify_mit);
+		sev->verify_mit = NULL;
+	}
+
+	if (sev->sev_kobj) {
+		kobject_put(sev->sev_kobj);
+		sev->sev_kobj = NULL;
+	}
+}
+#else
+static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
+static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
+#endif
+
 static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
 {
 	struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
@@ -1670,6 +1828,14 @@ int sev_platform_init(struct sev_platform_init_args *args)
 	rc = _sev_platform_init_locked(args);
 	mutex_unlock(&sev_cmd_mutex);
 
+	/*
+	 * The shutdown + init path can race with in-flight _show()/_store() operations
+	 * which acquire the sev_cmd_mutex. Register the sysfs interface outside
+	 * the sev_cmd_mutex and serialize by sev_mit_sysfs_mutex instead.
+	 */
+	if (!rc)
+		sev_snp_register_verify_mitigation(psp_master->sev_data);
+
 	return rc;
 }
 EXPORT_SYMBOL_GPL(sev_platform_init);
@@ -2796,6 +2962,12 @@ static void sev_firmware_shutdown(struct sev_device *sev)
 	if (sev->tio_status)
 		sev_tsm_uninit(sev);
 
+	/*
+	 * Concurrent access to the sysfs entry will call sev_do_cmd() for
+	 * SNP_VERIFY_MITIGATION which locks the mutex and can cause a deadlock.
+	 */
+	sev_snp_unregister_verify_mitigation(sev);
+
 	mutex_lock(&sev_cmd_mutex);
 
 	__sev_firmware_shutdown(sev, false);
diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
index b1cd556bbbf6..d5e596606def 100644
--- a/drivers/crypto/ccp/sev-dev.h
+++ b/drivers/crypto/ccp/sev-dev.h
@@ -59,6 +59,9 @@ struct sev_device {
 
 	bool snp_initialized;
 
+	struct kobject *sev_kobj;
+	struct kobject *verify_mit;
+
 	struct sev_user_data_status sev_plat_status;
 
 	struct sev_user_data_snp_status snp_plat_status;
diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
index d5099a2baca5..98666c5a6f79 100644
--- a/include/linux/psp-sev.h
+++ b/include/linux/psp-sev.h
@@ -129,6 +129,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,
@@ -898,10 +899,60 @@ struct snp_feature_info {
 #define SNP_CIPHER_TEXT_HIDING_SUPPORTED	BIT(3)
 #define SNP_AES_256_XTS_POLICY_SUPPORTED	BIT(4)
 #define SNP_CXL_ALLOW_POLICY_SUPPORTED		BIT(5)
+#define SNP_VERIFY_MITIGATION_SUPPORTED	BIT(13)
 
 /* Feature bits in EBX */
 #define SNP_SEV_TIO_SUPPORTED			BIT(1)
 
+#define SNP_MIT_SUBCMD_REQ_STATUS      0x0
+#define SNP_MIT_SUBCMD_REQ_VERIFY      0x1
+
+/**
+ * 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.
+ *              REQ_STATUS: 0x0 - Request status about currently supported and
+ *                                verified mitigations
+ *              REQ_VERIFY: 0x1 - Request to initiate verification mitigation
+ *                                operation on a specific mitigation
+ * @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
+ * @src_paddr: Source address for optional input data
+ * @dst_paddr: Destination address to write the result
+ * @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;
+
+/**
+ * struct sev_data_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 sev_data_snp_verify_mitigation_dst {
+	u64 mit_verified_vector;                /* OUT */
+	u64 mit_supported_vector;               /* OUT */
+	u32 mit_failure_status;                 /* OUT */
+} __packed;
+
 #ifdef CONFIG_CRYPTO_DEV_SP_PSP
 
 /**
-- 
2.53.0
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Tom Lendacky 4 days, 4 hours ago
On 5/19/26 14:50, Pratik R. Sampat wrote:
> 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.
> 
> This command is an explicit mechanism to ascertain if a firmware
> mitigation is applied without needing a full RMP re-build, which is most
> useful in a live firmware update scenario.
> 
> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
> subcommand is used to query the supported and verified mitigation bits.
> The VERIFY subcommand initiates the mitigation process within the FW for
> the specified vulnerability. Expose a userspace interface under:
> /sys/firmware/sev/vulnerabilities/
>   - supported_mitigations (read-only): supported mitigation vector mask
>   - verified_mitigations (read/write): current verified mask; write a
>     vector to request VERIFY for that bit
> 
> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
> it are bug-specific. Information about supported mitigations and its
> corresponding vector is to be published as part of the AMD Security
> Bulletin.
> 
> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
> more details.
> 
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
> ---
>  .../sysfs-firmware-sev-vulnerabilities        |  17 ++
>  drivers/crypto/ccp/sev-dev.c                  | 172 ++++++++++++++++++
>  drivers/crypto/ccp/sev-dev.h                  |   3 +
>  include/linux/psp-sev.h                       |  51 ++++++
>  4 files changed, 243 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
> 
> diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
> new file mode 100644
> index 000000000000..cc84adbac3c0
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
> @@ -0,0 +1,17 @@
> +What:		/sys/firmware/sev/vulnerabilities/
> +		/sys/firmware/sev/vulnerabilities/supported_mitigations
> +		/sys/firmware/sev/vulnerabilities/verified_mitigations
> +Date:		May 2026
> +Contact:	linux-crypto@vger.kernel.org
> +Description:	Information about SEV-SNP firmware vulnerability mitigations.
> +		supported_mitigations: Read-only interface that reports
> +				       the vector of mitigations supported by
> +				       the firmware.
> +		verified_mitigations: Read/write interface that reports
> +				      the vector of mitigations already verified
> +				      by the firmware. Writing a vector value
> +				      requests the firmware to VERIFY the
> +				      corresponding mitigation bit(s).
> +		The list of supported mitigations and the meaning of each
> +		vector bit are both platform- and bug-specific and are
> +		published as part of the AMD Security Bulletin.
> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
> index d1e9e0ac63b6..eec4864c6597 100644
> --- a/drivers/crypto/ccp/sev-dev.c
> +++ b/drivers/crypto/ccp/sev-dev.c
> @@ -57,6 +57,7 @@
>  #define CMD_BUF_DESC_MAX (CMD_BUF_FW_WRITABLE_MAX + 1)
>  
>  static DEFINE_MUTEX(sev_cmd_mutex);
> +static DEFINE_MUTEX(sev_mit_sysfs_mutex);
>  static struct sev_misc_dev *misc_dev;
>  
>  static int psp_cmd_timeout = 100;
> @@ -245,6 +246,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);
> @@ -1351,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
>  	return 0;
>  }
>  
> +static int snp_verify_mitigation(u16 command, u64 vector,
> +				 struct sev_data_snp_verify_mitigation_dst *dst)
> +{
> +	struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
> +	struct sev_data_snp_verify_mitigation data = {0};
> +	struct sev_device *sev = psp_master->sev_data;
> +	int ret, error = 0;
> +
> +	mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
> +	if (!mit_dst)
> +		return -ENOMEM;
> +
> +	data.length = sizeof(data);
> +	data.subcommand = command;
> +	data.vector = vector;
> +	data.dst_paddr = __psp_pa(mit_dst);
> +	data.dst_paddr_en = true;
> +
> +	ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
> +	if (!ret)
> +		memcpy(dst, mit_dst, sizeof(*mit_dst));
> +	else
> +		dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
> +			ret, error);
> +
> +	snp_free_firmware_page(mit_dst);
> +
> +	return ret;
> +}

Should this function also be under the CONFIG_SYSFS #ifdef? Won't you get
an unused function warning if CONFIG_SYSFS isn't defined?

> +
> +#ifdef CONFIG_SYSFS
> +static ssize_t supported_mitigations_show(struct kobject *kobj,
> +					  struct kobj_attribute *attr, char *buf)
> +{
> +	struct sev_data_snp_verify_mitigation_dst dst;
> +	int ret;
> +
> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
> +	if (ret)
> +		return ret;
> +
> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
> +}
> +
> +static struct kobj_attribute supported_attr =
> +		__ATTR_RO_MODE(supported_mitigations, 0400);
> +
> +static ssize_t verified_mitigations_show(struct kobject *kobj,
> +					 struct kobj_attribute *attr, char *buf)
> +{
> +	struct sev_data_snp_verify_mitigation_dst dst;
> +	int ret;
> +
> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
> +	if (ret)
> +		return ret;
> +
> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
> +}
> +
> +static ssize_t verified_mitigations_store(struct kobject *kobj,
> +					  struct kobj_attribute *attr,
> +					  const char *buf, size_t count)
> +{
> +	struct sev_data_snp_verify_mitigation_dst dst;
> +	struct sev_device *sev = psp_master->sev_data;
> +	u64 vector;
> +	int ret;
> +
> +	ret = kstrtoull(buf, 0, &vector);
> +	if (ret)
> +		return ret;
> +
> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
> +	if (ret)
> +		return ret;
> +
> +	if (dst.mit_failure_status) {
> +		dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
> +			dst.mit_failure_status);
> +		return -EIO;
> +	}
> +
> +	return count;
> +}
> +
> +static struct kobj_attribute verified_attr =
> +		__ATTR_RW_MODE(verified_mitigations, 0600);
> +
> +static struct attribute *mitigation_attrs[] = {
> +	&supported_attr.attr,
> +	&verified_attr.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group mit_attr_group = {
> +	.attrs = mitigation_attrs,
> +};
> +
> +static void sev_snp_register_verify_mitigation(struct sev_device *sev)
> +{
> +	int rc;
> +
> +	if (!sev->snp_initialized || !sev->snp_plat_status.feature_info ||
> +	    !(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED))
> +		return;
> +
> +	guard(mutex)(&sev_mit_sysfs_mutex);
> +
> +	if (sev->verify_mit)
> +		return;
> +
> +	if (!sev->sev_kobj) {
> +		sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
> +		if (!sev->sev_kobj)
> +			return;
> +	}
> +
> +	sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
> +	if (!sev->verify_mit)
> +		goto err_sev_kobj;
> +
> +	rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
> +	if (rc)
> +		goto err_verify_mit;
> +
> +	return;
> +
> +err_verify_mit:
> +	kobject_put(sev->verify_mit);
> +	sev->verify_mit = NULL;
> +err_sev_kobj:
> +	kobject_put(sev->sev_kobj);
> +	sev->sev_kobj = NULL;
> +}
> +
> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
> +{
> +	guard(mutex)(&sev_mit_sysfs_mutex);
> +
> +	if (sev->verify_mit) {
> +		sysfs_remove_group(sev->verify_mit, &mit_attr_group);
> +		kobject_put(sev->verify_mit);
> +		sev->verify_mit = NULL;
> +	}
> +
> +	if (sev->sev_kobj) {
> +		kobject_put(sev->sev_kobj);
> +		sev->sev_kobj = NULL;
> +	}
> +}
> +#else
> +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
> +#endif
> +
>  static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
>  {
>  	struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
> @@ -1670,6 +1828,14 @@ int sev_platform_init(struct sev_platform_init_args *args)
>  	rc = _sev_platform_init_locked(args);
>  	mutex_unlock(&sev_cmd_mutex);
>  
> +	/*
> +	 * The shutdown + init path can race with in-flight _show()/_store() operations
> +	 * which acquire the sev_cmd_mutex. Register the sysfs interface outside
> +	 * the sev_cmd_mutex and serialize by sev_mit_sysfs_mutex instead.

I'm not quite sure I follow this. The shutdown and init path can't race
with each other, right? In which case this new mutex doesn't really matter
unless you take it on _show()/_short(), right?

Thanks,
Tom

> +	 */
> +	if (!rc)
> +		sev_snp_register_verify_mitigation(psp_master->sev_data);
> +
>  	return rc;
>  }
>  EXPORT_SYMBOL_GPL(sev_platform_init);
> @@ -2796,6 +2962,12 @@ static void sev_firmware_shutdown(struct sev_device *sev)
>  	if (sev->tio_status)
>  		sev_tsm_uninit(sev);
>  
> +	/*
> +	 * Concurrent access to the sysfs entry will call sev_do_cmd() for
> +	 * SNP_VERIFY_MITIGATION which locks the mutex and can cause a deadlock.
> +	 */
> +	sev_snp_unregister_verify_mitigation(sev);
> +
>  	mutex_lock(&sev_cmd_mutex);
>  
>  	__sev_firmware_shutdown(sev, false);
> diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
> index b1cd556bbbf6..d5e596606def 100644
> --- a/drivers/crypto/ccp/sev-dev.h
> +++ b/drivers/crypto/ccp/sev-dev.h
> @@ -59,6 +59,9 @@ struct sev_device {
>  
>  	bool snp_initialized;
>  
> +	struct kobject *sev_kobj;
> +	struct kobject *verify_mit;
> +
>  	struct sev_user_data_status sev_plat_status;
>  
>  	struct sev_user_data_snp_status snp_plat_status;
> diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h
> index d5099a2baca5..98666c5a6f79 100644
> --- a/include/linux/psp-sev.h
> +++ b/include/linux/psp-sev.h
> @@ -129,6 +129,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,
> @@ -898,10 +899,60 @@ struct snp_feature_info {
>  #define SNP_CIPHER_TEXT_HIDING_SUPPORTED	BIT(3)
>  #define SNP_AES_256_XTS_POLICY_SUPPORTED	BIT(4)
>  #define SNP_CXL_ALLOW_POLICY_SUPPORTED		BIT(5)
> +#define SNP_VERIFY_MITIGATION_SUPPORTED	BIT(13)
>  
>  /* Feature bits in EBX */
>  #define SNP_SEV_TIO_SUPPORTED			BIT(1)
>  
> +#define SNP_MIT_SUBCMD_REQ_STATUS      0x0
> +#define SNP_MIT_SUBCMD_REQ_VERIFY      0x1
> +
> +/**
> + * 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.
> + *              REQ_STATUS: 0x0 - Request status about currently supported and
> + *                                verified mitigations
> + *              REQ_VERIFY: 0x1 - Request to initiate verification mitigation
> + *                                operation on a specific mitigation
> + * @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
> + * @src_paddr: Source address for optional input data
> + * @dst_paddr: Destination address to write the result
> + * @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;
> +
> +/**
> + * struct sev_data_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 sev_data_snp_verify_mitigation_dst {
> +	u64 mit_verified_vector;                /* OUT */
> +	u64 mit_supported_vector;               /* OUT */
> +	u32 mit_failure_status;                 /* OUT */
> +} __packed;
> +
>  #ifdef CONFIG_CRYPTO_DEV_SP_PSP
>  
>  /**
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Pratik R. Sampat 3 days, 22 hours ago
Hi Tom,

On 5/20/26 4:22 PM, Tom Lendacky wrote:
> On 5/19/26 14:50, Pratik R. Sampat wrote:
>> 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.
>>
>> This command is an explicit mechanism to ascertain if a firmware
>> mitigation is applied without needing a full RMP re-build, which is most
>> useful in a live firmware update scenario.
>>
>> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
>> subcommand is used to query the supported and verified mitigation bits.
>> The VERIFY subcommand initiates the mitigation process within the FW for
>> the specified vulnerability. Expose a userspace interface under:
>> /sys/firmware/sev/vulnerabilities/
>>   - supported_mitigations (read-only): supported mitigation vector mask
>>   - verified_mitigations (read/write): current verified mask; write a
>>     vector to request VERIFY for that bit
>>
>> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
>> it are bug-specific. Information about supported mitigations and its
>> corresponding vector is to be published as part of the AMD Security
>> Bulletin.
>>
>> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
>> more details.
>>
>> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
>> ---
>>  .../sysfs-firmware-sev-vulnerabilities        |  17 ++
>>  drivers/crypto/ccp/sev-dev.c                  | 172 ++++++++++++++++++
>>  drivers/crypto/ccp/sev-dev.h                  |   3 +
>>  include/linux/psp-sev.h                       |  51 ++++++
>>  4 files changed, 243 insertions(+)
>>  create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>>
>> diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>> new file mode 100644
>> index 000000000000..cc84adbac3c0
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>> @@ -0,0 +1,17 @@
>> +What:		/sys/firmware/sev/vulnerabilities/
>> +		/sys/firmware/sev/vulnerabilities/supported_mitigations
>> +		/sys/firmware/sev/vulnerabilities/verified_mitigations
>> +Date:		May 2026
>> +Contact:	linux-crypto@vger.kernel.org
>> +Description:	Information about SEV-SNP firmware vulnerability mitigations.
>> +		supported_mitigations: Read-only interface that reports
>> +				       the vector of mitigations supported by
>> +				       the firmware.
>> +		verified_mitigations: Read/write interface that reports
>> +				      the vector of mitigations already verified
>> +				      by the firmware. Writing a vector value
>> +				      requests the firmware to VERIFY the
>> +				      corresponding mitigation bit(s).
>> +		The list of supported mitigations and the meaning of each
>> +		vector bit are both platform- and bug-specific and are
>> +		published as part of the AMD Security Bulletin.
>> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
>> index d1e9e0ac63b6..eec4864c6597 100644
>> --- a/drivers/crypto/ccp/sev-dev.c
>> +++ b/drivers/crypto/ccp/sev-dev.c
>> @@ -57,6 +57,7 @@
>>  #define CMD_BUF_DESC_MAX (CMD_BUF_FW_WRITABLE_MAX + 1)
>>  
>>  static DEFINE_MUTEX(sev_cmd_mutex);
>> +static DEFINE_MUTEX(sev_mit_sysfs_mutex);
>>  static struct sev_misc_dev *misc_dev;
>>  
>>  static int psp_cmd_timeout = 100;
>> @@ -245,6 +246,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);
>> @@ -1351,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
>>  	return 0;
>>  }
>>  
>> +static int snp_verify_mitigation(u16 command, u64 vector,
>> +				 struct sev_data_snp_verify_mitigation_dst *dst)
>> +{
>> +	struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
>> +	struct sev_data_snp_verify_mitigation data = {0};
>> +	struct sev_device *sev = psp_master->sev_data;
>> +	int ret, error = 0;
>> +
>> +	mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
>> +	if (!mit_dst)
>> +		return -ENOMEM;
>> +
>> +	data.length = sizeof(data);
>> +	data.subcommand = command;
>> +	data.vector = vector;
>> +	data.dst_paddr = __psp_pa(mit_dst);
>> +	data.dst_paddr_en = true;
>> +
>> +	ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
>> +	if (!ret)
>> +		memcpy(dst, mit_dst, sizeof(*mit_dst));
>> +	else
>> +		dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
>> +			ret, error);
>> +
>> +	snp_free_firmware_page(mit_dst);
>> +
>> +	return ret;
>> +}
> 
> Should this function also be under the CONFIG_SYSFS #ifdef? Won't you get
> an unused function warning if CONFIG_SYSFS isn't defined?

That's right. Thanks for spotting that!

> 
>> +
>> +#ifdef CONFIG_SYSFS
>> +static ssize_t supported_mitigations_show(struct kobject *kobj,
>> +					  struct kobj_attribute *attr, char *buf)
>> +{
>> +	struct sev_data_snp_verify_mitigation_dst dst;
>> +	int ret;
>> +
>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
>> +}
>> +
>> +static struct kobj_attribute supported_attr =
>> +		__ATTR_RO_MODE(supported_mitigations, 0400);
>> +
>> +static ssize_t verified_mitigations_show(struct kobject *kobj,
>> +					 struct kobj_attribute *attr, char *buf)
>> +{
>> +	struct sev_data_snp_verify_mitigation_dst dst;
>> +	int ret;
>> +
>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
>> +}
>> +
>> +static ssize_t verified_mitigations_store(struct kobject *kobj,
>> +					  struct kobj_attribute *attr,
>> +					  const char *buf, size_t count)
>> +{
>> +	struct sev_data_snp_verify_mitigation_dst dst;
>> +	struct sev_device *sev = psp_master->sev_data;
>> +	u64 vector;
>> +	int ret;
>> +
>> +	ret = kstrtoull(buf, 0, &vector);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
>> +	if (ret)
>> +		return ret;
>> +
>> +	if (dst.mit_failure_status) {
>> +		dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
>> +			dst.mit_failure_status);
>> +		return -EIO;
>> +	}
>> +
>> +	return count;
>> +}
>> +
>> +static struct kobj_attribute verified_attr =
>> +		__ATTR_RW_MODE(verified_mitigations, 0600);
>> +
>> +static struct attribute *mitigation_attrs[] = {
>> +	&supported_attr.attr,
>> +	&verified_attr.attr,
>> +	NULL
>> +};
>> +
>> +static const struct attribute_group mit_attr_group = {
>> +	.attrs = mitigation_attrs,
>> +};
>> +
>> +static void sev_snp_register_verify_mitigation(struct sev_device *sev)
>> +{
>> +	int rc;
>> +
>> +	if (!sev->snp_initialized || !sev->snp_plat_status.feature_info ||
>> +	    !(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED))
>> +		return;
>> +
>> +	guard(mutex)(&sev_mit_sysfs_mutex);
>> +
>> +	if (sev->verify_mit)
>> +		return;
>> +
>> +	if (!sev->sev_kobj) {
>> +		sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
>> +		if (!sev->sev_kobj)
>> +			return;
>> +	}
>> +
>> +	sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
>> +	if (!sev->verify_mit)
>> +		goto err_sev_kobj;
>> +
>> +	rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
>> +	if (rc)
>> +		goto err_verify_mit;
>> +
>> +	return;
>> +
>> +err_verify_mit:
>> +	kobject_put(sev->verify_mit);
>> +	sev->verify_mit = NULL;
>> +err_sev_kobj:
>> +	kobject_put(sev->sev_kobj);
>> +	sev->sev_kobj = NULL;
>> +}
>> +
>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
>> +{
>> +	guard(mutex)(&sev_mit_sysfs_mutex);
>> +
>> +	if (sev->verify_mit) {
>> +		sysfs_remove_group(sev->verify_mit, &mit_attr_group);
>> +		kobject_put(sev->verify_mit);
>> +		sev->verify_mit = NULL;
>> +	}
>> +
>> +	if (sev->sev_kobj) {
>> +		kobject_put(sev->sev_kobj);
>> +		sev->sev_kobj = NULL;
>> +	}
>> +}
>> +#else
>> +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
>> +#endif
>> +
>>  static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
>>  {
>>  	struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
>> @@ -1670,6 +1828,14 @@ int sev_platform_init(struct sev_platform_init_args *args)
>>  	rc = _sev_platform_init_locked(args);
>>  	mutex_unlock(&sev_cmd_mutex);
>>  
>> +	/*
>> +	 * The shutdown + init path can race with in-flight _show()/_store() operations
>> +	 * which acquire the sev_cmd_mutex. Register the sysfs interface outside
>> +	 * the sev_cmd_mutex and serialize by sev_mit_sysfs_mutex instead.
> 
> I'm not quite sure I follow this. The shutdown and init path can't race
> with each other, right? In which case this new mutex doesn't really matter
> unless you take it on _show()/_short(), right?
> 
What I meant here is the new mutex attempts to addresses the following scenario:

First, assume sev_snp_[un]register_verify_mitigation() are protected under
sev_cmd_mutex:

t1                                 | t2
---------------------------------- | ----------------------------------
sev_firmware_shutdown()            |
  lock(sev_cmd_mutex)              |
                                   | verified_mitigations_store()
                                   |   lock(sev_cmd_mutex)  <-- waits on t1
  unregister_verify_mitigation()   |
    sysfs_remove_group()  <-- waits for t2's _store to drain

So sev_snp_unregister_verify_mitigation() has to run outside sev_cmd_mutex to
avoid the sysfs_remove_group() <-> in-flight _show()/_store() deadlock.

Now, with unregister no longer protected by sev_cmd_mutex, a concurrent init
can race with shutdown on the sysfs lifetime like so:
t1                                 | t2
---------------------------------- | ----------------------------------
sev_firmware_shutdown()            | sev_platform_init()
  unregister_verify_mitigation()   |   register_verify_mitigation()
    sysfs_remove_group()           |     sysfs_create_group()

Both sides touch sev->verify_mit without serialization. The same race also
exists for init vs init which is no longer covered by sev_cmd_mutex once
register moves outside it.

So, I attempt address that with a sev_mit_sysfs_mutex guard.

--Pratik
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Tom Lendacky 3 days, 11 hours ago
On 5/20/26 21:10, Pratik R. Sampat wrote:
> Hi Tom,
> 
> On 5/20/26 4:22 PM, Tom Lendacky wrote:
>> On 5/19/26 14:50, Pratik R. Sampat wrote:
>>> 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.
>>>
>>> This command is an explicit mechanism to ascertain if a firmware
>>> mitigation is applied without needing a full RMP re-build, which is most
>>> useful in a live firmware update scenario.
>>>
>>> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
>>> subcommand is used to query the supported and verified mitigation bits.
>>> The VERIFY subcommand initiates the mitigation process within the FW for
>>> the specified vulnerability. Expose a userspace interface under:
>>> /sys/firmware/sev/vulnerabilities/
>>>   - supported_mitigations (read-only): supported mitigation vector mask
>>>   - verified_mitigations (read/write): current verified mask; write a
>>>     vector to request VERIFY for that bit
>>>
>>> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
>>> it are bug-specific. Information about supported mitigations and its
>>> corresponding vector is to be published as part of the AMD Security
>>> Bulletin.
>>>
>>> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
>>> more details.
>>>
>>> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
>>> ---
>>>  .../sysfs-firmware-sev-vulnerabilities        |  17 ++
>>>  drivers/crypto/ccp/sev-dev.c                  | 172 ++++++++++++++++++
>>>  drivers/crypto/ccp/sev-dev.h                  |   3 +
>>>  include/linux/psp-sev.h                       |  51 ++++++
>>>  4 files changed, 243 insertions(+)
>>>  create mode 100644 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>>>
>>> diff --git a/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>>> new file mode 100644
>>> index 000000000000..cc84adbac3c0
>>> --- /dev/null
>>> +++ b/Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities
>>> @@ -0,0 +1,17 @@
>>> +What:		/sys/firmware/sev/vulnerabilities/
>>> +		/sys/firmware/sev/vulnerabilities/supported_mitigations
>>> +		/sys/firmware/sev/vulnerabilities/verified_mitigations
>>> +Date:		May 2026
>>> +Contact:	linux-crypto@vger.kernel.org
>>> +Description:	Information about SEV-SNP firmware vulnerability mitigations.
>>> +		supported_mitigations: Read-only interface that reports
>>> +				       the vector of mitigations supported by
>>> +				       the firmware.
>>> +		verified_mitigations: Read/write interface that reports
>>> +				      the vector of mitigations already verified
>>> +				      by the firmware. Writing a vector value
>>> +				      requests the firmware to VERIFY the
>>> +				      corresponding mitigation bit(s).
>>> +		The list of supported mitigations and the meaning of each
>>> +		vector bit are both platform- and bug-specific and are
>>> +		published as part of the AMD Security Bulletin.
>>> diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
>>> index d1e9e0ac63b6..eec4864c6597 100644
>>> --- a/drivers/crypto/ccp/sev-dev.c
>>> +++ b/drivers/crypto/ccp/sev-dev.c
>>> @@ -57,6 +57,7 @@
>>>  #define CMD_BUF_DESC_MAX (CMD_BUF_FW_WRITABLE_MAX + 1)
>>>  
>>>  static DEFINE_MUTEX(sev_cmd_mutex);
>>> +static DEFINE_MUTEX(sev_mit_sysfs_mutex);
>>>  static struct sev_misc_dev *misc_dev;
>>>  
>>>  static int psp_cmd_timeout = 100;
>>> @@ -245,6 +246,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);
>>> @@ -1351,6 +1353,162 @@ static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg)
>>>  	return 0;
>>>  }
>>>  
>>> +static int snp_verify_mitigation(u16 command, u64 vector,
>>> +				 struct sev_data_snp_verify_mitigation_dst *dst)
>>> +{
>>> +	struct sev_data_snp_verify_mitigation_dst *mit_dst = NULL;
>>> +	struct sev_data_snp_verify_mitigation data = {0};
>>> +	struct sev_device *sev = psp_master->sev_data;
>>> +	int ret, error = 0;
>>> +
>>> +	mit_dst = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO);
>>> +	if (!mit_dst)
>>> +		return -ENOMEM;
>>> +
>>> +	data.length = sizeof(data);
>>> +	data.subcommand = command;
>>> +	data.vector = vector;
>>> +	data.dst_paddr = __psp_pa(mit_dst);
>>> +	data.dst_paddr_en = true;
>>> +
>>> +	ret = sev_do_cmd(SEV_CMD_SNP_VERIFY_MITIGATION, &data, &error);
>>> +	if (!ret)
>>> +		memcpy(dst, mit_dst, sizeof(*mit_dst));
>>> +	else
>>> +		dev_err(sev->dev, "SNP_VERIFY_MITIGATION command failed, ret = %d, error = %#x\n",
>>> +			ret, error);
>>> +
>>> +	snp_free_firmware_page(mit_dst);
>>> +
>>> +	return ret;
>>> +}
>>
>> Should this function also be under the CONFIG_SYSFS #ifdef? Won't you get
>> an unused function warning if CONFIG_SYSFS isn't defined?
> 
> That's right. Thanks for spotting that!
> 
>>
>>> +
>>> +#ifdef CONFIG_SYSFS
>>> +static ssize_t supported_mitigations_show(struct kobject *kobj,
>>> +					  struct kobj_attribute *attr, char *buf)
>>> +{
>>> +	struct sev_data_snp_verify_mitigation_dst dst;
>>> +	int ret;
>>> +
>>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_supported_vector);
>>> +}
>>> +
>>> +static struct kobj_attribute supported_attr =
>>> +		__ATTR_RO_MODE(supported_mitigations, 0400);
>>> +
>>> +static ssize_t verified_mitigations_show(struct kobject *kobj,
>>> +					 struct kobj_attribute *attr, char *buf)
>>> +{
>>> +	struct sev_data_snp_verify_mitigation_dst dst;
>>> +	int ret;
>>> +
>>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_STATUS, 0, &dst);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	return sysfs_emit(buf, "0x%llx\n", dst.mit_verified_vector);
>>> +}
>>> +
>>> +static ssize_t verified_mitigations_store(struct kobject *kobj,
>>> +					  struct kobj_attribute *attr,
>>> +					  const char *buf, size_t count)
>>> +{
>>> +	struct sev_data_snp_verify_mitigation_dst dst;
>>> +	struct sev_device *sev = psp_master->sev_data;
>>> +	u64 vector;
>>> +	int ret;
>>> +
>>> +	ret = kstrtoull(buf, 0, &vector);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = snp_verify_mitigation(SNP_MIT_SUBCMD_REQ_VERIFY, vector, &dst);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	if (dst.mit_failure_status) {
>>> +		dev_err(sev->dev, "Verify Mitigation - failure status: 0x%x\n",
>>> +			dst.mit_failure_status);
>>> +		return -EIO;
>>> +	}
>>> +
>>> +	return count;
>>> +}
>>> +
>>> +static struct kobj_attribute verified_attr =
>>> +		__ATTR_RW_MODE(verified_mitigations, 0600);
>>> +
>>> +static struct attribute *mitigation_attrs[] = {
>>> +	&supported_attr.attr,
>>> +	&verified_attr.attr,
>>> +	NULL
>>> +};
>>> +
>>> +static const struct attribute_group mit_attr_group = {
>>> +	.attrs = mitigation_attrs,
>>> +};
>>> +
>>> +static void sev_snp_register_verify_mitigation(struct sev_device *sev)
>>> +{
>>> +	int rc;
>>> +
>>> +	if (!sev->snp_initialized || !sev->snp_plat_status.feature_info ||
>>> +	    !(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED))
>>> +		return;
>>> +
>>> +	guard(mutex)(&sev_mit_sysfs_mutex);
>>> +
>>> +	if (sev->verify_mit)
>>> +		return;
>>> +
>>> +	if (!sev->sev_kobj) {
>>> +		sev->sev_kobj = kobject_create_and_add("sev", firmware_kobj);
>>> +		if (!sev->sev_kobj)
>>> +			return;
>>> +	}
>>> +
>>> +	sev->verify_mit = kobject_create_and_add("vulnerabilities", sev->sev_kobj);
>>> +	if (!sev->verify_mit)
>>> +		goto err_sev_kobj;
>>> +
>>> +	rc = sysfs_create_group(sev->verify_mit, &mit_attr_group);
>>> +	if (rc)
>>> +		goto err_verify_mit;
>>> +
>>> +	return;
>>> +
>>> +err_verify_mit:
>>> +	kobject_put(sev->verify_mit);
>>> +	sev->verify_mit = NULL;
>>> +err_sev_kobj:
>>> +	kobject_put(sev->sev_kobj);
>>> +	sev->sev_kobj = NULL;
>>> +}
>>> +
>>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev)
>>> +{
>>> +	guard(mutex)(&sev_mit_sysfs_mutex);
>>> +
>>> +	if (sev->verify_mit) {
>>> +		sysfs_remove_group(sev->verify_mit, &mit_attr_group);
>>> +		kobject_put(sev->verify_mit);
>>> +		sev->verify_mit = NULL;
>>> +	}
>>> +
>>> +	if (sev->sev_kobj) {
>>> +		kobject_put(sev->sev_kobj);
>>> +		sev->sev_kobj = NULL;
>>> +	}
>>> +}
>>> +#else
>>> +static void sev_snp_register_verify_mitigation(struct sev_device *sev) { }
>>> +static void sev_snp_unregister_verify_mitigation(struct sev_device *sev) { }
>>> +#endif
>>> +
>>>  static int __sev_snp_init_locked(int *error, unsigned int max_snp_asid)
>>>  {
>>>  	struct sev_data_range_list *snp_range_list __free(kfree) = NULL;
>>> @@ -1670,6 +1828,14 @@ int sev_platform_init(struct sev_platform_init_args *args)
>>>  	rc = _sev_platform_init_locked(args);
>>>  	mutex_unlock(&sev_cmd_mutex);
>>>  
>>> +	/*
>>> +	 * The shutdown + init path can race with in-flight _show()/_store() operations
>>> +	 * which acquire the sev_cmd_mutex. Register the sysfs interface outside
>>> +	 * the sev_cmd_mutex and serialize by sev_mit_sysfs_mutex instead.
>>
>> I'm not quite sure I follow this. The shutdown and init path can't race
>> with each other, right? In which case this new mutex doesn't really matter
>> unless you take it on _show()/_short(), right?
>>
> What I meant here is the new mutex attempts to addresses the following scenario:
> 
> First, assume sev_snp_[un]register_verify_mitigation() are protected under
> sev_cmd_mutex:
> 
> t1                                 | t2
> ---------------------------------- | ----------------------------------
> sev_firmware_shutdown()            |
>   lock(sev_cmd_mutex)              |
>                                    | verified_mitigations_store()
>                                    |   lock(sev_cmd_mutex)  <-- waits on t1
>   unregister_verify_mitigation()   |
>     sysfs_remove_group()  <-- waits for t2's _store to drain
> 
> So sev_snp_unregister_verify_mitigation() has to run outside sev_cmd_mutex to
> avoid the sysfs_remove_group() <-> in-flight _show()/_store() deadlock.
> 
> Now, with unregister no longer protected by sev_cmd_mutex, a concurrent init
> can race with shutdown on the sysfs lifetime like so:

Can it? Can init and shutdown race? Isn't that part of module load /
unload, I'm not sure how they can race...

> t1                                 | t2
> ---------------------------------- | ----------------------------------
> sev_firmware_shutdown()            | sev_platform_init()
>   unregister_verify_mitigation()   |   register_verify_mitigation()
>     sysfs_remove_group()           |     sysfs_create_group()
> 
> Both sides touch sev->verify_mit without serialization. The same race also
> exists for init vs init which is no longer covered by sev_cmd_mutex once
> register moves outside it.

I don't think you can have init vs init race, can you? This just all seems
odd to me. Have you created all these race scenarios to test this out?

Would putting the regsiter/unregister under the sev_cmd_mutex and then
taking the sev_cmd_mutex upon entry to _show()/_store() fix all this?
After obtaining the mutex in _show()/_store(), you check for
sev->verify_mit and return an error if NULL. Then you can use the
__sev_do_cmd_locked() to issue any commands.

Also, on the register function, all you need is the check for
!(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) since if
!sev->snp_plat_status.feature_info is true, so is this this check. And, as
the spec says, the required firmware state is based on the mitigation
requirements, so I don't think you should be checking for snp_initialized.

Thanks,
Tom

> 
> So, I attempt address that with a sev_mit_sysfs_mutex guard.
> 
> --Pratik
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Tycho Andersen 3 days, 9 hours ago
On Thu, May 21, 2026 at 08:12:52AM -0500, Tom Lendacky wrote:
> > Now, with unregister no longer protected by sev_cmd_mutex, a concurrent init
> > can race with shutdown on the sysfs lifetime like so:
> 
> Can it? Can init and shutdown race? Isn't that part of module load /
> unload, I'm not sure how they can race...

That's only true after
https://lore.kernel.org/all/20260504165147.1615643-5-tycho@kernel.org/
right? Before that, if the first init failed, you could trigger a
re-init via ioctl(), and presumably trigger the race sashiko is
complaining about by spamming ioctl() + sysfs writes on separate
threads.

> > t1                                 | t2
> > ---------------------------------- | ----------------------------------
> > sev_firmware_shutdown()            | sev_platform_init()
> >   unregister_verify_mitigation()   |   register_verify_mitigation()
> >     sysfs_remove_group()           |     sysfs_create_group()
> > 
> > Both sides touch sev->verify_mit without serialization. The same race also
> > exists for init vs init which is no longer covered by sev_cmd_mutex once
> > register moves outside it.
> 
> I don't think you can have init vs init race, can you? This just all seems
> odd to me. Have you created all these race scenarios to test this out?
> 
> Would putting the regsiter/unregister under the sev_cmd_mutex and then
> taking the sev_cmd_mutex upon entry to _show()/_store() fix all this?
> After obtaining the mutex in _show()/_store(), you check for
> sev->verify_mit and return an error if NULL. Then you can use the
> __sev_do_cmd_locked() to issue any commands.

As long as sysfs_remove_group() happens before
__sev_firmware_shutdown() it seems like it should be fine since sysfs
will do its own synchronization. IIUC we might not need this locking
at all assuming the above is applied?

Tycho
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Tom Lendacky 3 days, 4 hours ago
On 5/21/26 10:05, Tycho Andersen wrote:
> On Thu, May 21, 2026 at 08:12:52AM -0500, Tom Lendacky wrote:
>>> Now, with unregister no longer protected by sev_cmd_mutex, a concurrent init
>>> can race with shutdown on the sysfs lifetime like so:
>>
>> Can it? Can init and shutdown race? Isn't that part of module load /
>> unload, I'm not sure how they can race...
> 
> That's only true after
> https://lore.kernel.org/all/20260504165147.1615643-5-tycho@kernel.org/
> right? Before that, if the first init failed, you could trigger a
> re-init via ioctl(), and presumably trigger the race sashiko is
> complaining about by spamming ioctl() + sysfs writes on separate
> threads.
> 
>>> t1                                 | t2
>>> ---------------------------------- | ----------------------------------
>>> sev_firmware_shutdown()            | sev_platform_init()
>>>   unregister_verify_mitigation()   |   register_verify_mitigation()
>>>     sysfs_remove_group()           |     sysfs_create_group()
>>>
>>> Both sides touch sev->verify_mit without serialization. The same race also
>>> exists for init vs init which is no longer covered by sev_cmd_mutex once
>>> register moves outside it.
>>
>> I don't think you can have init vs init race, can you? This just all seems
>> odd to me. Have you created all these race scenarios to test this out?
>>
>> Would putting the regsiter/unregister under the sev_cmd_mutex and then
>> taking the sev_cmd_mutex upon entry to _show()/_store() fix all this?
>> After obtaining the mutex in _show()/_store(), you check for
>> sev->verify_mit and return an error if NULL. Then you can use the
>> __sev_do_cmd_locked() to issue any commands.
> 
> As long as sysfs_remove_group() happens before
> __sev_firmware_shutdown() it seems like it should be fine since sysfs
> will do its own synchronization. IIUC we might not need this locking
> at all assuming the above is applied?

That's what I'm thinking. I'll let Pratik confirm.

Thanks,
Tom

> 
> Tycho
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Pratik R. Sampat 2 days, 22 hours ago

On 5/21/26 4:04 PM, Tom Lendacky wrote:
> On 5/21/26 10:05, Tycho Andersen wrote:
>> On Thu, May 21, 2026 at 08:12:52AM -0500, Tom Lendacky wrote:
>>>> Now, with unregister no longer protected by sev_cmd_mutex, a concurrent init
>>>> can race with shutdown on the sysfs lifetime like so:
>>>
>>> Can it? Can init and shutdown race? Isn't that part of module load /
>>> unload, I'm not sure how they can race...
>>
>> That's only true after
>> https://lore.kernel.org/all/20260504165147.1615643-5-tycho@kernel.org/
>> right? Before that, if the first init failed, you could trigger a
>> re-init via ioctl(), and presumably trigger the race sashiko is
>> complaining about by spamming ioctl() + sysfs writes on separate
>> threads.

Yes, this is the race I had in mind and probably what sashiko complained about
in it's review too. I missed this patch from earlier. This should avoid any
racing.

>>
>>>> t1                                 | t2
>>>> ---------------------------------- | ----------------------------------
>>>> sev_firmware_shutdown()            | sev_platform_init()
>>>>   unregister_verify_mitigation()   |   register_verify_mitigation()
>>>>     sysfs_remove_group()           |     sysfs_create_group()
>>>>
>>>> Both sides touch sev->verify_mit without serialization. The same race also
>>>> exists for init vs init which is no longer covered by sev_cmd_mutex once
>>>> register moves outside it.
>>>
>>> I don't think you can have init vs init race, can you? This just all seems
>>> odd to me. Have you created all these race scenarios to test this out?
>>>
>>> Would putting the regsiter/unregister under the sev_cmd_mutex and then
>>> taking the sev_cmd_mutex upon entry to _show()/_store() fix all this?
>>> After obtaining the mutex in _show()/_store(), you check for
>>> sev->verify_mit and return an error if NULL. Then you can use the
>>> __sev_do_cmd_locked() to issue any commands.
>>
>> As long as sysfs_remove_group() happens before
>> __sev_firmware_shutdown() it seems like it should be fine since sysfs
>> will do its own synchronization. IIUC we might not need this locking
>> at all assuming the above is applied?
> 
> That's what I'm thinking. I'll let Pratik confirm.
> 

Yes, sysfs should do its own synchronization and I'm assuming this means that we
don't need any locks anymore and I can get rid of the sev_mit_sysfs_mutex and
move unregister outside the sev_cmd_mutex.

I tested this with putting a msleep() in the _show()/_store() and in parallel
rmmod calling shutdown. This seems to work without issues whereas with the
former approach I could deadlock waiting on sev_cmd_mutex.

> 
>>> Also, on the register function, all you need is the check for
>>> !(sev->snp_feat_info_0.ecx & SNP_VERIFY_MITIGATION_SUPPORTED) since if
>>> !sev->snp_plat_status.feature_info is true, so is this this check. And, as
>>> the spec says, the required firmware state is based on the mitigation
>>> requirements, so I don't think you should be checking for snp_initialized.

Ack, will just keep the SNP_VERIFY_MITIGATION_SUPPORTED check in the next
iteration.

Thanks Tom and Tycho!
--Pratik

> Thanks,
> Tom
> 
>>
>> Tycho
>
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by kernel test robot 4 days, 5 hours ago
Hi Pratik,

kernel test robot noticed the following build warnings:

[auto build test WARNING on herbert-cryptodev-2.6/master]
[also build test WARNING on herbert-crypto-2.6/master linus/master v7.1-rc4]
[cannot apply to next-20260520]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pratik-R-Sampat/crypto-ccp-Introduce-SNP_VERIFY_MITIGATION-command/20260520-035846
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
patch link:    https://lore.kernel.org/r/36137b565d183fa2f2985ad098f2e2096f1c432f.1779219958.git.prsampat%40amd.com
patch subject: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
docutils: docutils (Docutils 0.21.2, Python 3.13.5, on linux)
reproduce: (https://download.01.org/0day-ci/archive/20260520/202605202038.zpyF8AIf-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605202038.zpyF8AIf-lkp@intel.com/

All warnings (new ones prefixed by >>):

   WARNING: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/os_mode is defined 2 times: Documentation/ABI/testing/sysfs-driver-hid-lenovo-go:364; Documentation/ABI/testing/sysfs-driver-hid-lenovo-go-s:234
   WARNING: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/os_mode_index is defined 2 times: Documentation/ABI/testing/sysfs-driver-hid-lenovo-go:373; Documentation/ABI/testing/sysfs-driver-hid-lenovo-go-s:243
   WARNING: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/touchpad/enabled is defined 2 times: Documentation/ABI/testing/sysfs-driver-hid-lenovo-go:636; Documentation/ABI/testing/sysfs-driver-hid-lenovo-go-s:252
   WARNING: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/touchpad/enabled_index is defined 2 times: Documentation/ABI/testing/sysfs-driver-hid-lenovo-go:645; Documentation/ABI/testing/sysfs-driver-hid-lenovo-go-s:261
   Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities:1: ERROR: Unexpected indentation. [docutils]
>> Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities:1: WARNING: Block quote ends without a blank line; unexpected unindent. [docutils]
>> Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities:1: WARNING: Definition list ends without a blank line; unexpected unindent. [docutils]
   Documentation/arch/riscv/zicfilp.rst:79: WARNING: Inline literal start-string without end-string. [docutils]
   Documentation/core-api/kref:328: ./include/linux/kref.h:72: WARNING: Invalid C declaration: Expected end of definition. [error at 96]
   int kref_put_mutex (struct kref *kref, void (*release)(struct kref *kref), struct mutex *mutex) __cond_acquires(true# mutex)
   ------------------------------------------------------------------------------------------------^
   Documentation/core-api/kref:328: ./include/linux/kref.h:94: WARNING: Invalid C declaration: Expected end of definition. [error at 92]


vim +1 Documentation/ABI/testing/sysfs-firmware-sev-vulnerabilities

   > 1	What:		/sys/firmware/sev/vulnerabilities/

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Tycho Andersen 4 days, 7 hours ago
On Tue, May 19, 2026 at 02:50:29PM -0500, Pratik R. Sampat wrote:
> 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.
> 
> This command is an explicit mechanism to ascertain if a firmware
> mitigation is applied without needing a full RMP re-build, which is most
> useful in a live firmware update scenario.
> 
> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
> subcommand is used to query the supported and verified mitigation bits.
> The VERIFY subcommand initiates the mitigation process within the FW for
> the specified vulnerability. Expose a userspace interface under:
> /sys/firmware/sev/vulnerabilities/
>   - supported_mitigations (read-only): supported mitigation vector mask
>   - verified_mitigations (read/write): current verified mask; write a
>     vector to request VERIFY for that bit
> 
> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
> it are bug-specific. Information about supported mitigations and its
> corresponding vector is to be published as part of the AMD Security
> Bulletin.
> 
> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
> more details.
> 
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>

Reviewed-by: Tycho Andersen (AMD) <tycho@kernel.org>
Re: [PATCH v3] crypto/ccp: Introduce SNP_VERIFY_MITIGATION command
Posted by Pratik R. Sampat 5 days, 4 hours ago

On 5/19/26 3:50 PM, Pratik R. Sampat wrote:
> 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.
> 
> This command is an explicit mechanism to ascertain if a firmware
> mitigation is applied without needing a full RMP re-build, which is most
> useful in a live firmware update scenario.
> 
> The firmware supports two subcommands: STATUS and VERIFY. The STATUS
> subcommand is used to query the supported and verified mitigation bits.
> The VERIFY subcommand initiates the mitigation process within the FW for
> the specified vulnerability. Expose a userspace interface under:
> /sys/firmware/sev/vulnerabilities/
>   - supported_mitigations (read-only): supported mitigation vector mask
>   - verified_mitigations (read/write): current verified mask; write a
>     vector to request VERIFY for that bit
> 
> The behavior of SNP_VERIFY_MITIGATION and the pre-requisites for using
> it are bug-specific. Information about supported mitigations and its
> corresponding vector is to be published as part of the AMD Security
> Bulletin.
> 
> See SEV-SNP Firmware ABI specifications 1.58, SNP_VERIFY_MITIGATION for
> more details.
> 
> Signed-off-by: Pratik R. Sampat <prsampat@amd.com>
> ---

Apologies, missed adding the changelog with the patch. For the record:

---
v3:
  * Remove failed_status interface and report failure via dev_err - Tycho
  * Make vulnerability interfaces root only accessible - Sashiko
  * Move /sys/firmware/vulnerabilities/ to
    /sys/firmware/sev/vulnerabilities/ to be platform specific - Sashiko
  * Guard sysfs creation under a new mutex to avoid racing during
    creation and using the sev_cmd_mutex which would race with
    vulnerability operations - Sashiko

v2: https://lore.kernel.org/linux-crypto/20260501152051.17469-1-prsampat@amd.com/
  * Intrdouce /sys/firmware/vulnerabilities sysfs interface instead of
    an ioctl interface - Boris
  * Reword commit message to focus on need for a userspace interface - Sean
  * Since download_firmware_ex is the primary usecase of this feature,
    posting this patch in parallel to those discussions[1].
  Link to RFC: https://lore.kernel.org/linux-crypto/20250630202319.56331-1-prsampat@amd.com/

[1]: https://lore.kernel.org/linux-crypto/20260430160716.1120553-1-tycho@kernel.org/
---

Pratik