This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 8251f294ba5 arch/arm/armv7-a: Start the PMU cycle counter on the
secondary CPUs.
8251f294ba5 is described below
commit 8251f294ba5da947b7820d84d34350c1db88ee0d
Author: Marco Casaroli <[email protected]>
AuthorDate: Tue Nov 3 21:44:15 2026 +0100
arch/arm/armv7-a: Start the PMU cycle counter on the secondary CPUs.
The boards call up_perf_init() once, on the boot CPU. But the cycle
counter (PMCCNTR) and its control registers belong to each CPU, so the
counter of the other CPUs does not run. With SMP, perf_gettime() on
CPU 1 to N returns a constant: the critmon times and the CPU-time
clocks of the threads on those CPUs stay 0.
Add arm_perf_secondary_init() and call it in arm_cpu_boot() of the
ARMv7-A chips that start the counter on the boot CPU (qemu, goldfish,
rtl8730e), with the same condition (ARCH_PERF_EVENTS).
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
arch/arm/src/armv7-a/arm_perf.c | 31 ++++++++++++++++++++++++++++---
arch/arm/src/common/arm_internal.h | 15 +++++++++++++++
arch/arm/src/goldfish/goldfish_cpuboot.c | 4 ++++
arch/arm/src/qemu/qemu_cpuboot.c | 4 ++++
arch/arm/src/rtl8730e/rtl8730e_cpuboot.c | 4 ++++
5 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/arch/arm/src/armv7-a/arm_perf.c b/arch/arm/src/armv7-a/arm_perf.c
index 4337cb0600c..40acb7c3cb7 100644
--- a/arch/arm/src/armv7-a/arm_perf.c
+++ b/arch/arm/src/armv7-a/arm_perf.c
@@ -39,6 +39,17 @@
static unsigned long g_cpu_freq = ULONG_MAX;
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void arm_perf_start(void)
+{
+ cp15_pmu_uer(PMUER_UME);
+ cp15_pmu_pmcr(PMCR_E);
+ cp15_pmu_cesr(PMCESR_CCES);
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -74,11 +85,25 @@ void up_perf_init(void *arg)
}
#endif
- cp15_pmu_uer(PMUER_UME);
- cp15_pmu_pmcr(PMCR_E);
- cp15_pmu_cesr(PMCESR_CCES);
+ arm_perf_start();
}
+/****************************************************************************
+ * Name: arm_perf_secondary_init
+ *
+ * Description:
+ * Start the cycle counter of a secondary CPU. up_perf_init() runs on
+ * the boot CPU only, and the cycle counter is a register of each CPU.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ARCH_PERF_EVENTS)
+void arm_perf_secondary_init(void)
+{
+ arm_perf_start();
+}
+#endif
+
unsigned long up_perf_getfreq(void)
{
return g_cpu_freq;
diff --git a/arch/arm/src/common/arm_internal.h
b/arch/arm/src/common/arm_internal.h
index 5e77ae30bab..bfeae9deeee 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -478,6 +478,21 @@ void arm_netinitialize(void);
void arm_timer_secondary_init(unsigned int freq);
#endif
+/****************************************************************************
+ * Name: arm_perf_secondary_init
+ *
+ * Description:
+ * Start the PMU cycle counter of a secondary CPU.
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ARCH_PERF_EVENTS)
+void arm_perf_secondary_init(void);
+#endif
+
/* USB **********************************************************************/
#ifdef CONFIG_USBDEV
diff --git a/arch/arm/src/goldfish/goldfish_cpuboot.c
b/arch/arm/src/goldfish/goldfish_cpuboot.c
index 3773bb4b29a..63f7e9037ac 100644
--- a/arch/arm/src/goldfish/goldfish_cpuboot.c
+++ b/arch/arm/src/goldfish/goldfish_cpuboot.c
@@ -91,6 +91,10 @@ void arm_cpu_boot(int cpu)
arm_timer_secondary_init(0);
+#ifdef CONFIG_ARCH_PERF_EVENTS
+ arm_perf_secondary_init();
+#endif
+
/* The next thing that we expect to happen is for logic running on CPU0
* to call up_cpu_start() which generate an SGI and a context switch to
* the configured NuttX IDLE task.
diff --git a/arch/arm/src/qemu/qemu_cpuboot.c b/arch/arm/src/qemu/qemu_cpuboot.c
index 1b9457707ab..05bcf0d21db 100644
--- a/arch/arm/src/qemu/qemu_cpuboot.c
+++ b/arch/arm/src/qemu/qemu_cpuboot.c
@@ -85,6 +85,10 @@ void arm_cpu_boot(int cpu)
arm_timer_secondary_init(0);
+#ifdef CONFIG_ARCH_PERF_EVENTS
+ arm_perf_secondary_init();
+#endif
+
/* Then transfer control to the IDLE task */
nx_idle_trampoline();
diff --git a/arch/arm/src/rtl8730e/rtl8730e_cpuboot.c
b/arch/arm/src/rtl8730e/rtl8730e_cpuboot.c
index 964e5d8d5c0..fc743e299db 100644
--- a/arch/arm/src/rtl8730e/rtl8730e_cpuboot.c
+++ b/arch/arm/src/rtl8730e/rtl8730e_cpuboot.c
@@ -85,6 +85,10 @@ void arm_cpu_boot(int cpu)
arm_timer_secondary_init(0);
+#ifdef CONFIG_ARCH_PERF_EVENTS
+ arm_perf_secondary_init();
+#endif
+
/* Then transfer control to the IDLE task */
nx_idle_trampoline();