Commit 3102f784 authored by Michael Ellerman's avatar Michael Ellerman Committed by Benjamin Herrenschmidt

powerpc/kvm/book3s_hv: Use threads_per_subcore in KVM

To support split core on POWER8 we need to modify various parts of the
KVM code to use threads_per_subcore instead of threads_per_core. On
systems that do not support split core threads_per_subcore ==
threads_per_core and these changes are a nop.

We use threads_per_subcore as the value reported by KVM_CAP_PPC_SMT.
This communicates to userspace that guests can only be created with
a value of threads_per_core that is less than or equal to the current
threads_per_subcore. This ensures that guests can only be created with a
thread configuration that we are able to run given the current split
core mode.

Although threads_per_subcore can change during the life of the system,
the commit that enables that will ensure that threads_per_subcore does
not change during the life of a KVM VM.
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarMichael Neuling <mikey@neuling.org>
Acked-by: default avatarAlexander Graf <agraf@suse.de>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 6f5e40a3
...@@ -1266,7 +1266,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, ...@@ -1266,7 +1266,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
int core; int core;
struct kvmppc_vcore *vcore; struct kvmppc_vcore *vcore;
core = id / threads_per_core; core = id / threads_per_subcore;
if (core >= KVM_MAX_VCORES) if (core >= KVM_MAX_VCORES)
goto out; goto out;
...@@ -1305,7 +1305,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, ...@@ -1305,7 +1305,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm,
init_waitqueue_head(&vcore->wq); init_waitqueue_head(&vcore->wq);
vcore->preempt_tb = TB_NIL; vcore->preempt_tb = TB_NIL;
vcore->lpcr = kvm->arch.lpcr; vcore->lpcr = kvm->arch.lpcr;
vcore->first_vcpuid = core * threads_per_core; vcore->first_vcpuid = core * threads_per_subcore;
vcore->kvm = kvm; vcore->kvm = kvm;
} }
kvm->arch.vcores[core] = vcore; kvm->arch.vcores[core] = vcore;
...@@ -1495,16 +1495,19 @@ static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc) ...@@ -1495,16 +1495,19 @@ static void kvmppc_wait_for_nap(struct kvmppc_vcore *vc)
static int on_primary_thread(void) static int on_primary_thread(void)
{ {
int cpu = smp_processor_id(); int cpu = smp_processor_id();
int thr = cpu_thread_in_core(cpu); int thr;
if (thr) /* Are we on a primary subcore? */
if (cpu_thread_in_subcore(cpu))
return 0; return 0;
while (++thr < threads_per_core)
thr = 0;
while (++thr < threads_per_subcore)
if (cpu_online(cpu + thr)) if (cpu_online(cpu + thr))
return 0; return 0;
/* Grab all hw threads so they can't go into the kernel */ /* Grab all hw threads so they can't go into the kernel */
for (thr = 1; thr < threads_per_core; ++thr) { for (thr = 1; thr < threads_per_subcore; ++thr) {
if (kvmppc_grab_hwthread(cpu + thr)) { if (kvmppc_grab_hwthread(cpu + thr)) {
/* Couldn't grab one; let the others go */ /* Couldn't grab one; let the others go */
do { do {
...@@ -1563,15 +1566,18 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1563,15 +1566,18 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
} }
/* /*
* Make sure we are running on thread 0, and that * Make sure we are running on primary threads, and that secondary
* secondary threads are offline. * threads are offline. Also check if the number of threads in this
* guest are greater than the current system threads per guest.
*/ */
if (threads_per_core > 1 && !on_primary_thread()) { if ((threads_per_core > 1) &&
((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
vcpu->arch.ret = -EBUSY; vcpu->arch.ret = -EBUSY;
goto out; goto out;
} }
vc->pcpu = smp_processor_id(); vc->pcpu = smp_processor_id();
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) { list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
kvmppc_start_thread(vcpu); kvmppc_start_thread(vcpu);
...@@ -1599,7 +1605,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) ...@@ -1599,7 +1605,7 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc)
/* wait for secondary threads to finish writing their state to memory */ /* wait for secondary threads to finish writing their state to memory */
if (vc->nap_count < vc->n_woken) if (vc->nap_count < vc->n_woken)
kvmppc_wait_for_nap(vc); kvmppc_wait_for_nap(vc);
for (i = 0; i < threads_per_core; ++i) for (i = 0; i < threads_per_subcore; ++i)
kvmppc_release_hwthread(vc->pcpu + i); kvmppc_release_hwthread(vc->pcpu + i);
/* prevent other vcpu threads from doing kvmppc_start_thread() now */ /* prevent other vcpu threads from doing kvmppc_start_thread() now */
vc->vcore_state = VCORE_EXITING; vc->vcore_state = VCORE_EXITING;
......
...@@ -384,7 +384,7 @@ int kvm_dev_ioctl_check_extension(long ext) ...@@ -384,7 +384,7 @@ int kvm_dev_ioctl_check_extension(long ext)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
case KVM_CAP_PPC_SMT: case KVM_CAP_PPC_SMT:
if (hv_enabled) if (hv_enabled)
r = threads_per_core; r = threads_per_subcore;
else else
r = 0; r = 0;
break; break;
......
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