[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


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Daisuke Nishimura <nishimura@xxxxxxxxxxxxx>
  • Date: Tue, 10 Nov 2026 14:30:39 +0900
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=j3V8l/mNWRz2YJFIRXoVS8SRruajOHQneJcfEo6dcAM=; b=PKa121g/OteZJL5Cl9wsvwccSHiYu+I0uwdl20XHytDGF/5Hezeqgs2UPW6W+75xtKpphR2ZBA55mooXtM+0qIPbpPlgMYIKhuPOAvqp3U82RDgj3AKNHZrmf+9keT17f78pKwNXfKwof14s5EtHuF/OScNddTBsRt/XUq/zS1QVZiGdnEbG1YsWaaNG/gbbIuhZeiPK4FKkBF2+Tgnm7ICVokjee8aJlU8vbYWZB6NrlkGMRnsAkYbrTeIMnnmnCia5gHVxrg/oPQT/KREMDEqyjU7ed7G9vB77n47cyDgAn4FSWrqIuRpqDkKSlPyQ9Nj2c1Kszj+h1JZxLpXtYg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=uwiTp7UUAobgDgg1JzKbMAFlFNIwYlRX2+MLrcupKrFjcIGVU7juwRPRboBXS0EL0ubHRPP3Ec25s0A3FXZKnGKXjXtgK0+nozVOfLFWxJtxKWq+ZqM4nbRurwv9Zve/FgSkCUVzX2pMjnL5dOFlbbHH+ruZkk1BukTQat2UVgYExGBVt+Sv8wlaa9hC1GAvPI/NB7dagAcm0l2tHWZVUShJUD6LXfuz4gylua71ECsR6fvwwXTmze/Br4+oI3GJunZyhTCtdQZu0aFhedlvQRimjR5Ag2xylWV1m1y69cTdk5ovfejOSL7//RdlLCsoQEX+wYD8bfvvT6ZqBHtNAQ==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=valinux.co.jp header.i="@valinux.co.jp" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: mx.microsoft.com 1; dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp;
  • Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Leonid Komarianskyi <leonid_komarianskyi@xxxxxxxx>
  • Delivery-date: Tue, 10 Nov 2026 05:34:16 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

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



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.