Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: ccp - Add support for SNP_FEATURE_INFO command

The FEATURE_INFO command provides hypervisors with a programmatic means
to learn about the supported features of the currently loaded firmware.
This command mimics the CPUID instruction relative to sub-leaf input and
the four unsigned integer output values. To obtain information
regarding the features present in the currently loaded SEV firmware,
use the SNP_FEATURE_INFO command.

Cache the SNP platform status and feature information from CPUID
0x8000_0024 in the sev_device structure. If SNP is enabled, utilize
this cached SNP platform status for the API major, minor and build
version.

Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
Reviewed-by: Kim Phillips <kim.phillips@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ashish Kalra and committed by
Herbert Xu
33cfb80d 459daec4

+104
+72
drivers/crypto/ccp/sev-dev.c
··· 233 233 case SEV_CMD_SNP_GUEST_REQUEST: return sizeof(struct sev_data_snp_guest_request); 234 234 case SEV_CMD_SNP_CONFIG: return sizeof(struct sev_user_data_snp_config); 235 235 case SEV_CMD_SNP_COMMIT: return sizeof(struct sev_data_snp_commit); 236 + case SEV_CMD_SNP_FEATURE_INFO: return sizeof(struct sev_data_snp_feature_info); 236 237 default: return 0; 237 238 } 238 239 ··· 1074 1073 wrmsrq(MSR_VM_HSAVE_PA, 0); 1075 1074 } 1076 1075 1076 + static int snp_get_platform_data(struct sev_device *sev, int *error) 1077 + { 1078 + struct sev_data_snp_feature_info snp_feat_info; 1079 + struct snp_feature_info *feat_info; 1080 + struct sev_data_snp_addr buf; 1081 + struct page *page; 1082 + int rc; 1083 + 1084 + /* 1085 + * This function is expected to be called before SNP is 1086 + * initialized. 1087 + */ 1088 + if (sev->snp_initialized) 1089 + return -EINVAL; 1090 + 1091 + buf.address = __psp_pa(&sev->snp_plat_status); 1092 + rc = sev_do_cmd(SEV_CMD_SNP_PLATFORM_STATUS, &buf, error); 1093 + if (rc) { 1094 + dev_err(sev->dev, "SNP PLATFORM_STATUS command failed, ret = %d, error = %#x\n", 1095 + rc, *error); 1096 + return rc; 1097 + } 1098 + 1099 + sev->api_major = sev->snp_plat_status.api_major; 1100 + sev->api_minor = sev->snp_plat_status.api_minor; 1101 + sev->build = sev->snp_plat_status.build_id; 1102 + 1103 + /* 1104 + * Do feature discovery of the currently loaded firmware, 1105 + * and cache feature information from CPUID 0x8000_0024, 1106 + * sub-function 0. 1107 + */ 1108 + if (!sev->snp_plat_status.feature_info) 1109 + return 0; 1110 + 1111 + /* 1112 + * Use dynamically allocated structure for the SNP_FEATURE_INFO 1113 + * command to ensure structure is 8-byte aligned, and does not 1114 + * cross a page boundary. 1115 + */ 1116 + page = alloc_page(GFP_KERNEL); 1117 + if (!page) 1118 + return -ENOMEM; 1119 + 1120 + feat_info = page_address(page); 1121 + snp_feat_info.length = sizeof(snp_feat_info); 1122 + snp_feat_info.ecx_in = 0; 1123 + snp_feat_info.feature_info_paddr = __psp_pa(feat_info); 1124 + 1125 + rc = sev_do_cmd(SEV_CMD_SNP_FEATURE_INFO, &snp_feat_info, error); 1126 + if (!rc) 1127 + sev->snp_feat_info_0 = *feat_info; 1128 + else 1129 + dev_err(sev->dev, "SNP FEATURE_INFO command failed, ret = %d, error = %#x\n", 1130 + rc, *error); 1131 + 1132 + __free_page(page); 1133 + 1134 + return rc; 1135 + } 1136 + 1077 1137 static int snp_filter_reserved_mem_regions(struct resource *rs, void *arg) 1078 1138 { 1079 1139 struct sev_data_range_list *range_list = arg; ··· 1660 1598 struct sev_device *sev = psp_master->sev_data; 1661 1599 struct sev_user_data_status status; 1662 1600 int error = 0, ret; 1601 + 1602 + /* 1603 + * Cache SNP platform status and SNP feature information 1604 + * if SNP is available. 1605 + */ 1606 + if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) { 1607 + ret = snp_get_platform_data(sev, &error); 1608 + if (ret) 1609 + return 1; 1610 + } 1663 1611 1664 1612 ret = sev_platform_status(&status, &error); 1665 1613 if (ret) {
+3
drivers/crypto/ccp/sev-dev.h
··· 58 58 bool snp_initialized; 59 59 60 60 struct sev_user_data_status sev_plat_status; 61 + 62 + struct sev_user_data_snp_status snp_plat_status; 63 + struct snp_feature_info snp_feat_info_0; 61 64 }; 62 65 63 66 int sev_dev_init(struct psp_device *psp);
+29
include/linux/psp-sev.h
··· 107 107 SEV_CMD_SNP_DOWNLOAD_FIRMWARE_EX = 0x0CA, 108 108 SEV_CMD_SNP_COMMIT = 0x0CB, 109 109 SEV_CMD_SNP_VLEK_LOAD = 0x0CD, 110 + SEV_CMD_SNP_FEATURE_INFO = 0x0CE, 110 111 111 112 SEV_CMD_MAX, 112 113 }; ··· 813 812 */ 814 813 struct sev_data_snp_commit { 815 814 u32 len; 815 + } __packed; 816 + 817 + /** 818 + * struct sev_data_snp_feature_info - SEV_SNP_FEATURE_INFO structure 819 + * 820 + * @length: len of the command buffer read by the PSP 821 + * @ecx_in: subfunction index 822 + * @feature_info_paddr : System Physical Address of the FEATURE_INFO structure 823 + */ 824 + struct sev_data_snp_feature_info { 825 + u32 length; 826 + u32 ecx_in; 827 + u64 feature_info_paddr; 828 + } __packed; 829 + 830 + /** 831 + * struct feature_info - FEATURE_INFO structure 832 + * 833 + * @eax: output of SNP_FEATURE_INFO command 834 + * @ebx: output of SNP_FEATURE_INFO command 835 + * @ecx: output of SNP_FEATURE_INFO command 836 + * #edx: output of SNP_FEATURE_INFO command 837 + */ 838 + struct snp_feature_info { 839 + u32 eax; 840 + u32 ebx; 841 + u32 ecx; 842 + u32 edx; 816 843 } __packed; 817 844 818 845 #ifdef CONFIG_CRYPTO_DEV_SP_PSP