Skip to content

Commit

Permalink
KVM: SVM: Serialize access to the SEV ASID bitmap
Browse files Browse the repository at this point in the history
The SEV ASID bitmap currently is not protected against parallel SEV guest
startups. This can result in an SEV guest failing to start because another
SEV guest could have been assigned the same ASID value. Use a mutex to
serialize access to the SEV ASID bitmap.

Fixes: 1654efc ("KVM: SVM: Add KVM_SEV_INIT command")
Tested-by: David Rientjes <rientjes@google.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
Tom Lendacky authored and Paolo Bonzini committed Oct 22, 2019
1 parent 20baa8e commit e3b9a9e
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions arch/x86/kvm/svm.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ enum {

#define VMCB_AVIC_APIC_BAR_MASK 0xFFFFFFFFFF000ULL

static DEFINE_MUTEX(sev_bitmap_lock);
static unsigned int max_sev_asid;
static unsigned int min_sev_asid;
static unsigned long *sev_asid_bitmap;
Expand Down Expand Up @@ -1723,25 +1724,22 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
return 0;
}

static void __sev_asid_free(int asid)
static void sev_asid_free(int asid)
{
struct svm_cpu_data *sd;
int cpu, pos;

mutex_lock(&sev_bitmap_lock);

pos = asid - 1;
clear_bit(pos, sev_asid_bitmap);
__clear_bit(pos, sev_asid_bitmap);

for_each_possible_cpu(cpu) {
sd = per_cpu(svm_data, cpu);
sd->sev_vmcbs[pos] = NULL;
}
}

static void sev_asid_free(struct kvm *kvm)
{
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;

__sev_asid_free(sev->asid);
mutex_unlock(&sev_bitmap_lock);
}

static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
Expand Down Expand Up @@ -1910,7 +1908,7 @@ static void sev_vm_destroy(struct kvm *kvm)
mutex_unlock(&kvm->lock);

sev_unbind_asid(kvm, sev->handle);
sev_asid_free(kvm);
sev_asid_free(sev->asid);
}

static void avic_vm_destroy(struct kvm *kvm)
Expand Down Expand Up @@ -6268,14 +6266,21 @@ static int sev_asid_new(void)
{
int pos;

mutex_lock(&sev_bitmap_lock);

/*
* SEV-enabled guest must use asid from min_sev_asid to max_sev_asid.
*/
pos = find_next_zero_bit(sev_asid_bitmap, max_sev_asid, min_sev_asid - 1);
if (pos >= max_sev_asid)
if (pos >= max_sev_asid) {
mutex_unlock(&sev_bitmap_lock);
return -EBUSY;
}

__set_bit(pos, sev_asid_bitmap);

mutex_unlock(&sev_bitmap_lock);

set_bit(pos, sev_asid_bitmap);
return pos + 1;
}

Expand Down Expand Up @@ -6303,7 +6308,7 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
return 0;

e_free:
__sev_asid_free(asid);
sev_asid_free(asid);
return ret;
}

Expand Down

0 comments on commit e3b9a9e

Please sign in to comment.