Commit 63f4711a authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Avi Kivity:
 "Two asynchronous page fault fixes (one guest, one host), a powerpc
  page refcount fix, and an ia64 build fix."

* git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: ia64: fix build due to typo
  KVM: PPC: Book3S HV: Fix refcounting of hugepages
  KVM: Do not take reference to mm during async #PF
  KVM: ensure async PF event wakes up vcpu from halt
parents 6a5beacc 331b646d
...@@ -1174,7 +1174,7 @@ static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data) ...@@ -1174,7 +1174,7 @@ static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data)
bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
{ {
return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL); return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
} }
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
......
...@@ -258,6 +258,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn, ...@@ -258,6 +258,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
!(memslot->userspace_addr & (s - 1))) { !(memslot->userspace_addr & (s - 1))) {
start &= ~(s - 1); start &= ~(s - 1);
pgsize = s; pgsize = s;
get_page(hpage);
put_page(page);
page = hpage; page = hpage;
} }
} }
...@@ -281,11 +283,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn, ...@@ -281,11 +283,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
err = 0; err = 0;
out: out:
if (got) { if (got)
if (PageHuge(page))
page = compound_head(page);
put_page(page); put_page(page);
}
return err; return err;
up_err: up_err:
...@@ -678,8 +677,15 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, ...@@ -678,8 +677,15 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
SetPageDirty(page); SetPageDirty(page);
out_put: out_put:
if (page) if (page) {
put_page(page); /*
* We drop pages[0] here, not page because page might
* have been set to the head page of a compound, but
* we have to drop the reference on the correct tail
* page to match the get inside gup()
*/
put_page(pages[0]);
}
return ret; return ret;
out_unlock: out_unlock:
...@@ -979,6 +985,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa, ...@@ -979,6 +985,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
pa = *physp; pa = *physp;
} }
page = pfn_to_page(pa >> PAGE_SHIFT); page = pfn_to_page(pa >> PAGE_SHIFT);
get_page(page);
} else { } else {
hva = gfn_to_hva_memslot(memslot, gfn); hva = gfn_to_hva_memslot(memslot, gfn);
npages = get_user_pages_fast(hva, 1, 1, pages); npages = get_user_pages_fast(hva, 1, 1, pages);
...@@ -991,8 +998,6 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa, ...@@ -991,8 +998,6 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
page = compound_head(page); page = compound_head(page);
psize <<= compound_order(page); psize <<= compound_order(page);
} }
if (!kvm->arch.using_mmu_notifiers)
get_page(page);
offset = gpa & (psize - 1); offset = gpa & (psize - 1);
if (nb_ret) if (nb_ret)
*nb_ret = psize - offset; *nb_ret = psize - offset;
...@@ -1003,7 +1008,6 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va) ...@@ -1003,7 +1008,6 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
{ {
struct page *page = virt_to_page(va); struct page *page = virt_to_page(va);
page = compound_head(page);
put_page(page); put_page(page);
} }
......
...@@ -1192,8 +1192,6 @@ static void unpin_slot(struct kvm *kvm, int slot_id) ...@@ -1192,8 +1192,6 @@ static void unpin_slot(struct kvm *kvm, int slot_id)
continue; continue;
pfn = physp[j] >> PAGE_SHIFT; pfn = physp[j] >> PAGE_SHIFT;
page = pfn_to_page(pfn); page = pfn_to_page(pfn);
if (PageHuge(page))
page = compound_head(page);
SetPageDirty(page); SetPageDirty(page);
put_page(page); put_page(page);
} }
......
...@@ -79,7 +79,6 @@ struct kvm_task_sleep_node { ...@@ -79,7 +79,6 @@ struct kvm_task_sleep_node {
u32 token; u32 token;
int cpu; int cpu;
bool halted; bool halted;
struct mm_struct *mm;
}; };
static struct kvm_task_sleep_head { static struct kvm_task_sleep_head {
...@@ -126,9 +125,7 @@ void kvm_async_pf_task_wait(u32 token) ...@@ -126,9 +125,7 @@ void kvm_async_pf_task_wait(u32 token)
n.token = token; n.token = token;
n.cpu = smp_processor_id(); n.cpu = smp_processor_id();
n.mm = current->active_mm;
n.halted = idle || preempt_count() > 1; n.halted = idle || preempt_count() > 1;
atomic_inc(&n.mm->mm_count);
init_waitqueue_head(&n.wq); init_waitqueue_head(&n.wq);
hlist_add_head(&n.link, &b->list); hlist_add_head(&n.link, &b->list);
spin_unlock(&b->lock); spin_unlock(&b->lock);
...@@ -161,9 +158,6 @@ EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait); ...@@ -161,9 +158,6 @@ EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait);
static void apf_task_wake_one(struct kvm_task_sleep_node *n) static void apf_task_wake_one(struct kvm_task_sleep_node *n)
{ {
hlist_del_init(&n->link); hlist_del_init(&n->link);
if (!n->mm)
return;
mmdrop(n->mm);
if (n->halted) if (n->halted)
smp_send_reschedule(n->cpu); smp_send_reschedule(n->cpu);
else if (waitqueue_active(&n->wq)) else if (waitqueue_active(&n->wq))
...@@ -207,7 +201,7 @@ void kvm_async_pf_task_wake(u32 token) ...@@ -207,7 +201,7 @@ void kvm_async_pf_task_wake(u32 token)
* async PF was not yet handled. * async PF was not yet handled.
* Add dummy entry for the token. * Add dummy entry for the token.
*/ */
n = kmalloc(sizeof(*n), GFP_ATOMIC); n = kzalloc(sizeof(*n), GFP_ATOMIC);
if (!n) { if (!n) {
/* /*
* Allocation failed! Busy wait while other cpu * Allocation failed! Busy wait while other cpu
...@@ -219,7 +213,6 @@ void kvm_async_pf_task_wake(u32 token) ...@@ -219,7 +213,6 @@ void kvm_async_pf_task_wake(u32 token)
} }
n->token = token; n->token = token;
n->cpu = smp_processor_id(); n->cpu = smp_processor_id();
n->mm = NULL;
init_waitqueue_head(&n->wq); init_waitqueue_head(&n->wq);
hlist_add_head(&n->link, &b->list); hlist_add_head(&n->link, &b->list);
} else } else
......
...@@ -6581,6 +6581,7 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, ...@@ -6581,6 +6581,7 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
kvm_inject_page_fault(vcpu, &fault); kvm_inject_page_fault(vcpu, &fault);
} }
vcpu->arch.apf.halted = false; vcpu->arch.apf.halted = false;
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
} }
bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
......
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