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();

Reply via email to