[RFC PATCH v2 07/10] KVM: PPC: Ultravisor: Restrict LDBAR access
Claudio Carvalho
cclaudio at linux.ibm.com
Sun May 19 00:25:21 AEST 2019
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.
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
--
2.20.1
More information about the Linuxppc-dev
mailing list