1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Confidential Computing Platform Capability checks 4 * 5 * Copyright (C) 2021 Advanced Micro Devices, Inc. 6 * Copyright (C) 2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 7 * 8 * Author: Tom Lendacky <thomas.lendacky@amd.com> 9 */ 10 11 #include <linux/export.h> 12 #include <linux/cc_platform.h> 13 #include <linux/string.h> 14 #include <linux/random.h> 15 16 #include <asm/archrandom.h> 17 #include <asm/coco.h> 18 #include <asm/processor.h> 19 20 enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE; 21 SYM_PIC_ALIAS(cc_vendor); 22 u64 cc_mask __ro_after_init; 23 SYM_PIC_ALIAS(cc_mask); 24 25 static struct cc_attr_flags { 26 __u64 host_sev_snp : 1, 27 __resv : 63; 28 } cc_flags; 29 30 static bool noinstr intel_cc_platform_has(enum cc_attr attr) 31 { 32 switch (attr) { 33 case CC_ATTR_GUEST_UNROLL_STRING_IO: 34 case CC_ATTR_GUEST_MEM_ENCRYPT: 35 case CC_ATTR_MEM_ENCRYPT: 36 return true; 37 default: 38 return false; 39 } 40 } 41 42 /* 43 * Handle the SEV-SNP vTOM case where sme_me_mask is zero, and 44 * the other levels of SME/SEV functionality, including C-bit 45 * based SEV-SNP, are not enabled. 46 */ 47 static __maybe_unused __always_inline bool amd_cc_platform_vtom(enum cc_attr attr) 48 { 49 switch (attr) { 50 case CC_ATTR_GUEST_MEM_ENCRYPT: 51 case CC_ATTR_MEM_ENCRYPT: 52 return true; 53 default: 54 return false; 55 } 56 } 57 58 /* 59 * SME and SEV are very similar but they are not the same, so there are 60 * times that the kernel will need to distinguish between SME and SEV. The 61 * cc_platform_has() function is used for this. When a distinction isn't 62 * needed, the CC_ATTR_MEM_ENCRYPT attribute can be used. 63 * 64 * The trampoline code is a good example for this requirement. Before 65 * paging is activated, SME will access all memory as decrypted, but SEV 66 * will access all memory as encrypted. So, when APs are being brought 67 * up under SME the trampoline area cannot be encrypted, whereas under SEV 68 * the trampoline area must be encrypted. 69 */ 70 static bool noinstr amd_cc_platform_has(enum cc_attr attr) 71 { 72 #ifdef CONFIG_AMD_MEM_ENCRYPT 73 74 if (sev_status & MSR_AMD64_SNP_VTOM) 75 return amd_cc_platform_vtom(attr); 76 77 switch (attr) { 78 case CC_ATTR_MEM_ENCRYPT: 79 return sme_me_mask; 80 81 case CC_ATTR_HOST_MEM_ENCRYPT: 82 return sme_me_mask && !(sev_status & MSR_AMD64_SEV_ENABLED); 83 84 case CC_ATTR_GUEST_MEM_ENCRYPT: 85 return sev_status & MSR_AMD64_SEV_ENABLED; 86 87 case CC_ATTR_GUEST_STATE_ENCRYPT: 88 return sev_status & MSR_AMD64_SEV_ES_ENABLED; 89 90 /* 91 * With SEV, the rep string I/O instructions need to be unrolled 92 * but SEV-ES supports them through the #VC handler. 93 */ 94 case CC_ATTR_GUEST_UNROLL_STRING_IO: 95 return (sev_status & MSR_AMD64_SEV_ENABLED) && 96 !(sev_status & MSR_AMD64_SEV_ES_ENABLED); 97 98 case CC_ATTR_GUEST_SEV_SNP: 99 return sev_status & MSR_AMD64_SEV_SNP_ENABLED; 100 101 case CC_ATTR_GUEST_SNP_SECURE_TSC: 102 return sev_status & MSR_AMD64_SNP_SECURE_TSC; 103 104 case CC_ATTR_HOST_SEV_SNP: 105 return cc_flags.host_sev_snp; 106 107 case CC_ATTR_SNP_SECURE_AVIC: 108 return sev_status & MSR_AMD64_SNP_SECURE_AVIC; 109 110 default: 111 return false; 112 } 113 #else 114 return false; 115 #endif 116 } 117 118 bool noinstr cc_platform_has(enum cc_attr attr) 119 { 120 switch (cc_vendor) { 121 case CC_VENDOR_AMD: 122 return amd_cc_platform_has(attr); 123 case CC_VENDOR_INTEL: 124 return intel_cc_platform_has(attr); 125 default: 126 return false; 127 } 128 } 129 EXPORT_SYMBOL_GPL(cc_platform_has); 130 131 u64 cc_mkenc(u64 val) 132 { 133 /* 134 * Both AMD and Intel use a bit in the page table to indicate 135 * encryption status of the page. 136 * 137 * - for AMD, bit *set* means the page is encrypted 138 * - for AMD with vTOM and for Intel, *clear* means encrypted 139 */ 140 switch (cc_vendor) { 141 case CC_VENDOR_AMD: 142 if (sev_status & MSR_AMD64_SNP_VTOM) 143 return val & ~cc_mask; 144 else 145 return val | cc_mask; 146 case CC_VENDOR_INTEL: 147 return val & ~cc_mask; 148 default: 149 return val; 150 } 151 } 152 153 u64 cc_mkdec(u64 val) 154 { 155 /* See comment in cc_mkenc() */ 156 switch (cc_vendor) { 157 case CC_VENDOR_AMD: 158 if (sev_status & MSR_AMD64_SNP_VTOM) 159 return val | cc_mask; 160 else 161 return val & ~cc_mask; 162 case CC_VENDOR_INTEL: 163 return val | cc_mask; 164 default: 165 return val; 166 } 167 } 168 EXPORT_SYMBOL_GPL(cc_mkdec); 169 170 static void amd_cc_platform_clear(enum cc_attr attr) 171 { 172 switch (attr) { 173 case CC_ATTR_HOST_SEV_SNP: 174 cc_flags.host_sev_snp = 0; 175 break; 176 default: 177 break; 178 } 179 } 180 181 void cc_platform_clear(enum cc_attr attr) 182 { 183 switch (cc_vendor) { 184 case CC_VENDOR_AMD: 185 amd_cc_platform_clear(attr); 186 break; 187 default: 188 break; 189 } 190 } 191 192 static void amd_cc_platform_set(enum cc_attr attr) 193 { 194 switch (attr) { 195 case CC_ATTR_HOST_SEV_SNP: 196 cc_flags.host_sev_snp = 1; 197 break; 198 default: 199 break; 200 } 201 } 202 203 void cc_platform_set(enum cc_attr attr) 204 { 205 switch (cc_vendor) { 206 case CC_VENDOR_AMD: 207 amd_cc_platform_set(attr); 208 break; 209 default: 210 break; 211 } 212 } 213 214 __init void cc_random_init(void) 215 { 216 /* 217 * The seed is 32 bytes (in units of longs), which is 256 bits, which 218 * is the security level that the RNG is targeting. 219 */ 220 unsigned long rng_seed[32 / sizeof(long)]; 221 size_t i, longs; 222 223 if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) 224 return; 225 226 /* 227 * Since the CoCo threat model includes the host, the only reliable 228 * source of entropy that can be neither observed nor manipulated is 229 * RDRAND. Usually, RDRAND failure is considered tolerable, but since 230 * CoCo guests have no other unobservable source of entropy, it's 231 * important to at least ensure the RNG gets some initial random seeds. 232 */ 233 for (i = 0; i < ARRAY_SIZE(rng_seed); i += longs) { 234 longs = arch_get_random_longs(&rng_seed[i], ARRAY_SIZE(rng_seed) - i); 235 236 /* 237 * A zero return value means that the guest doesn't have RDRAND 238 * or the CPU is physically broken, and in both cases that 239 * means most crypto inside of the CoCo instance will be 240 * broken, defeating the purpose of CoCo in the first place. So 241 * just panic here because it's absolutely unsafe to continue 242 * executing. 243 */ 244 if (longs == 0) 245 panic("RDRAND is defective."); 246 } 247 add_device_randomness(rng_seed, sizeof(rng_seed)); 248 memzero_explicit(rng_seed, sizeof(rng_seed)); 249 } 250