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

Merge tag 'kvm-x86-svm-6.9' of https://github.com/kvm-x86/linux into HEAD

KVM SVM changes for 6.9:

- Add support for systems that are configured with SEV and SEV-ES+ enabled,
but have all ASIDs assigned to SEV-ES+ guests, which effectively makes SEV
unusuable. Cleanup ASID handling to make supporting this scenario less
brittle/ugly.

- Return -EINVAL instead of -EBUSY if userspace attempts to invoke
KVM_SEV{,ES}_INIT on an SEV+ guest. The operation is simply invalid, and
not related to resource contention in any way.

+39 -29
+34 -24
arch/x86/kvm/svm/sev.c
··· 84 84 }; 85 85 86 86 /* Called with the sev_bitmap_lock held, or on shutdown */ 87 - static int sev_flush_asids(int min_asid, int max_asid) 87 + static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid) 88 88 { 89 - int ret, asid, error = 0; 89 + int ret, error = 0; 90 + unsigned int asid; 90 91 91 92 /* Check if there are any ASIDs to reclaim before performing a flush */ 92 93 asid = find_next_bit(sev_reclaim_asid_bitmap, nr_asids, min_asid); ··· 117 116 } 118 117 119 118 /* Must be called with the sev_bitmap_lock held */ 120 - static bool __sev_recycle_asids(int min_asid, int max_asid) 119 + static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid) 121 120 { 122 121 if (sev_flush_asids(min_asid, max_asid)) 123 122 return false; ··· 144 143 145 144 static int sev_asid_new(struct kvm_sev_info *sev) 146 145 { 147 - int asid, min_asid, max_asid, ret; 146 + /* 147 + * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. 148 + * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. 149 + * Note: min ASID can end up larger than the max if basic SEV support is 150 + * effectively disabled by disallowing use of ASIDs for SEV guests. 151 + */ 152 + unsigned int min_asid = sev->es_active ? 1 : min_sev_asid; 153 + unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; 154 + unsigned int asid; 148 155 bool retry = true; 156 + int ret; 157 + 158 + if (min_asid > max_asid) 159 + return -ENOTTY; 149 160 150 161 WARN_ON(sev->misc_cg); 151 162 sev->misc_cg = get_current_misc_cg(); ··· 170 157 171 158 mutex_lock(&sev_bitmap_lock); 172 159 173 - /* 174 - * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. 175 - * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. 176 - */ 177 - min_asid = sev->es_active ? 1 : min_sev_asid; 178 - max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; 179 160 again: 180 161 asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid); 181 162 if (asid > max_asid) { ··· 186 179 187 180 mutex_unlock(&sev_bitmap_lock); 188 181 189 - return asid; 182 + sev->asid = asid; 183 + return 0; 190 184 e_uncharge: 191 185 sev_misc_cg_uncharge(sev); 192 186 put_misc_cg(sev->misc_cg); ··· 195 187 return ret; 196 188 } 197 189 198 - static int sev_get_asid(struct kvm *kvm) 190 + static unsigned int sev_get_asid(struct kvm *kvm) 199 191 { 200 192 struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; 201 193 ··· 255 247 { 256 248 struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; 257 249 struct sev_platform_init_args init_args = {0}; 258 - int asid, ret; 250 + int ret; 259 251 260 252 if (kvm->created_vcpus) 261 253 return -EINVAL; 262 254 263 - ret = -EBUSY; 264 255 if (unlikely(sev->active)) 265 - return ret; 256 + return -EINVAL; 266 257 267 258 sev->active = true; 268 259 sev->es_active = argp->id == KVM_SEV_ES_INIT; 269 - asid = sev_asid_new(sev); 270 - if (asid < 0) 260 + ret = sev_asid_new(sev); 261 + if (ret) 271 262 goto e_no_asid; 272 - sev->asid = asid; 273 263 274 264 init_args.probe = false; 275 265 ret = sev_platform_init(&init_args); ··· 293 287 294 288 static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error) 295 289 { 290 + unsigned int asid = sev_get_asid(kvm); 296 291 struct sev_data_activate activate; 297 - int asid = sev_get_asid(kvm); 298 292 int ret; 299 293 300 294 /* activate ASID on the given handle */ ··· 2246 2240 goto out; 2247 2241 } 2248 2242 2249 - sev_asid_count = max_sev_asid - min_sev_asid + 1; 2250 - WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); 2243 + if (min_sev_asid <= max_sev_asid) { 2244 + sev_asid_count = max_sev_asid - min_sev_asid + 1; 2245 + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); 2246 + } 2251 2247 sev_supported = true; 2252 2248 2253 2249 /* SEV-ES support requested? */ ··· 2280 2272 out: 2281 2273 if (boot_cpu_has(X86_FEATURE_SEV)) 2282 2274 pr_info("SEV %s (ASIDs %u - %u)\n", 2283 - sev_supported ? "enabled" : "disabled", 2275 + sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" : 2276 + "unusable" : 2277 + "disabled", 2284 2278 min_sev_asid, max_sev_asid); 2285 2279 if (boot_cpu_has(X86_FEATURE_SEV_ES)) 2286 2280 pr_info("SEV-ES %s (ASIDs %u - %u)\n", ··· 2330 2320 */ 2331 2321 static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va) 2332 2322 { 2333 - int asid = to_kvm_svm(vcpu->kvm)->sev_info.asid; 2323 + unsigned int asid = sev_get_asid(vcpu->kvm); 2334 2324 2335 2325 /* 2336 2326 * Note! The address must be a kernel address, as regular page walk ··· 2648 2638 void pre_sev_run(struct vcpu_svm *svm, int cpu) 2649 2639 { 2650 2640 struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu); 2651 - int asid = sev_get_asid(svm->vcpu.kvm); 2641 + unsigned int asid = sev_get_asid(svm->vcpu.kvm); 2652 2642 2653 2643 /* Assign the asid allocated with this SEV guest */ 2654 2644 svm->asid = asid;
+5 -5
arch/x86/kvm/trace.h
··· 735 735 * Tracepoint for nested #vmexit because of interrupt pending 736 736 */ 737 737 TRACE_EVENT(kvm_invlpga, 738 - TP_PROTO(__u64 rip, int asid, u64 address), 738 + TP_PROTO(__u64 rip, unsigned int asid, u64 address), 739 739 TP_ARGS(rip, asid, address), 740 740 741 741 TP_STRUCT__entry( 742 - __field( __u64, rip ) 743 - __field( int, asid ) 744 - __field( __u64, address ) 742 + __field( __u64, rip ) 743 + __field( unsigned int, asid ) 744 + __field( __u64, address ) 745 745 ), 746 746 747 747 TP_fast_assign( ··· 750 750 __entry->address = address; 751 751 ), 752 752 753 - TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx", 753 + TP_printk("rip: 0x%016llx asid: %u address: 0x%016llx", 754 754 __entry->rip, __entry->asid, __entry->address) 755 755 ); 756 756