[PATCH v2 07/11] lib: utils: fdt_fixup: Add fdt_add_pmu_mappings() helper function
Anup Patel
anup at brainfault.org
Wed Nov 15 22:59:16 PST 2023
On Thu, Oct 19, 2023 at 5:11 PM Yu Chien Peter Lin
<peterlin at andestech.com> wrote:
>
> Add fdt_add_pmu_mappings() that creates entries of riscv,*event-to-mhpm*
> property from arrays right before fdt_pmu_setup() populating the mapping
> tables (i.e. hw_event_map[] and fdt_pmu_evt_select[]).
>
> The helper function will skip the creation of those properties if a
> "/pmu" node with "riscv,pmu" compatible string is provided.
>
> Signed-off-by: Yu Chien Peter Lin <peterlin at andestech.com>
This patch can be dropped. See my comment in PATCH10.
Regards,
Anup
> ---
> Changes v1 -> v2:
> - New patch
> ---
> include/sbi_utils/fdt/fdt_fixup.h | 48 ++++++++++
> lib/utils/fdt/fdt_fixup.c | 95 ++++++++++++++++++++
> platform/generic/include/platform_override.h | 1 +
> platform/generic/platform.c | 10 ++-
> 4 files changed, 153 insertions(+), 1 deletion(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
> index ecd55a7..9b72df8 100644
> --- a/include/sbi_utils/fdt/fdt_fixup.h
> +++ b/include/sbi_utils/fdt/fdt_fixup.h
> @@ -19,6 +19,54 @@ struct sbi_cpu_idle_state {
> uint32_t wakeup_latency_us;
> };
>
> +struct sbi_pmu_event_select_map {
> + /**
> + * The description of an entry in
> + * riscv,event-to-mhpmevent property
> + */
> + uint32_t eidx;
> + uint64_t select;
> +};
> +
> +struct sbi_pmu_event_counter_map {
> + /**
> + * The description of an entry in
> + * riscv,event-to-mhpmcounters property
> + */
> + uint32_t eidx_start;
> + uint32_t eidx_end;
> + uint32_t ctr_map;
> +};
> +
> +struct sbi_pmu_raw_event_counter_map {
> + /**
> + * The description of an entry in
> + * riscv,raw-event-to-mhpmcounters property
> + */
> + uint64_t select;
> + uint64_t select_mask;
> + uint32_t ctr_map;
> +};
> +
> +/**
> + * Add PMU properties in the DT
> + *
> + * Add information about event to selector/counter mappings to the
> + * devicetree.
> + *
> + * @param fdt: device tree blob
> + * @param selects: array of event index to selector value mapping
> + * descriptions, ending with empty element
> + * @param counters: array of event indexes to counters mapping
> + * descriptions, ending with empty element
> + * @param rcounters: array of raw events to counters mapping
> + * descriptions, ending with empty element
> + * @return zero on success and -ve on failure
> + */
> +int fdt_add_pmu_mappings(void *fdt, const struct sbi_pmu_event_select_map *selects,
> + const struct sbi_pmu_event_counter_map *counters,
> + const struct sbi_pmu_raw_event_counter_map *rcounters);
> +
> /**
> * Add CPU idle states to cpu nodes in the DT
> *
> diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
> index e213ded..67e2e2e 100644
> --- a/lib/utils/fdt/fdt_fixup.c
> +++ b/lib/utils/fdt/fdt_fixup.c
> @@ -20,6 +20,101 @@
> #include <sbi_utils/fdt/fdt_pmu.h>
> #include <sbi_utils/fdt/fdt_helper.h>
>
> +int fdt_add_pmu_mappings(void *fdt, const struct sbi_pmu_event_select_map *selects,
> + const struct sbi_pmu_event_counter_map *counters,
> + const struct sbi_pmu_raw_event_counter_map *rcounters)
> +{
> + int i, err, pmu_noff, root_noff;
> + const char *comp;
> + fdt32_t evt_to_mhpmevent[3];
> + fdt32_t evt_to_mhpmcounters[3];
> + fdt32_t raw_evt_to_mhpmcounters[5];
> +
> + /* Try to locate pmu node */
> + pmu_noff = fdt_path_offset(fdt, "/pmu");
> +
> + if (pmu_noff > 0) {
> + /*
> + * If compatible string is "riscv,pmu",
> + * we assume a valid pmu node has been
> + * provided.
> + */
> + comp = fdt_getprop(fdt, pmu_noff, "compatible", NULL);
> + if (comp && !strcmp(comp, "riscv,pmu"))
> + return 0;
> + else
> + return -FDT_ERR_BADVALUE;
> + }
> +
> + if (pmu_noff < 0 && pmu_noff != -FDT_ERR_NOTFOUND)
> + return pmu_noff;
> +
> + /*
> + * If "riscv,event-to-mhpmevent" is present, "riscv,event-to-mhpmcounters"
> + * must be provided as well, but not vice versa (OpenSBI will direct mapping
> + * event_idx as selector value).
> + */
> + if (selects && !counters) {
> + sbi_printf("%s: ERR: riscv,event-to-mhpmcounters is mandatory if"
> + " riscv,event-to-mhpmevent is present.", __func__);
> + return SBI_EINVAL;
> + }
> +
> + /*
> + * Create pmu node based on given @selects, @counters
> + * and @rcounters.
> + */
> + root_noff = fdt_path_offset(fdt, "/");
> + pmu_noff = fdt_add_subnode(fdt, root_noff, "pmu");
> + if (pmu_noff < 0)
> + return pmu_noff;
> +
> + err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 1024);
> + if (err < 0)
> + return err;
> +
> + err = fdt_setprop_string(fdt, pmu_noff, "compatible", "riscv,pmu");
> + if (err)
> + return err;
> +
> + /* Add riscv,event-to-mhpmevent */
> + for (i = 0; selects && selects[i].eidx; i++) {
> + evt_to_mhpmevent[0] = cpu_to_fdt32(selects[i].eidx);
> + evt_to_mhpmevent[1] = cpu_to_fdt32(selects[i].select >> 32);
> + evt_to_mhpmevent[2] = cpu_to_fdt32(selects[i].select & ~0UL);
> + err = fdt_appendprop(fdt, pmu_noff, "riscv,event-to-mhpmevent",
> + evt_to_mhpmevent, 3 * sizeof(fdt32_t));
> + if (err)
> + return err;
> + }
> +
> + /* Add riscv,event-to-mhpmcounters */
> + for (i = 0; counters && counters[i].eidx_start; i++) {
> + evt_to_mhpmcounters[0] = cpu_to_fdt32(counters[i].eidx_start);
> + evt_to_mhpmcounters[1] = cpu_to_fdt32(counters[i].eidx_end);
> + evt_to_mhpmcounters[2] = cpu_to_fdt32(counters[i].ctr_map);
> + err = fdt_appendprop(fdt, pmu_noff, "riscv,event-to-mhpmcounters",
> + evt_to_mhpmcounters, 3 * sizeof(fdt32_t));
> + if (err)
> + return err;
> + }
> +
> + /* Add riscv,raw-event-to-mhpmcounters */
> + for (i = 0; rcounters && rcounters[i].select; i++) {
> + raw_evt_to_mhpmcounters[0] = cpu_to_fdt32(rcounters[i].select >> 32);
> + raw_evt_to_mhpmcounters[1] = cpu_to_fdt32(rcounters[i].select & ~0UL);
> + raw_evt_to_mhpmcounters[2] = cpu_to_fdt32(rcounters[i].select_mask >> 32);
> + raw_evt_to_mhpmcounters[3] = cpu_to_fdt32(rcounters[i].select_mask & ~0UL);
> + raw_evt_to_mhpmcounters[4] = cpu_to_fdt32(rcounters[i].ctr_map);
> + err = fdt_appendprop(fdt, pmu_noff, "riscv,raw-event-to-mhpmcounters",
> + raw_evt_to_mhpmcounters, 5 * sizeof(fdt32_t));
> + if (err)
> + return err;
> + }
> +
> + return 0;
> +}
> +
> int fdt_add_cpu_idle_states(void *fdt, const struct sbi_cpu_idle_state *state)
> {
> int cpu_node, cpus_node, err, idle_states_node;
> diff --git a/platform/generic/include/platform_override.h b/platform/generic/include/platform_override.h
> index bf4b112..bd34d2a 100644
> --- a/platform/generic/include/platform_override.h
> +++ b/platform/generic/include/platform_override.h
> @@ -19,6 +19,7 @@ struct platform_override {
> u64 (*features)(const struct fdt_match *match);
> u64 (*tlbr_flush_limit)(const struct fdt_match *match);
> u32 (*tlb_num_entries)(const struct fdt_match *match);
> + int (*fdt_add_pmu_mappings)(void *fdt, const struct fdt_match *match);
> bool (*cold_boot_allowed)(u32 hartid, const struct fdt_match *match);
> int (*early_init)(bool cold_boot, const struct fdt_match *match);
> int (*final_init)(bool cold_boot, const struct fdt_match *match);
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index cb9270d..a48a8b7 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -265,9 +265,17 @@ static u32 generic_tlb_num_entries(void)
>
> static int generic_pmu_init(void)
> {
> + void *fdt = fdt_get_address();
> int rc;
>
> - rc = fdt_pmu_setup(fdt_get_address());
> + if (generic_plat && generic_plat->fdt_add_pmu_mappings) {
> + rc = generic_plat->fdt_add_pmu_mappings(fdt,
> + generic_plat_match);
> + if (rc)
> + return rc;
> + }
> +
> + rc = fdt_pmu_setup(fdt);
> if (rc && rc != SBI_ENOENT)
> return rc;
>
> --
> 2.34.1
>
More information about the opensbi
mailing list