mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
KVM: PPC: Book3S HV: Take out virtual core piggybacking code
This takes out the code that arranges to run two (or more) virtual cores on a single subcore when possible, that is, when both vcores are from the same VM, the VM is configured with one CPU thread per virtual core, and all the per-subcore registers have the same value in each vcore. Since the VTB (virtual timebase) is a per-subcore register, and will almost always differ between vcores, this code is disabled on POWER8 machines, meaning that it is only usable on POWER7 machines (which don't have VTB). Given the tiny number of POWER7 machines which have firmware that allows them to run HV KVM, the benefit of simplifying the code outweighs the loss of this feature on POWER7 machines. Tested-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
88b02cf97b
commit
b009031f74
@ -2103,66 +2103,6 @@ static void init_master_vcore(struct kvmppc_vcore *vc)
|
|||||||
vc->conferring_threads = 0;
|
vc->conferring_threads = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* See if the existing subcores can be split into 3 (or fewer) subcores
|
|
||||||
* of at most two threads each, so we can fit in another vcore. This
|
|
||||||
* assumes there are at most two subcores and at most 6 threads in total.
|
|
||||||
*/
|
|
||||||
static bool can_split_piggybacked_subcores(struct core_info *cip)
|
|
||||||
{
|
|
||||||
int sub, new_sub;
|
|
||||||
int large_sub = -1;
|
|
||||||
int thr;
|
|
||||||
int n_subcores = cip->n_subcores;
|
|
||||||
struct kvmppc_vcore *vc, *vcnext;
|
|
||||||
struct kvmppc_vcore *master_vc = NULL;
|
|
||||||
|
|
||||||
for (sub = 0; sub < cip->n_subcores; ++sub) {
|
|
||||||
if (cip->subcore_threads[sub] <= 2)
|
|
||||||
continue;
|
|
||||||
if (large_sub >= 0)
|
|
||||||
return false;
|
|
||||||
large_sub = sub;
|
|
||||||
vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
|
|
||||||
preempt_list);
|
|
||||||
if (vc->num_threads > 2)
|
|
||||||
return false;
|
|
||||||
n_subcores += (cip->subcore_threads[sub] - 1) >> 1;
|
|
||||||
}
|
|
||||||
if (large_sub < 0 || !subcore_config_ok(n_subcores + 1, 2))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Seems feasible, so go through and move vcores to new subcores.
|
|
||||||
* Note that when we have two or more vcores in one subcore,
|
|
||||||
* all those vcores must have only one thread each.
|
|
||||||
*/
|
|
||||||
new_sub = cip->n_subcores;
|
|
||||||
thr = 0;
|
|
||||||
sub = large_sub;
|
|
||||||
list_for_each_entry_safe(vc, vcnext, &cip->vcs[sub], preempt_list) {
|
|
||||||
if (thr >= 2) {
|
|
||||||
list_del(&vc->preempt_list);
|
|
||||||
list_add_tail(&vc->preempt_list, &cip->vcs[new_sub]);
|
|
||||||
/* vc->num_threads must be 1 */
|
|
||||||
if (++cip->subcore_threads[new_sub] == 1) {
|
|
||||||
cip->subcore_vm[new_sub] = vc->kvm;
|
|
||||||
init_master_vcore(vc);
|
|
||||||
master_vc = vc;
|
|
||||||
++cip->n_subcores;
|
|
||||||
} else {
|
|
||||||
vc->master_vcore = master_vc;
|
|
||||||
++new_sub;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thr += vc->num_threads;
|
|
||||||
}
|
|
||||||
cip->subcore_threads[large_sub] = 2;
|
|
||||||
cip->max_subcore_threads = 2;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
|
static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
|
||||||
{
|
{
|
||||||
int n_threads = vc->num_threads;
|
int n_threads = vc->num_threads;
|
||||||
@ -2173,23 +2113,9 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
|
|||||||
|
|
||||||
if (n_threads < cip->max_subcore_threads)
|
if (n_threads < cip->max_subcore_threads)
|
||||||
n_threads = cip->max_subcore_threads;
|
n_threads = cip->max_subcore_threads;
|
||||||
if (subcore_config_ok(cip->n_subcores + 1, n_threads)) {
|
if (!subcore_config_ok(cip->n_subcores + 1, n_threads))
|
||||||
cip->max_subcore_threads = n_threads;
|
|
||||||
} else if (cip->n_subcores <= 2 && cip->total_threads <= 6 &&
|
|
||||||
vc->num_threads <= 2) {
|
|
||||||
/*
|
|
||||||
* We may be able to fit another subcore in by
|
|
||||||
* splitting an existing subcore with 3 or 4
|
|
||||||
* threads into two 2-thread subcores, or one
|
|
||||||
* with 5 or 6 threads into three subcores.
|
|
||||||
* We can only do this if those subcores have
|
|
||||||
* piggybacked virtual cores.
|
|
||||||
*/
|
|
||||||
if (!can_split_piggybacked_subcores(cip))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
cip->max_subcore_threads = n_threads;
|
||||||
|
|
||||||
sub = cip->n_subcores;
|
sub = cip->n_subcores;
|
||||||
++cip->n_subcores;
|
++cip->n_subcores;
|
||||||
@ -2203,45 +2129,6 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool can_piggyback_subcore(struct kvmppc_vcore *pvc,
|
|
||||||
struct core_info *cip, int sub)
|
|
||||||
{
|
|
||||||
struct kvmppc_vcore *vc;
|
|
||||||
int n_thr;
|
|
||||||
|
|
||||||
vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
|
|
||||||
preempt_list);
|
|
||||||
|
|
||||||
/* require same VM and same per-core reg values */
|
|
||||||
if (pvc->kvm != vc->kvm ||
|
|
||||||
pvc->tb_offset != vc->tb_offset ||
|
|
||||||
pvc->pcr != vc->pcr ||
|
|
||||||
pvc->lpcr != vc->lpcr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* P8 guests can't do piggybacking, because then the
|
|
||||||
* VTB would be shared between the vcpus.
|
|
||||||
*/
|
|
||||||
if (cpu_has_feature(CPU_FTR_ARCH_207S))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
n_thr = cip->subcore_threads[sub] + pvc->num_threads;
|
|
||||||
if (n_thr > cip->max_subcore_threads) {
|
|
||||||
if (!subcore_config_ok(cip->n_subcores, n_thr))
|
|
||||||
return false;
|
|
||||||
cip->max_subcore_threads = n_thr;
|
|
||||||
}
|
|
||||||
|
|
||||||
cip->total_threads += pvc->num_threads;
|
|
||||||
cip->subcore_threads[sub] = n_thr;
|
|
||||||
pvc->master_vcore = vc;
|
|
||||||
list_del(&pvc->preempt_list);
|
|
||||||
list_add_tail(&pvc->preempt_list, &cip->vcs[sub]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Work out whether it is possible to piggyback the execution of
|
* Work out whether it is possible to piggyback the execution of
|
||||||
* vcore *pvc onto the execution of the other vcores described in *cip.
|
* vcore *pvc onto the execution of the other vcores described in *cip.
|
||||||
@ -2249,19 +2136,10 @@ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc,
|
|||||||
static bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip,
|
static bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip,
|
||||||
int target_threads)
|
int target_threads)
|
||||||
{
|
{
|
||||||
int sub;
|
|
||||||
|
|
||||||
if (cip->total_threads + pvc->num_threads > target_threads)
|
if (cip->total_threads + pvc->num_threads > target_threads)
|
||||||
return false;
|
return false;
|
||||||
for (sub = 0; sub < cip->n_subcores; ++sub)
|
|
||||||
if (cip->subcore_threads[sub] &&
|
|
||||||
can_piggyback_subcore(pvc, cip, sub))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (can_dynamic_split(pvc, cip))
|
return can_dynamic_split(pvc, cip);
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_threads(struct kvmppc_vcore *vc)
|
static void prepare_threads(struct kvmppc_vcore *vc)
|
||||||
|
Loading…
Reference in New Issue
Block a user