diff options
author | Paul Mackerras <paulus@samba.org> | 2015-03-27 23:21:06 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2015-04-21 09:21:32 -0400 |
commit | 5d5b99cd6818bdbea287d23ef055bba1a8a9e648 (patch) | |
tree | 1696dcf7ad7f1e566611093e18a387711c80aab7 /arch/powerpc/kvm/book3s_hv.c | |
parent | 25fedfca94cfbf2461314c6c34ef58e74a31b025 (diff) |
KVM: PPC: Book3S HV: Get rid of vcore nap_count and n_woken
We can tell when a secondary thread has finished running a guest by
the fact that it clears its kvm_hstate.kvm_vcpu pointer, so there
is no real need for the nap_count field in the kvmppc_vcore struct.
This changes kvmppc_wait_for_nap to poll the kvm_hstate.kvm_vcpu
pointers of the secondary threads rather than polling vc->nap_count.
Besides reducing the size of the kvmppc_vcore struct by 8 bytes,
this also means that we can tell which secondary threads have got
stuck and thus print a more informative error message.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv.c')
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index fb4f16628a51..7c1335dca4a5 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -1729,8 +1729,10 @@ static int kvmppc_grab_hwthread(int cpu) | |||
1729 | tpaca = &paca[cpu]; | 1729 | tpaca = &paca[cpu]; |
1730 | 1730 | ||
1731 | /* Ensure the thread won't go into the kernel if it wakes */ | 1731 | /* Ensure the thread won't go into the kernel if it wakes */ |
1732 | tpaca->kvm_hstate.hwthread_req = 1; | ||
1733 | tpaca->kvm_hstate.kvm_vcpu = NULL; | 1732 | tpaca->kvm_hstate.kvm_vcpu = NULL; |
1733 | tpaca->kvm_hstate.napping = 0; | ||
1734 | smp_wmb(); | ||
1735 | tpaca->kvm_hstate.hwthread_req = 1; | ||
1734 | 1736 | ||
1735 | /* | 1737 | /* |
1736 | * If the thread is already executing in the kernel (e.g. handling | 1738 | * If the thread is already executing in the kernel (e.g. handling |
@@ -1773,35 +1775,43 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu) | |||
1773 | } | 1775 | } |
1774 | cpu = vc->pcpu + vcpu->arch.ptid; | 1776 | cpu = vc->pcpu + vcpu->arch.ptid; |
1775 | tpaca = &paca[cpu]; | 1777 | tpaca = &paca[cpu]; |
1776 | tpaca->kvm_hstate.kvm_vcpu = vcpu; | ||
1777 | tpaca->kvm_hstate.kvm_vcore = vc; | 1778 | tpaca->kvm_hstate.kvm_vcore = vc; |
1778 | tpaca->kvm_hstate.ptid = vcpu->arch.ptid; | 1779 | tpaca->kvm_hstate.ptid = vcpu->arch.ptid; |
1779 | vcpu->cpu = vc->pcpu; | 1780 | vcpu->cpu = vc->pcpu; |
1781 | /* Order stores to hstate.kvm_vcore etc. before store to kvm_vcpu */ | ||
1780 | smp_wmb(); | 1782 | smp_wmb(); |
1783 | tpaca->kvm_hstate.kvm_vcpu = vcpu; | ||
1781 | #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) | 1784 | #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) |
1782 | if (cpu != smp_processor_id()) { | 1785 | if (cpu != smp_processor_id()) |
1783 | xics_wake_cpu(cpu); | 1786 | xics_wake_cpu(cpu); |
1784 | if (vcpu->arch.ptid) | ||
1785 | ++vc->n_woken; | ||
1786 | } | ||
1787 | #endif | 1787 | #endif |
1788 | } | 1788 | } |
1789 | 1789 | ||
1790 | static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc) | 1790 | static void kvmppc_wait_for_nap(void) |
1791 | { | 1791 | { |
1792 | int i; | 1792 | int cpu = smp_processor_id(); |
1793 | int i, loops; | ||
1793 | 1794 | ||
1794 | HMT_low(); | 1795 | for (loops = 0; loops < 1000000; ++loops) { |
1795 | i = 0; | 1796 | /* |
1796 | while (vc->nap_count < vc->n_woken) { | 1797 | * Check if all threads are finished. |
1797 | if (++i >= 1000000) { | 1798 | * We set the vcpu pointer when starting a thread |
1798 | pr_err("kvmppc_wait_for_nap timeout %d %d\n", | 1799 | * and the thread clears it when finished, so we look |
1799 | vc->nap_count, vc->n_woken); | 1800 | * for any threads that still have a non-NULL vcpu ptr. |
1800 | break; | 1801 | */ |
1802 | for (i = 1; i < threads_per_subcore; ++i) | ||
1803 | if (paca[cpu + i].kvm_hstate.kvm_vcpu) | ||
1804 | break; | ||
1805 | if (i == threads_per_subcore) { | ||
1806 | HMT_medium(); | ||
1807 | return; | ||
1801 | } | 1808 | } |
1802 | cpu_relax(); | 1809 | HMT_low(); |
1803 | } | 1810 | } |
1804 | HMT_medium(); | 1811 | HMT_medium(); |
1812 | for (i = 1; i < threads_per_subcore; ++i) | ||
1813 | if (paca[cpu + i].kvm_hstate.kvm_vcpu) | ||
1814 | pr_err("KVM: CPU %d seems to be stuck\n", cpu + i); | ||
1805 | } | 1815 | } |
1806 | 1816 | ||
1807 | /* | 1817 | /* |
@@ -1942,8 +1952,6 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) | |||
1942 | /* | 1952 | /* |
1943 | * Initialize *vc. | 1953 | * Initialize *vc. |
1944 | */ | 1954 | */ |
1945 | vc->n_woken = 0; | ||
1946 | vc->nap_count = 0; | ||
1947 | vc->entry_exit_count = 0; | 1955 | vc->entry_exit_count = 0; |
1948 | vc->preempt_tb = TB_NIL; | 1956 | vc->preempt_tb = TB_NIL; |
1949 | vc->in_guest = 0; | 1957 | vc->in_guest = 0; |
@@ -2002,8 +2010,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) | |||
2002 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) | 2010 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) |
2003 | vcpu->cpu = -1; | 2011 | vcpu->cpu = -1; |
2004 | /* wait for secondary threads to finish writing their state to memory */ | 2012 | /* wait for secondary threads to finish writing their state to memory */ |
2005 | if (vc->nap_count < vc->n_woken) | 2013 | kvmppc_wait_for_nap(); |
2006 | kvmppc_wait_for_nap(vc); | ||
2007 | for (i = 0; i < threads_per_subcore; ++i) | 2014 | for (i = 0; i < threads_per_subcore; ++i) |
2008 | kvmppc_release_hwthread(vc->pcpu + i); | 2015 | kvmppc_release_hwthread(vc->pcpu + i); |
2009 | /* prevent other vcpu threads from doing kvmppc_start_thread() now */ | 2016 | /* prevent other vcpu threads from doing kvmppc_start_thread() now */ |