[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