Commit f656ce01 authored by Marcelo Tosatti's avatar Marcelo Tosatti

KVM: switch vcpu context to use SRCU

Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent e93f8a0f
...@@ -636,12 +636,9 @@ static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu) ...@@ -636,12 +636,9 @@ static void kvm_vcpu_post_transition(struct kvm_vcpu *vcpu)
static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{ {
union context *host_ctx, *guest_ctx; union context *host_ctx, *guest_ctx;
int r; int r, idx;
/* idx = srcu_read_lock(&vcpu->kvm->srcu);
* down_read() may sleep and return with interrupts enabled
*/
down_read(&vcpu->kvm->slots_lock);
again: again:
if (signal_pending(current)) { if (signal_pending(current)) {
...@@ -663,7 +660,7 @@ again: ...@@ -663,7 +660,7 @@ again:
if (r < 0) if (r < 0)
goto vcpu_run_fail; goto vcpu_run_fail;
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
kvm_guest_enter(); kvm_guest_enter();
/* /*
...@@ -687,7 +684,7 @@ again: ...@@ -687,7 +684,7 @@ again:
kvm_guest_exit(); kvm_guest_exit();
preempt_enable(); preempt_enable();
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
r = kvm_handle_exit(kvm_run, vcpu); r = kvm_handle_exit(kvm_run, vcpu);
...@@ -697,10 +694,10 @@ again: ...@@ -697,10 +694,10 @@ again:
} }
out: out:
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (r > 0) { if (r > 0) {
kvm_resched(vcpu); kvm_resched(vcpu);
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
goto again; goto again;
} }
......
...@@ -67,10 +67,14 @@ static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu) ...@@ -67,10 +67,14 @@ static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu) static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
{ {
int idx;
struct kvm_memory_slot *mem; struct kvm_memory_slot *mem;
struct kvm_memslots *memslots;
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
mem = &vcpu->kvm->memslots[0]; memslots = rcu_dereference(vcpu->kvm->memslots);
mem = &memslots->memslots[0];
vcpu->arch.sie_block->gmsor = mem->userspace_addr; vcpu->arch.sie_block->gmsor = mem->userspace_addr;
vcpu->arch.sie_block->gmslm = vcpu->arch.sie_block->gmslm =
...@@ -78,7 +82,7 @@ static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu) ...@@ -78,7 +82,7 @@ static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
(mem->npages << PAGE_SHIFT) + (mem->npages << PAGE_SHIFT) +
VIRTIODESCSPACE - 1ul; VIRTIODESCSPACE - 1ul;
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
} }
/* implemented in priv.c */ /* implemented in priv.c */
......
...@@ -2933,10 +2933,9 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) ...@@ -2933,10 +2933,9 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
spin_lock(&kvm_lock); spin_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list) { list_for_each_entry(kvm, &vm_list, vm_list) {
int npages; int npages, idx;
if (!down_read_trylock(&kvm->slots_lock)) idx = srcu_read_lock(&kvm->srcu);
continue;
spin_lock(&kvm->mmu_lock); spin_lock(&kvm->mmu_lock);
npages = kvm->arch.n_alloc_mmu_pages - npages = kvm->arch.n_alloc_mmu_pages -
kvm->arch.n_free_mmu_pages; kvm->arch.n_free_mmu_pages;
...@@ -2949,7 +2948,7 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask) ...@@ -2949,7 +2948,7 @@ static int mmu_shrink(int nr_to_scan, gfp_t gfp_mask)
nr_to_scan--; nr_to_scan--;
spin_unlock(&kvm->mmu_lock); spin_unlock(&kvm->mmu_lock);
up_read(&kvm->slots_lock); srcu_read_unlock(&kvm->srcu, idx);
} }
if (kvm_freed) if (kvm_freed)
list_move_tail(&kvm_freed->vm_list, &vm_list); list_move_tail(&kvm_freed->vm_list, &vm_list);
......
...@@ -2478,10 +2478,10 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) ...@@ -2478,10 +2478,10 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
u64 msr; u64 msr;
int ret; int ret, idx;
vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)); vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
if (!init_rmode(vmx->vcpu.kvm)) { if (!init_rmode(vmx->vcpu.kvm)) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -2589,7 +2589,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) ...@@ -2589,7 +2589,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx->emulation_required = 0; vmx->emulation_required = 0;
out: out:
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
return ret; return ret;
} }
......
...@@ -1306,15 +1306,15 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs, ...@@ -1306,15 +1306,15 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
int (*do_msr)(struct kvm_vcpu *vcpu, int (*do_msr)(struct kvm_vcpu *vcpu,
unsigned index, u64 *data)) unsigned index, u64 *data))
{ {
int i; int i, idx;
vcpu_load(vcpu); vcpu_load(vcpu);
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
for (i = 0; i < msrs->nmsrs; ++i) for (i = 0; i < msrs->nmsrs; ++i)
if (do_msr(vcpu, entries[i].index, &entries[i].data)) if (do_msr(vcpu, entries[i].index, &entries[i].data))
break; break;
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
vcpu_put(vcpu); vcpu_put(vcpu);
...@@ -3900,14 +3900,15 @@ static void vapic_enter(struct kvm_vcpu *vcpu) ...@@ -3900,14 +3900,15 @@ static void vapic_enter(struct kvm_vcpu *vcpu)
static void vapic_exit(struct kvm_vcpu *vcpu) static void vapic_exit(struct kvm_vcpu *vcpu)
{ {
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
int idx;
if (!apic || !apic->vapic_addr) if (!apic || !apic->vapic_addr)
return; return;
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
kvm_release_page_dirty(apic->vapic_page); kvm_release_page_dirty(apic->vapic_page);
mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
} }
static void update_cr8_intercept(struct kvm_vcpu *vcpu) static void update_cr8_intercept(struct kvm_vcpu *vcpu)
...@@ -4036,7 +4037,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) ...@@ -4036,7 +4037,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
kvm_lapic_sync_to_vapic(vcpu); kvm_lapic_sync_to_vapic(vcpu);
} }
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
kvm_guest_enter(); kvm_guest_enter();
...@@ -4078,7 +4079,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) ...@@ -4078,7 +4079,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
preempt_enable(); preempt_enable();
down_read(&vcpu->kvm->slots_lock); vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
/* /*
* Profile KVM exit RIPs: * Profile KVM exit RIPs:
...@@ -4100,6 +4101,7 @@ out: ...@@ -4100,6 +4101,7 @@ out:
static int __vcpu_run(struct kvm_vcpu *vcpu) static int __vcpu_run(struct kvm_vcpu *vcpu)
{ {
int r; int r;
struct kvm *kvm = vcpu->kvm;
if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) { if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED)) {
pr_debug("vcpu %d received sipi with vector # %x\n", pr_debug("vcpu %d received sipi with vector # %x\n",
...@@ -4111,7 +4113,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) ...@@ -4111,7 +4113,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
} }
down_read(&vcpu->kvm->slots_lock); vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
vapic_enter(vcpu); vapic_enter(vcpu);
r = 1; r = 1;
...@@ -4119,9 +4121,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) ...@@ -4119,9 +4121,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
r = vcpu_enter_guest(vcpu); r = vcpu_enter_guest(vcpu);
else { else {
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
kvm_vcpu_block(vcpu); kvm_vcpu_block(vcpu);
down_read(&vcpu->kvm->slots_lock); vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests)) if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
{ {
switch(vcpu->arch.mp_state) { switch(vcpu->arch.mp_state) {
...@@ -4156,13 +4158,13 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) ...@@ -4156,13 +4158,13 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
++vcpu->stat.signal_exits; ++vcpu->stat.signal_exits;
} }
if (need_resched()) { if (need_resched()) {
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
kvm_resched(vcpu); kvm_resched(vcpu);
down_read(&vcpu->kvm->slots_lock); vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
} }
} }
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
post_kvm_run_save(vcpu); post_kvm_run_save(vcpu);
vapic_exit(vcpu); vapic_exit(vcpu);
...@@ -4201,10 +4203,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -4201,10 +4203,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
vcpu->mmio_read_completed = 1; vcpu->mmio_read_completed = 1;
vcpu->mmio_needed = 0; vcpu->mmio_needed = 0;
down_read(&vcpu->kvm->slots_lock); vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
r = emulate_instruction(vcpu, vcpu->arch.mmio_fault_cr2, 0, r = emulate_instruction(vcpu, vcpu->arch.mmio_fault_cr2, 0,
EMULTYPE_NO_DECODE); EMULTYPE_NO_DECODE);
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
if (r == EMULATE_DO_MMIO) { if (r == EMULATE_DO_MMIO) {
/* /*
* Read-modify-write. Back to userspace. * Read-modify-write. Back to userspace.
...@@ -4967,11 +4969,12 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, ...@@ -4967,11 +4969,12 @@ int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
{ {
unsigned long vaddr = tr->linear_address; unsigned long vaddr = tr->linear_address;
gpa_t gpa; gpa_t gpa;
int idx;
vcpu_load(vcpu); vcpu_load(vcpu);
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr); gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, vaddr);
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
tr->physical_address = gpa; tr->physical_address = gpa;
tr->valid = gpa != UNMAPPED_GVA; tr->valid = gpa != UNMAPPED_GVA;
tr->writeable = 1; tr->writeable = 1;
...@@ -5223,11 +5226,13 @@ fail: ...@@ -5223,11 +5226,13 @@ fail:
void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
{ {
int idx;
kfree(vcpu->arch.mce_banks); kfree(vcpu->arch.mce_banks);
kvm_free_lapic(vcpu); kvm_free_lapic(vcpu);
down_read(&vcpu->kvm->slots_lock); idx = srcu_read_lock(&vcpu->kvm->srcu);
kvm_mmu_destroy(vcpu); kvm_mmu_destroy(vcpu);
up_read(&vcpu->kvm->slots_lock); srcu_read_unlock(&vcpu->kvm->srcu, idx);
free_page((unsigned long)vcpu->arch.pio_data); free_page((unsigned long)vcpu->arch.pio_data);
} }
......
...@@ -83,6 +83,8 @@ struct kvm_vcpu { ...@@ -83,6 +83,8 @@ struct kvm_vcpu {
struct kvm_run *run; struct kvm_run *run;
unsigned long requests; unsigned long requests;
unsigned long guest_debug; unsigned long guest_debug;
int srcu_idx;
int fpu_active; int fpu_active;
int guest_fpu_loaded; int guest_fpu_loaded;
wait_queue_head_t wq; wait_queue_head_t wq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment