aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-02-02 19:54:17 -0500
committerAvi Kivity <avi@redhat.com>2012-04-08 07:01:20 -0400
commitf0888f70151c7f53de2b45ee20ff1905837943e8 (patch)
tree80b7e133e681a2b4e4255a8fa747711da4c59211 /arch/powerpc/kvm/book3s_hv.c
parentf6127716c346c73ab1513edee53231800188c5ba (diff)
KVM: PPC: Book3S HV: Make secondary threads more robust against stray IPIs
Currently on POWER7, if we are running the guest on a core and we don't need all the hardware threads, we do nothing to ensure that the unused threads aren't executing in the kernel (other than checking that they are offline). We just assume they're napping and we don't do anything to stop them trying to enter the kernel while the guest is running. This means that a stray IPI can wake up the hardware thread and it will then try to enter the kernel, but since the core is in guest context, it will execute code from the guest in hypervisor mode once it turns the MMU on, which tends to lead to crashes or hangs in the host. This fixes the problem by adding two new one-byte flags in the kvmppc_host_state structure in the PACA which are used to interlock between the primary thread and the unused secondary threads when entering the guest. With these flags, the primary thread can ensure that the unused secondaries are not already in kernel mode (i.e. handling a stray IPI) and then indicate that they should not try to enter the kernel if they do get woken for any reason. Instead they will go into KVM code, find that there is no vcpu to run, acknowledge and clear the IPI and go back to nap mode. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv.c')
-rw-r--r--arch/powerpc/kvm/book3s_hv.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 01294a5099dd..e87f6196d222 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -569,6 +569,45 @@ static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
569 list_del(&vcpu->arch.run_list); 569 list_del(&vcpu->arch.run_list);
570} 570}
571 571
572static int kvmppc_grab_hwthread(int cpu)
573{
574 struct paca_struct *tpaca;
575 long timeout = 1000;
576
577 tpaca = &paca[cpu];
578
579 /* Ensure the thread won't go into the kernel if it wakes */
580 tpaca->kvm_hstate.hwthread_req = 1;
581
582 /*
583 * If the thread is already executing in the kernel (e.g. handling
584 * a stray interrupt), wait for it to get back to nap mode.
585 * The smp_mb() is to ensure that our setting of hwthread_req
586 * is visible before we look at hwthread_state, so if this
587 * races with the code at system_reset_pSeries and the thread
588 * misses our setting of hwthread_req, we are sure to see its
589 * setting of hwthread_state, and vice versa.
590 */
591 smp_mb();
592 while (tpaca->kvm_hstate.hwthread_state == KVM_HWTHREAD_IN_KERNEL) {
593 if (--timeout <= 0) {
594 pr_err("KVM: couldn't grab cpu %d\n", cpu);
595 return -EBUSY;
596 }
597 udelay(1);
598 }
599 return 0;
600}
601
602static void kvmppc_release_hwthread(int cpu)
603{
604 struct paca_struct *tpaca;
605
606 tpaca = &paca[cpu];
607 tpaca->kvm_hstate.hwthread_req = 0;
608 tpaca->kvm_hstate.kvm_vcpu = NULL;
609}
610
572static void kvmppc_start_thread(struct kvm_vcpu *vcpu) 611static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
573{ 612{
574 int cpu; 613 int cpu;
@@ -588,8 +627,7 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
588 smp_wmb(); 627 smp_wmb();
589#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) 628#if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
590 if (vcpu->arch.ptid) { 629 if (vcpu->arch.ptid) {
591 tpaca->cpu_start = 0x80; 630 kvmppc_grab_hwthread(cpu);
592 wmb();
593 xics_wake_cpu(cpu); 631 xics_wake_cpu(cpu);
594 ++vc->n_woken; 632 ++vc->n_woken;
595 } 633 }
@@ -639,7 +677,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
639 struct kvm_vcpu *vcpu, *vcpu0, *vnext; 677 struct kvm_vcpu *vcpu, *vcpu0, *vnext;
640 long ret; 678 long ret;
641 u64 now; 679 u64 now;
642 int ptid; 680 int ptid, i;
643 681
644 /* don't start if any threads have a signal pending */ 682 /* don't start if any threads have a signal pending */
645 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) 683 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
@@ -686,12 +724,17 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
686 vc->napping_threads = 0; 724 vc->napping_threads = 0;
687 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) 725 list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
688 kvmppc_start_thread(vcpu); 726 kvmppc_start_thread(vcpu);
727 /* Grab any remaining hw threads so they can't go into the kernel */
728 for (i = ptid; i < threads_per_core; ++i)
729 kvmppc_grab_hwthread(vc->pcpu + i);
689 730
690 preempt_disable(); 731 preempt_disable();
691 spin_unlock(&vc->lock); 732 spin_unlock(&vc->lock);
692 733
693 kvm_guest_enter(); 734 kvm_guest_enter();
694 __kvmppc_vcore_entry(NULL, vcpu0); 735 __kvmppc_vcore_entry(NULL, vcpu0);
736 for (i = 0; i < threads_per_core; ++i)
737 kvmppc_release_hwthread(vc->pcpu + i);
695 738
696 spin_lock(&vc->lock); 739 spin_lock(&vc->lock);
697 /* disable sending of IPIs on virtual external irqs */ 740 /* disable sending of IPIs on virtual external irqs */