sev_firmware_shutdown(sev);
}
+
+static int get_v1_svn(struct sev_device *sev)
+{
+ struct sev_snp_tcb_version_genoa_milan *tcb;
+ struct sev_user_data_snp_status status;
+ int ret, error = 0;
+
+ mutex_lock(&sev_cmd_mutex);
+ ret = __sev_do_snp_platform_status(&status, &error);
+ mutex_unlock(&sev_cmd_mutex);
+ if (ret < 0)
+ return ret;
+
+ tcb = (struct sev_snp_tcb_version_genoa_milan *)&status
+ .current_tcb_version;
+ return tcb->snp;
+}
+
+static int get_v2_svn(struct sev_device *sev)
+{
+ struct sev_user_data_snp_status status;
+ struct sev_snp_tcb_version_turin *tcb;
+ int ret, error = 0;
+
+ mutex_lock(&sev_cmd_mutex);
+ ret = __sev_do_snp_platform_status(&status, &error);
+ mutex_unlock(&sev_cmd_mutex);
+ if (ret < 0)
+ return ret;
+
+ tcb = (struct sev_snp_tcb_version_turin *)&status
+ .current_tcb_version;
+ return tcb->snp;
+}
+
+static bool sev_firmware_allows_es(struct sev_device *sev)
+{
+ /* Documented in AMD-SB-3023 */
+ if (boot_cpu_has(X86_FEATURE_ZEN4) || boot_cpu_has(X86_FEATURE_ZEN3))
+ return get_v1_svn(sev) < 0x1b;
+ else if (boot_cpu_has(X86_FEATURE_ZEN5))
+ return get_v2_svn(sev) < 0x4;
+ else
+ return true;
+}
+
+int sev_firmware_supported_vm_types(void)
+{
+ int supported_vm_types = 0;
+ struct sev_device *sev;
+
+ if (!psp_master || !psp_master->sev_data)
+ return supported_vm_types;
+ sev = psp_master->sev_data;
+
+ supported_vm_types |= BIT(KVM_X86_SEV_VM);
+ supported_vm_types |= BIT(KVM_X86_SEV_ES_VM);
+
+ if (!sev->snp_initialized)
+ return supported_vm_types;
+
+ supported_vm_types |= BIT(KVM_X86_SNP_VM);
+
+ if (!sev_firmware_allows_es(sev))
+ supported_vm_types &= ~BIT(KVM_X86_SEV_ES_VM);
+
+ return supported_vm_types;
+
+}
+EXPORT_SYMBOL_FOR_MODULES(sev_firmware_supported_vm_types, "kvm-amd");
/* Feature bits in EBX */
#define SNP_SEV_TIO_SUPPORTED BIT(1)
+/**
+ * struct sev_snp_tcb_version_genoa_milan
+ *
+ * @boot_loader: SVN of PSP bootloader
+ * @tee: SVN of PSP operating system
+ * @reserved: reserved
+ * @snp: SVN of SNP firmware
+ * @microcode: Lowest current patch level of all cores
+ */
+struct sev_snp_tcb_version_genoa_milan {
+ u8 boot_loader;
+ u8 tee;
+ u8 reserved[4];
+ u8 snp;
+ u8 microcode;
+};
+
+/**
+ * struct sev_snp_tcb_version_turin
+ *
+ * @fmc: SVN of FMC firmware
+ * @boot_loader: SVN of PSP bootloader
+ * @tee: SVN of PSP operating system
+ * @snp: SVN of SNP firmware
+ * @reserved: reserved
+ * @microcode: Lowest current patch level of all cores
+ */
+struct sev_snp_tcb_version_turin {
+ u8 fmc;
+ u8 boot_loader;
+ u8 tee;
+ u8 snp;
+ u8 reserved[3];
+ u8 microcode;
+};
+
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
/**
void sev_platform_shutdown(void);
bool sev_is_snp_ciphertext_hiding_supported(void);
u64 sev_get_snp_policy_bits(void);
+int sev_firmware_supported_vm_types(void);
#else /* !CONFIG_CRYPTO_DEV_SP_PSP */