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. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEKTobbabEP7vbhhN9OlYIJqCjN/0FAmXeMssACgkQOlYIJqCj N/3UQg/8D5J0N1jqE6cnPsN3OA733Q+fRkfJd6zLUn5qJ8jqssxeNUiRCCUYIP8b ijuUB1/SCphQoIlAmy73+lmLOs2AMtW5Qaephekv4YZlSlsqIbIq12LJ88PGv/Gd WO6zxeWnIPh1jLvaHA5bqEg6VC/vyl0enCXaw6o0ll3UubAQ5wcHaYoW0SM28bT3 mHJJBjElgvV9845y3sZkWYYP4AYAbrhNWVJLYgxZjByCYPHo5h0bffZKzniWxAZQ kANkotYJ2mMXAnagmuUvxOBxzSSVn7dYijR6u7eAx5PPodv9mptrFyY0XdGl0o8O MexEF4IQRpJN4JhFmC0Wm0Zw42TDq+CSBv2YqHEfnpgN7BYjIqiefx3+DdaQ3fwp czd+EVHHqDOklyCpBmOtZAtqSrSNAJn7OJk36Q/SCaEMbmgyE1nCNAZ7CubHpwET 9jGumcQ2gd+fcw8Ju8ehxD9su7tQun93gIZ5DGGcw3/x0P85V5eWvafjqv5lNnZ+ 5uwHFqt9Bir1Pdk59MyWpIH1YZ//Us3KYe+yApRwyjxMpiilrkYYowvQbu0/3BKo 0WcIDnTezYlF1EdHBruok/lgmIKm04FrlbxwAGFUFD0ClBSwZCr9K59gczX3v4sq giI4lWoHwRN79hM6QioeJcFDzSaxos9hppgcAw0+1fL8RsOPedA= =9jK/ -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
1d55934ed5
@ -84,9 +84,10 @@ struct enc_region {
|
||||
};
|
||||
|
||||
/* Called with the sev_bitmap_lock held, or on shutdown */
|
||||
static int sev_flush_asids(int min_asid, int max_asid)
|
||||
static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid)
|
||||
{
|
||||
int ret, asid, error = 0;
|
||||
int ret, error = 0;
|
||||
unsigned int asid;
|
||||
|
||||
/* Check if there are any ASIDs to reclaim before performing a flush */
|
||||
asid = find_next_bit(sev_reclaim_asid_bitmap, nr_asids, min_asid);
|
||||
@ -116,7 +117,7 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm)
|
||||
}
|
||||
|
||||
/* Must be called with the sev_bitmap_lock held */
|
||||
static bool __sev_recycle_asids(int min_asid, int max_asid)
|
||||
static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid)
|
||||
{
|
||||
if (sev_flush_asids(min_asid, max_asid))
|
||||
return false;
|
||||
@ -143,8 +144,20 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
|
||||
|
||||
static int sev_asid_new(struct kvm_sev_info *sev)
|
||||
{
|
||||
int asid, min_asid, max_asid, ret;
|
||||
/*
|
||||
* SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
|
||||
* SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
|
||||
* Note: min ASID can end up larger than the max if basic SEV support is
|
||||
* effectively disabled by disallowing use of ASIDs for SEV guests.
|
||||
*/
|
||||
unsigned int min_asid = sev->es_active ? 1 : min_sev_asid;
|
||||
unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
|
||||
unsigned int asid;
|
||||
bool retry = true;
|
||||
int ret;
|
||||
|
||||
if (min_asid > max_asid)
|
||||
return -ENOTTY;
|
||||
|
||||
WARN_ON(sev->misc_cg);
|
||||
sev->misc_cg = get_current_misc_cg();
|
||||
@ -157,12 +170,6 @@ static int sev_asid_new(struct kvm_sev_info *sev)
|
||||
|
||||
mutex_lock(&sev_bitmap_lock);
|
||||
|
||||
/*
|
||||
* SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
|
||||
* SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
|
||||
*/
|
||||
min_asid = sev->es_active ? 1 : min_sev_asid;
|
||||
max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
|
||||
again:
|
||||
asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid);
|
||||
if (asid > max_asid) {
|
||||
@ -179,7 +186,8 @@ again:
|
||||
|
||||
mutex_unlock(&sev_bitmap_lock);
|
||||
|
||||
return asid;
|
||||
sev->asid = asid;
|
||||
return 0;
|
||||
e_uncharge:
|
||||
sev_misc_cg_uncharge(sev);
|
||||
put_misc_cg(sev->misc_cg);
|
||||
@ -187,7 +195,7 @@ e_uncharge:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sev_get_asid(struct kvm *kvm)
|
||||
static unsigned int sev_get_asid(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
|
||||
|
||||
@ -247,21 +255,19 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
||||
{
|
||||
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
|
||||
struct sev_platform_init_args init_args = {0};
|
||||
int asid, ret;
|
||||
int ret;
|
||||
|
||||
if (kvm->created_vcpus)
|
||||
return -EINVAL;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (unlikely(sev->active))
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
|
||||
sev->active = true;
|
||||
sev->es_active = argp->id == KVM_SEV_ES_INIT;
|
||||
asid = sev_asid_new(sev);
|
||||
if (asid < 0)
|
||||
ret = sev_asid_new(sev);
|
||||
if (ret)
|
||||
goto e_no_asid;
|
||||
sev->asid = asid;
|
||||
|
||||
init_args.probe = false;
|
||||
ret = sev_platform_init(&init_args);
|
||||
@ -287,8 +293,8 @@ e_no_asid:
|
||||
|
||||
static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
|
||||
{
|
||||
unsigned int asid = sev_get_asid(kvm);
|
||||
struct sev_data_activate activate;
|
||||
int asid = sev_get_asid(kvm);
|
||||
int ret;
|
||||
|
||||
/* activate ASID on the given handle */
|
||||
@ -2240,8 +2246,10 @@ void __init sev_hardware_setup(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sev_asid_count = max_sev_asid - min_sev_asid + 1;
|
||||
WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
|
||||
if (min_sev_asid <= max_sev_asid) {
|
||||
sev_asid_count = max_sev_asid - min_sev_asid + 1;
|
||||
WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
|
||||
}
|
||||
sev_supported = true;
|
||||
|
||||
/* SEV-ES support requested? */
|
||||
@ -2272,7 +2280,9 @@ void __init sev_hardware_setup(void)
|
||||
out:
|
||||
if (boot_cpu_has(X86_FEATURE_SEV))
|
||||
pr_info("SEV %s (ASIDs %u - %u)\n",
|
||||
sev_supported ? "enabled" : "disabled",
|
||||
sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" :
|
||||
"unusable" :
|
||||
"disabled",
|
||||
min_sev_asid, max_sev_asid);
|
||||
if (boot_cpu_has(X86_FEATURE_SEV_ES))
|
||||
pr_info("SEV-ES %s (ASIDs %u - %u)\n",
|
||||
@ -2320,7 +2330,7 @@ int sev_cpu_init(struct svm_cpu_data *sd)
|
||||
*/
|
||||
static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va)
|
||||
{
|
||||
int asid = to_kvm_svm(vcpu->kvm)->sev_info.asid;
|
||||
unsigned int asid = sev_get_asid(vcpu->kvm);
|
||||
|
||||
/*
|
||||
* Note! The address must be a kernel address, as regular page walk
|
||||
@ -2638,7 +2648,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
|
||||
void pre_sev_run(struct vcpu_svm *svm, int cpu)
|
||||
{
|
||||
struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
|
||||
int asid = sev_get_asid(svm->vcpu.kvm);
|
||||
unsigned int asid = sev_get_asid(svm->vcpu.kvm);
|
||||
|
||||
/* Assign the asid allocated with this SEV guest */
|
||||
svm->asid = asid;
|
||||
|
@ -735,13 +735,13 @@ TRACE_EVENT(kvm_nested_intr_vmexit,
|
||||
* Tracepoint for nested #vmexit because of interrupt pending
|
||||
*/
|
||||
TRACE_EVENT(kvm_invlpga,
|
||||
TP_PROTO(__u64 rip, int asid, u64 address),
|
||||
TP_PROTO(__u64 rip, unsigned int asid, u64 address),
|
||||
TP_ARGS(rip, asid, address),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( __u64, rip )
|
||||
__field( int, asid )
|
||||
__field( __u64, address )
|
||||
__field( __u64, rip )
|
||||
__field( unsigned int, asid )
|
||||
__field( __u64, address )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
@ -750,7 +750,7 @@ TRACE_EVENT(kvm_invlpga,
|
||||
__entry->address = address;
|
||||
),
|
||||
|
||||
TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx",
|
||||
TP_printk("rip: 0x%016llx asid: %u address: 0x%016llx",
|
||||
__entry->rip, __entry->asid, __entry->address)
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user