[RFC PATCH v2 07/10] KVM: PPC: Ultravisor: Restrict LDBAR access

Madhavan Srinivasan maddy at linux.vnet.ibm.com
Tue May 21 15:24:34 AEST 2019


On 18/05/19 7:55 PM, Claudio Carvalho wrote:
> From: Ram Pai <linuxram at us.ibm.com> When the ultravisor firmware is 
> available, it takes control over the LDBAR register. In this case, 
> thread-imc updates and save/restore operations on the LDBAR register 
> are handled by ultravisor.
we should remove the core and thread imc nodes in the skiboot
if the ultravisor is enabled. We dont need imc-pmu.c file changes, imc-pmu.c
inits only if we have the corresponding nodes. I will post a skiboot patch.

Maddy

> Signed-off-by: Ram Pai <linuxram at us.ibm.com>
> [Restrict LDBAR access in assembly code and some in C, update the commit
>   message]
> Signed-off-by: Claudio Carvalho <cclaudio at linux.ibm.com>
> ---
>   arch/powerpc/kvm/book3s_hv.c                 |  4 +-
>   arch/powerpc/kvm/book3s_hv_rmhandlers.S      |  2 +
>   arch/powerpc/perf/imc-pmu.c                  | 64 ++++++++++++--------
>   arch/powerpc/platforms/powernv/idle.c        |  6 +-
>   arch/powerpc/platforms/powernv/subcore-asm.S |  4 ++
>   5 files changed, 52 insertions(+), 28 deletions(-)
>
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index 0fab0a201027..81f35f955d16 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -75,6 +75,7 @@
>   #include <asm/xics.h>
>   #include <asm/xive.h>
>   #include <asm/hw_breakpoint.h>
> +#include <asm/firmware.h>
>
>   #include "book3s.h"
>
> @@ -3117,7 +3118,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>   			subcore_size = MAX_SMT_THREADS / split;
>   			split_info.rpr = mfspr(SPRN_RPR);
>   			split_info.pmmar = mfspr(SPRN_PMMAR);
> -			split_info.ldbar = mfspr(SPRN_LDBAR);
> +			if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
> +				split_info.ldbar = mfspr(SPRN_LDBAR);
>   			split_info.subcore_size = subcore_size;
>   		} else {
>   			split_info.subcore_size = 1;
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index dd014308f065..938cfa5dceed 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -375,8 +375,10 @@ BEGIN_FTR_SECTION
>   	mtspr	SPRN_RPR, r0
>   	ld	r0, KVM_SPLIT_PMMAR(r6)
>   	mtspr	SPRN_PMMAR, r0
> +BEGIN_FW_FTR_SECTION_NESTED(70)
>   	ld	r0, KVM_SPLIT_LDBAR(r6)
>   	mtspr	SPRN_LDBAR, r0
> +END_FW_FTR_SECTION_NESTED(FW_FEATURE_ULTRAVISOR, 0, 70)
>   	isync
>   FTR_SECTION_ELSE
>   	/* On P9 we use the split_info for coordinating LPCR changes */
> diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
> index 31fa753e2eb2..39c84de74da9 100644
> --- a/arch/powerpc/perf/imc-pmu.c
> +++ b/arch/powerpc/perf/imc-pmu.c
> @@ -17,6 +17,7 @@
>   #include <asm/cputhreads.h>
>   #include <asm/smp.h>
>   #include <linux/string.h>
> +#include <asm/firmware.h>
>
>   /* Nest IMC data structures and variables */
>
> @@ -816,6 +817,17 @@ static int core_imc_event_init(struct perf_event *event)
>   	return 0;
>   }
>
> +static void thread_imc_ldbar_disable(void *dummy)
> +{
> +	/*
> +	 * By Zeroing LDBAR, we disable thread-imc updates. When the ultravisor
> +	 * firmware is available, it is responsible for handling thread-imc
> +	 * updates, though
> +	 */
> +	if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
> +		mtspr(SPRN_LDBAR, 0);
> +}
> +
>   /*
>    * Allocates a page of memory for each of the online cpus, and load
>    * LDBAR with 0.
> @@ -856,7 +868,7 @@ static int thread_imc_mem_alloc(int cpu_id, int size)
>   		per_cpu(thread_imc_mem, cpu_id) = local_mem;
>   	}
>
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>   	return 0;
>   }
>
> @@ -867,7 +879,7 @@ static int ppc_thread_imc_cpu_online(unsigned int cpu)
>
>   static int ppc_thread_imc_cpu_offline(unsigned int cpu)
>   {
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>   	return 0;
>   }
>
> @@ -1010,7 +1022,6 @@ static int thread_imc_event_add(struct perf_event *event, int flags)
>   {
>   	int core_id;
>   	struct imc_pmu_ref *ref;
> -	u64 ldbar_value, *local_mem = per_cpu(thread_imc_mem, smp_processor_id());
>
>   	if (flags & PERF_EF_START)
>   		imc_event_start(event, flags);
> @@ -1019,8 +1030,14 @@ static int thread_imc_event_add(struct perf_event *event, int flags)
>   		return -EINVAL;
>
>   	core_id = smp_processor_id() / threads_per_core;
> -	ldbar_value = ((u64)local_mem & THREAD_IMC_LDBAR_MASK) | THREAD_IMC_ENABLE;
> -	mtspr(SPRN_LDBAR, ldbar_value);
> +	if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR)) {
> +		u64 ldbar_value, *local_mem;
> +
> +		local_mem = per_cpu(thread_imc_mem, smp_processor_id());
> +		ldbar_value = ((u64)local_mem & THREAD_IMC_LDBAR_MASK) |
> +				THREAD_IMC_ENABLE;
> +		mtspr(SPRN_LDBAR, ldbar_value);
> +	}
>
>   	/*
>   	 * imc pmus are enabled only when it is used.
> @@ -1053,7 +1070,7 @@ static void thread_imc_event_del(struct perf_event *event, int flags)
>   	int core_id;
>   	struct imc_pmu_ref *ref;
>
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>
>   	core_id = smp_processor_id() / threads_per_core;
>   	ref = &core_imc_refc[core_id];
> @@ -1109,7 +1126,7 @@ static int trace_imc_mem_alloc(int cpu_id, int size)
>   	trace_imc_refc[core_id].id = core_id;
>   	mutex_init(&trace_imc_refc[core_id].lock);
>
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>   	return 0;
>   }
>
> @@ -1120,7 +1137,7 @@ static int ppc_trace_imc_cpu_online(unsigned int cpu)
>
>   static int ppc_trace_imc_cpu_offline(unsigned int cpu)
>   {
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>   	return 0;
>   }
>
> @@ -1207,11 +1224,6 @@ static int trace_imc_event_add(struct perf_event *event, int flags)
>   {
>   	int core_id = smp_processor_id() / threads_per_core;
>   	struct imc_pmu_ref *ref = NULL;
> -	u64 local_mem, ldbar_value;
> -
> -	/* Set trace-imc bit in ldbar and load ldbar with per-thread memory address */
> -	local_mem = get_trace_imc_event_base_addr();
> -	ldbar_value = ((u64)local_mem & THREAD_IMC_LDBAR_MASK) | TRACE_IMC_ENABLE;
>
>   	if (core_imc_refc)
>   		ref = &core_imc_refc[core_id];
> @@ -1222,14 +1234,25 @@ static int trace_imc_event_add(struct perf_event *event, int flags)
>   		if (!ref)
>   			return -EINVAL;
>   	}
> -	mtspr(SPRN_LDBAR, ldbar_value);
> +	if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR)) {
> +		u64 local_mem, ldbar_value;
> +
> +		/*
> +		 * Set trace-imc bit in ldbar and load ldbar with per-thread
> +		 * memory address
> +		 */
> +		local_mem = get_trace_imc_event_base_addr();
> +		ldbar_value = ((u64)local_mem & THREAD_IMC_LDBAR_MASK) |
> +				TRACE_IMC_ENABLE;
> +		mtspr(SPRN_LDBAR, ldbar_value);
> +	}
>   	mutex_lock(&ref->lock);
>   	if (ref->refc == 0) {
>   		if (opal_imc_counters_start(OPAL_IMC_COUNTERS_TRACE,
>   				get_hard_smp_processor_id(smp_processor_id()))) {
>   			mutex_unlock(&ref->lock);
>   			pr_err("trace-imc: Unable to start the counters for core %d\n", core_id);
> -			mtspr(SPRN_LDBAR, 0);
> +			thread_imc_ldbar_disable(NULL);
>   			return -EINVAL;
>   		}
>   	}
> @@ -1270,7 +1293,7 @@ static void trace_imc_event_del(struct perf_event *event, int flags)
>   		if (!ref)
>   			return;
>   	}
> -	mtspr(SPRN_LDBAR, 0);
> +	thread_imc_ldbar_disable(NULL);
>   	mutex_lock(&ref->lock);
>   	ref->refc--;
>   	if (ref->refc == 0) {
> @@ -1413,15 +1436,6 @@ static void cleanup_all_core_imc_memory(void)
>   	kfree(core_imc_refc);
>   }
>
> -static void thread_imc_ldbar_disable(void *dummy)
> -{
> -	/*
> -	 * By Zeroing LDBAR, we disable thread-imc
> -	 * updates.
> -	 */
> -	mtspr(SPRN_LDBAR, 0);
> -}
> -
>   void thread_imc_disable(void)
>   {
>   	on_each_cpu(thread_imc_ldbar_disable, NULL, 1);
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index c9133f7908ca..fd62435e3267 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -679,7 +679,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
>   		sprs.ptcr	= mfspr(SPRN_PTCR);
>   		sprs.rpr	= mfspr(SPRN_RPR);
>   		sprs.tscr	= mfspr(SPRN_TSCR);
> -		sprs.ldbar	= mfspr(SPRN_LDBAR);
> +		if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
> +			sprs.ldbar	= mfspr(SPRN_LDBAR);
>
>   		sprs_saved = true;
>
> @@ -762,7 +763,8 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
>   	mtspr(SPRN_PTCR,	sprs.ptcr);
>   	mtspr(SPRN_RPR,		sprs.rpr);
>   	mtspr(SPRN_TSCR,	sprs.tscr);
> -	mtspr(SPRN_LDBAR,	sprs.ldbar);
> +	if (!firmware_has_feature(FW_FEATURE_ULTRAVISOR))
> +		mtspr(SPRN_LDBAR,	sprs.ldbar);
>
>   	if (pls >= pnv_first_tb_loss_level) {
>   		/* TB loss */
> diff --git a/arch/powerpc/platforms/powernv/subcore-asm.S b/arch/powerpc/platforms/powernv/subcore-asm.S
> index 39bb24aa8f34..e4383fa5e150 100644
> --- a/arch/powerpc/platforms/powernv/subcore-asm.S
> +++ b/arch/powerpc/platforms/powernv/subcore-asm.S
> @@ -44,7 +44,9 @@ _GLOBAL(split_core_secondary_loop)
>
>   real_mode:
>   	/* Grab values from unsplit SPRs */
> +BEGIN_FW_FTR_SECTION
>   	mfspr	r6,  SPRN_LDBAR
> +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ULTRAVISOR)
>   	mfspr	r7,  SPRN_PMMAR
>   	mfspr	r8,  SPRN_PMCR
>   	mfspr	r9,  SPRN_RPR
> @@ -77,7 +79,9 @@ real_mode:
>   	mtspr	SPRN_HDEC, r4
>
>   	/* Restore SPR values now we are split */
> +BEGIN_FW_FTR_SECTION
>   	mtspr	SPRN_LDBAR, r6
> +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ULTRAVISOR)
>   	mtspr	SPRN_PMMAR, r7
>   	mtspr	SPRN_PMCR, r8
>   	mtspr	SPRN_RPR, r9



More information about the Linuxppc-dev mailing list