|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 1/2] xen/arm: Track the minimum number of PMU counters across CPUs
On heterogeneous systems (e.g. a big.LITTLE system), the number of
PMU counters (PMCR_EL0.N) may differ between cores.
Any counter count reported to guests therefore needs to be valid
no matter which CPU their vCPUs run on.
Read PMCR_EL0.N once on the boot CPU and on each secondary CPU that
stays online, and keep the smallest value in 'system_pmu_num_cntrs'.
The update happens in update_system_features(), which is not called
for CPUs being parked. Secondary CPUs are brought up sequentially,
so no locking is needed.
To be able to do that in common code, move the PMCR_EL0.N field
definitions to asm/processor.h and provide the PMCR_EL0 -> PMCR
alias for arm32 builds.
Signed-off-by: Daisuke Nishimura <nishimura@xxxxxxxxxxxxx>
---
xen/arch/arm/arm64/cpufeature.c | 6 ++++++
xen/arch/arm/cpufeature.c | 21 +++++++++++++++++++++
xen/arch/arm/include/asm/cpregs.h | 1 +
xen/arch/arm/include/asm/cpufeature.h | 7 ++++++-
xen/arch/arm/include/asm/processor.h | 4 ++++
xen/arch/arm/setup.c | 1 +
6 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/xen/arch/arm/arm64/cpufeature.c
b/xen/arch/arm/arm64/cpufeature.c index 6fb8974ade..b32f924fc0 100644
--- a/xen/arch/arm/arm64/cpufeature.c
+++ b/xen/arch/arm/arm64/cpufeature.c
@@ -567,6 +567,12 @@ static void sanitize_reg(u64 *cur_reg, u64
new_reg, const char *reg_name, */
void update_system_features(const struct cpuinfo_arm *new)
{
+ /*
+ * Keep track of the smallest number of PMU counters across the
+ * CPUs that stay online (this function is not called for cores
+ * that are being parked).
+ */
+ update_system_pmu_num_cntrs();
#define SANITIZE_REG(field, num, reg) \
sanitize_reg(&system_cpuinfo.field.bits[num],
new->field.bits[num], \ diff --git a/xen/arch/arm/cpufeature.c
b/xen/arch/arm/cpufeature.c index 8d8cd19a96..6ce55a0f68 100644
--- a/xen/arch/arm/cpufeature.c
+++ b/xen/arch/arm/cpufeature.c
@@ -17,6 +17,27 @@ DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
struct cpuinfo_arm __read_mostly domain_cpuinfo;
+/* Minimum number of PMU counters across all online CPUs. */
+unsigned int __read_mostly system_pmu_num_cntrs = UINT_MAX;
+
+/*
+ * On heterogeneous systems the number of PMU counters may differ
+ * between cores. Keep the smallest value seen on CPUs that stay
+ * online, so that guests can be given a number of counters that is
+ * usable no matter which CPU their vCPUs run on.
+ *
+ * Called once on the boot CPU and once on every secondary CPU during
+ * bring-up; CPUs are started sequentially, so no locking is needed.
+ */
+void update_system_pmu_num_cntrs(void)
+{
+ unsigned int n = (unsigned int)(READ_SYSREG(PMCR_EL0) >>
+ PMCR_N_SHIFT) & PMCR_N_MASK;
+
+ if ( n < system_pmu_num_cntrs )
+ system_pmu_num_cntrs = n;
+}
+
#ifdef CONFIG_ARM_64
static bool has_sb_instruction(const struct arm_cpu_capabilities
*entry) {
diff --git a/xen/arch/arm/include/asm/cpregs.h
b/xen/arch/arm/include/asm/cpregs.h index 3f62b38dc0..fc0a7c6da3 100644
--- a/xen/arch/arm/include/asm/cpregs.h
+++ b/xen/arch/arm/include/asm/cpregs.h
@@ -480,6 +480,7 @@
#define MIDR_EL1 MIDR
#define MPIDR_EL1 MPIDR
#define PAR_EL1 PAR
+#define PMCR_EL0 PMCR
#define SCTLR_EL1 SCTLR
#define SCTLR_EL2 HSCTLR
#define TCR_EL1 TTBCR
diff --git a/xen/arch/arm/include/asm/cpufeature.h
b/xen/arch/arm/include/asm/cpufeature.h index c554686415..1ff31ab9b4
100644 --- a/xen/arch/arm/include/asm/cpufeature.h
+++ b/xen/arch/arm/include/asm/cpufeature.h
@@ -465,14 +465,19 @@ struct cpuinfo_arm {
extern struct cpuinfo_arm system_cpuinfo;
+/* Minimum number of PMU counters usable on all online CPUs. */
+extern unsigned int system_pmu_num_cntrs;
+
extern void identify_cpu(struct cpuinfo_arm *c);
+void update_system_pmu_num_cntrs(void);
+
#ifdef CONFIG_ARM_64
extern void update_system_features(const struct cpuinfo_arm *new);
#else
static inline void update_system_features(const struct cpuinfo_arm
*cpuinfo) {
- /* Not supported on arm32 */
+ update_system_pmu_num_cntrs();
}
#endif
diff --git a/xen/arch/arm/include/asm/processor.h
b/xen/arch/arm/include/asm/processor.h index 8ee8f88fb4..24ab182f84
100644 --- a/xen/arch/arm/include/asm/processor.h
+++ b/xen/arch/arm/include/asm/processor.h
@@ -446,6 +446,10 @@
#define HDCR_TPM (_AC(1,U)<<6) /* Trap Performance
Monitors accesses */ #define HDCR_TPMCR (_AC(1,U)<<5) /*
Trap PMCR accesses */
+/* PMCR_EL0/PMCR Number of event counters field, bits [15:11] */
+#define PMCR_N_SHIFT 11
+#define PMCR_N_MASK 0x1F
+
#define HSR_EC_SHIFT 26
#define HSR_EC_UNKNOWN 0x00
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 2cd1c021b5..474ab5deda 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -117,6 +117,7 @@ static void __init processor_id(void)
struct cpuinfo_arm *c = &system_cpuinfo;
identify_cpu(c);
+ update_system_pmu_num_cntrs();
current_cpu_data = *c;
if ( c->midr.implementer < ARRAY_SIZE(processor_implementers) &&
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |