Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 898b25b2 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

KVM: PPC: Book3S HV: Simplify dynamic micro-threading code



Since commit b009031f ("KVM: PPC: Book3S HV: Take out virtual
core piggybacking code", 2016-09-15), we only have at most one
vcore per subcore.  Previously, the fact that there might be more
than one vcore per subcore meant that we had the notion of a
"master vcore", which was the vcore that controlled thread 0 of
the subcore.  We also needed a list per subcore in the core_info
struct to record which vcores belonged to each subcore.  Now that
there can only be one vcore in the subcore, we can replace the
list with a simple pointer and get rid of the notion of the
master vcore (and in fact treat every vcore as a master vcore).

We can also get rid of the subcore_vm[] field in the core_info
struct since it is never read.

Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 2ed4f9dd
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -86,7 +86,6 @@ struct kvmppc_vcore {
	u16 last_cpu;
	u16 last_cpu;
	u8 vcore_state;
	u8 vcore_state;
	u8 in_guest;
	u8 in_guest;
	struct kvmppc_vcore *master_vcore;
	struct kvm_vcpu *runnable_threads[MAX_SMT_THREADS];
	struct kvm_vcpu *runnable_threads[MAX_SMT_THREADS];
	struct list_head preempt_list;
	struct list_head preempt_list;
	spinlock_t lock;
	spinlock_t lock;
+1 −1
Original line number Original line Diff line number Diff line
@@ -81,7 +81,7 @@ struct kvm_split_mode {
	u8		subcore_size;
	u8		subcore_size;
	u8		do_nap;
	u8		do_nap;
	u8		napped[MAX_SMT_THREADS];
	u8		napped[MAX_SMT_THREADS];
	struct kvmppc_vcore *master_vcs[MAX_SUBCORES];
	struct kvmppc_vcore *vc[MAX_SUBCORES];
};
};


/*
/*
+37 −51
Original line number Original line Diff line number Diff line
@@ -2171,7 +2171,6 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
{
{
	int cpu;
	int cpu;
	struct paca_struct *tpaca;
	struct paca_struct *tpaca;
	struct kvmppc_vcore *mvc = vc->master_vcore;
	struct kvm *kvm = vc->kvm;
	struct kvm *kvm = vc->kvm;


	cpu = vc->pcpu;
	cpu = vc->pcpu;
@@ -2181,7 +2180,7 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
			vcpu->arch.timer_running = 0;
			vcpu->arch.timer_running = 0;
		}
		}
		cpu += vcpu->arch.ptid;
		cpu += vcpu->arch.ptid;
		vcpu->cpu = mvc->pcpu;
		vcpu->cpu = vc->pcpu;
		vcpu->arch.thread_cpu = cpu;
		vcpu->arch.thread_cpu = cpu;


		/*
		/*
@@ -2207,10 +2206,10 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
	}
	}
	tpaca = &paca[cpu];
	tpaca = &paca[cpu];
	tpaca->kvm_hstate.kvm_vcpu = vcpu;
	tpaca->kvm_hstate.kvm_vcpu = vcpu;
	tpaca->kvm_hstate.ptid = cpu - mvc->pcpu;
	tpaca->kvm_hstate.ptid = cpu - vc->pcpu;
	/* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
	/* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
	smp_wmb();
	smp_wmb();
	tpaca->kvm_hstate.kvm_vcore = mvc;
	tpaca->kvm_hstate.kvm_vcore = vc;
	if (cpu != smp_processor_id())
	if (cpu != smp_processor_id())
		kvmppc_ipi_thread(cpu);
		kvmppc_ipi_thread(cpu);
}
}
@@ -2339,8 +2338,7 @@ struct core_info {
	int		max_subcore_threads;
	int		max_subcore_threads;
	int		total_threads;
	int		total_threads;
	int		subcore_threads[MAX_SUBCORES];
	int		subcore_threads[MAX_SUBCORES];
	struct kvm	*subcore_vm[MAX_SUBCORES];
	struct kvmppc_vcore *vc[MAX_SUBCORES];
	struct list_head vcs[MAX_SUBCORES];
};
};


/*
/*
@@ -2351,17 +2349,12 @@ static int subcore_thread_map[MAX_SUBCORES] = { 0, 4, 2, 6 };


static void init_core_info(struct core_info *cip, struct kvmppc_vcore *vc)
static void init_core_info(struct core_info *cip, struct kvmppc_vcore *vc)
{
{
	int sub;

	memset(cip, 0, sizeof(*cip));
	memset(cip, 0, sizeof(*cip));
	cip->n_subcores = 1;
	cip->n_subcores = 1;
	cip->max_subcore_threads = vc->num_threads;
	cip->max_subcore_threads = vc->num_threads;
	cip->total_threads = vc->num_threads;
	cip->total_threads = vc->num_threads;
	cip->subcore_threads[0] = vc->num_threads;
	cip->subcore_threads[0] = vc->num_threads;
	cip->subcore_vm[0] = vc->kvm;
	cip->vc[0] = vc;
	for (sub = 0; sub < MAX_SUBCORES; ++sub)
		INIT_LIST_HEAD(&cip->vcs[sub]);
	list_add_tail(&vc->preempt_list, &cip->vcs[0]);
}
}


static bool subcore_config_ok(int n_subcores, int n_threads)
static bool subcore_config_ok(int n_subcores, int n_threads)
@@ -2381,9 +2374,8 @@ static bool subcore_config_ok(int n_subcores, int n_threads)
	return n_subcores * roundup_pow_of_two(n_threads) <= MAX_SMT_THREADS;
	return n_subcores * roundup_pow_of_two(n_threads) <= MAX_SMT_THREADS;
}
}


static void init_master_vcore(struct kvmppc_vcore *vc)
static void init_vcore_to_run(struct kvmppc_vcore *vc)
{
{
	vc->master_vcore = vc;
	vc->entry_exit_map = 0;
	vc->entry_exit_map = 0;
	vc->in_guest = 0;
	vc->in_guest = 0;
	vc->napping_threads = 0;
	vc->napping_threads = 0;
@@ -2408,9 +2400,9 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
	++cip->n_subcores;
	++cip->n_subcores;
	cip->total_threads += vc->num_threads;
	cip->total_threads += vc->num_threads;
	cip->subcore_threads[sub] = vc->num_threads;
	cip->subcore_threads[sub] = vc->num_threads;
	cip->subcore_vm[sub] = vc->kvm;
	cip->vc[sub] = vc;
	init_master_vcore(vc);
	init_vcore_to_run(vc);
	list_move_tail(&vc->preempt_list, &cip->vcs[sub]);
	list_del_init(&vc->preempt_list);


	return true;
	return true;
}
}
@@ -2515,7 +2507,6 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master)
			wake_up(&vcpu->arch.cpu_run);
			wake_up(&vcpu->arch.cpu_run);
		}
		}
	}
	}
	list_del_init(&vc->preempt_list);
	if (!is_master) {
	if (!is_master) {
		if (still_running > 0) {
		if (still_running > 0) {
			kvmppc_vcore_preempt(vc);
			kvmppc_vcore_preempt(vc);
@@ -2587,7 +2578,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
	int i;
	int i;
	int srcu_idx;
	int srcu_idx;
	struct core_info core_info;
	struct core_info core_info;
	struct kvmppc_vcore *pvc, *vcnext;
	struct kvmppc_vcore *pvc;
	struct kvm_split_mode split_info, *sip;
	struct kvm_split_mode split_info, *sip;
	int split, subcore_size, active;
	int split, subcore_size, active;
	int sub;
	int sub;
@@ -2610,7 +2601,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
	/*
	/*
	 * Initialize *vc.
	 * Initialize *vc.
	 */
	 */
	init_master_vcore(vc);
	init_vcore_to_run(vc);
	vc->preempt_tb = TB_NIL;
	vc->preempt_tb = TB_NIL;


	/*
	/*
@@ -2670,9 +2661,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
		split_info.ldbar = mfspr(SPRN_LDBAR);
		split_info.ldbar = mfspr(SPRN_LDBAR);
		split_info.subcore_size = subcore_size;
		split_info.subcore_size = subcore_size;
		for (sub = 0; sub < core_info.n_subcores; ++sub)
		for (sub = 0; sub < core_info.n_subcores; ++sub)
			split_info.master_vcs[sub] =
			split_info.vc[sub] = core_info.vc[sub];
				list_first_entry(&core_info.vcs[sub],
					struct kvmppc_vcore, preempt_list);
		/* order writes to split_info before kvm_split_mode pointer */
		/* order writes to split_info before kvm_split_mode pointer */
		smp_wmb();
		smp_wmb();
	}
	}
@@ -2704,7 +2693,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
		thr = subcore_thread_map[sub];
		thr = subcore_thread_map[sub];
		thr0_done = false;
		thr0_done = false;
		active |= 1 << thr;
		active |= 1 << thr;
		list_for_each_entry(pvc, &core_info.vcs[sub], preempt_list) {
		pvc = core_info.vc[sub];
		pvc->pcpu = pcpu + thr;
		pvc->pcpu = pcpu + thr;
		for_each_runnable_thread(i, vcpu, pvc) {
		for_each_runnable_thread(i, vcpu, pvc) {
			kvmppc_start_thread(vcpu, pvc);
			kvmppc_start_thread(vcpu, pvc);
@@ -2718,11 +2707,10 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
		 * We need to start the first thread of each subcore
		 * We need to start the first thread of each subcore
		 * even if it doesn't have a vcpu.
		 * even if it doesn't have a vcpu.
		 */
		 */
			if (pvc->master_vcore == pvc && !thr0_done)
		if (!thr0_done)
			kvmppc_start_thread(NULL, pvc);
			kvmppc_start_thread(NULL, pvc);
		thr += pvc->num_threads;
		thr += pvc->num_threads;
	}
	}
	}


	/*
	/*
	 * Ensure that split_info.do_nap is set after setting
	 * Ensure that split_info.do_nap is set after setting
@@ -2748,8 +2736,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
	trace_kvmppc_run_core(vc, 0);
	trace_kvmppc_run_core(vc, 0);


	for (sub = 0; sub < core_info.n_subcores; ++sub)
	for (sub = 0; sub < core_info.n_subcores; ++sub)
		list_for_each_entry(pvc, &core_info.vcs[sub], preempt_list)
		spin_unlock(&core_info.vc[sub]->lock);
			spin_unlock(&pvc->lock);


	guest_enter();
	guest_enter();


@@ -2802,10 +2789,10 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
	smp_mb();
	smp_mb();
	guest_exit();
	guest_exit();


	for (sub = 0; sub < core_info.n_subcores; ++sub)
	for (sub = 0; sub < core_info.n_subcores; ++sub) {
		list_for_each_entry_safe(pvc, vcnext, &core_info.vcs[sub],
		pvc = core_info.vc[sub];
					 preempt_list)
		post_guest_process(pvc, pvc == vc);
		post_guest_process(pvc, pvc == vc);
	}


	spin_lock(&vc->lock);
	spin_lock(&vc->lock);
	preempt_enable();
	preempt_enable();
@@ -3026,15 +3013,14 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
	 */
	 */
	if (!signal_pending(current)) {
	if (!signal_pending(current)) {
		if (vc->vcore_state == VCORE_PIGGYBACK) {
		if (vc->vcore_state == VCORE_PIGGYBACK) {
			struct kvmppc_vcore *mvc = vc->master_vcore;
			if (spin_trylock(&vc->lock)) {
			if (spin_trylock(&mvc->lock)) {
				if (vc->vcore_state == VCORE_RUNNING &&
				if (mvc->vcore_state == VCORE_RUNNING &&
				    !VCORE_IS_EXITING(vc)) {
				    !VCORE_IS_EXITING(mvc)) {
					kvmppc_create_dtl_entry(vcpu, vc);
					kvmppc_create_dtl_entry(vcpu, vc);
					kvmppc_start_thread(vcpu, vc);
					kvmppc_start_thread(vcpu, vc);
					trace_kvm_guest_enter(vcpu);
					trace_kvm_guest_enter(vcpu);
				}
				}
				spin_unlock(&mvc->lock);
				spin_unlock(&vc->lock);
			}
			}
		} else if (vc->vcore_state == VCORE_RUNNING &&
		} else if (vc->vcore_state == VCORE_RUNNING &&
			   !VCORE_IS_EXITING(vc)) {
			   !VCORE_IS_EXITING(vc)) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -307,7 +307,7 @@ void kvmhv_commence_exit(int trap)
		return;
		return;


	for (i = 0; i < MAX_SUBCORES; ++i) {
	for (i = 0; i < MAX_SUBCORES; ++i) {
		vc = sip->master_vcs[i];
		vc = sip->vc[i];
		if (!vc)
		if (!vc)
			break;
			break;
		do {
		do {