[PATCH RFC 10/10] hw/riscv/virt.c: Generate the PMU node from the machine

Atish Patra posted 10 patches 1 month, 2 weeks ago
[PATCH RFC 10/10] hw/riscv/virt.c: Generate the PMU node from the machine
Posted by Atish Patra 1 month, 2 weeks ago
The virt machine implementation relies on the SBI PMU extension.
The OpenSBI implementation requires a PMU specific DT node that
is currently encodes the counter and PMU events mapping.
As the PMU DT node encodes the platform specific event encodings,
it should be implement in platform specific code instead of generic
PMU code.

Move the PMU DT node generation code from virt.c from common pmu
code.

Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
 hw/riscv/virt.c    | 21 +++++++++++++++++++--
 target/riscv/pmu.c | 36 ------------------------------------
 target/riscv/pmu.h |  1 -
 3 files changed, 19 insertions(+), 39 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ffda6d65d673..056afe6a6ceb 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -792,11 +792,28 @@ static void create_fdt_pmu(RISCVVirtState *s)
 {
     g_autofree char *pmu_name = g_strdup_printf("/pmu");
     MachineState *ms = MACHINE(s);
-    RISCVCPU hart = s->soc[0].harts[0];
+    uint32_t fdt_event_ctr_map[15] = {};
+    int i;
 
     qemu_fdt_add_subnode(ms->fdt, pmu_name);
     qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu");
-    riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name);
+
+    /*
+     * To keep it simple, any event can be mapped to any programmable counters
+     * in QEMU. The generic cycle & instruction count events can also be
+     * monitored using programmable counters. In that case, mcycle & minstret
+     * must continue to provide the correct value as well. Heterogeneous PMU per
+     * hart is not supported yet. Thus, number of counters are same across all
+     * harts.
+     */
+    for (i = 0; i < ARRAY_SIZE(pmu_events_arr); i++) {
+        fdt_event_ctr_map[0 + i * 3] = cpu_to_be32(pmu_events_arr[i].event_id);
+        fdt_event_ctr_map[1 + i * 3] = cpu_to_be32(pmu_events_arr[i].event_id);
+        fdt_event_ctr_map[2 + i * 3] = cpu_to_be32(pmu_events_arr[i].counter_mask);
+    }
+    /* This a OpenSBI specific DT property documented in OpenSBI docs */
+    qemu_fdt_setprop(ms->fdt, pmu_name, "riscv,event-to-mhpmcounters",
+                     fdt_event_ctr_map, sizeof(fdt_event_ctr_map));
 }
 
 static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index e80f0f911fa3..dd0a18ae3dc1 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -27,42 +27,6 @@
 
 #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */
 
-/*
- * To keep it simple, any event can be mapped to any programmable counters in
- * QEMU. The generic cycle & instruction count events can also be monitored
- * using programmable counters. In that case, mcycle & minstret must continue
- * to provide the correct value as well. Heterogeneous PMU per hart is not
- * supported yet. Thus, number of counters are same across all harts.
- */
-void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name)
-{
-    uint32_t fdt_event_ctr_map[15] = {};
-
-   fdt_event_ctr_map[0] = cpu_to_be32(VIRT_PMU_EVENT_HW_CPU_CYCLES);
-   fdt_event_ctr_map[1] = cpu_to_be32(VIRT_PMU_EVENT_HW_CPU_CYCLES);
-   fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0);
-
-   fdt_event_ctr_map[3] = cpu_to_be32(VIRT_PMU_EVENT_HW_INSTRUCTIONS);
-   fdt_event_ctr_map[4] = cpu_to_be32(VIRT_PMU_EVENT_HW_INSTRUCTIONS);
-   fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2);
-
-   fdt_event_ctr_map[6] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_DTLB_READ_MISS);
-   fdt_event_ctr_map[7] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_DTLB_READ_MISS);
-   fdt_event_ctr_map[8] = cpu_to_be32(cmask);
-
-   fdt_event_ctr_map[9] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_DTLB_WRITE_MISS);
-   fdt_event_ctr_map[10] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_DTLB_WRITE_MISS);
-   fdt_event_ctr_map[11] = cpu_to_be32(cmask);
-
-   fdt_event_ctr_map[12] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS);
-   fdt_event_ctr_map[13] = cpu_to_be32(VIRT_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS);
-   fdt_event_ctr_map[14] = cpu_to_be32(cmask);
-
-   /* This a OpenSBI specific DT property documented in OpenSBI docs */
-   qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters",
-                    fdt_event_ctr_map, sizeof(fdt_event_ctr_map));
-}
-
 static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx)
 {
     if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS ||
diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index 810ac2fae797..10505040d9e5 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -31,7 +31,6 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp);
 int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value,
                                uint32_t ctr_idx);
 int riscv_pmu_incr_ctr(RISCVCPU *cpu, uint64_t event_idx);
-void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value,
                           uint32_t ctr_idx);
 void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv,

-- 
2.34.1