Message ID | 20231130124213.2590640-15-peterlin@andestech.com |
---|---|
State | Changes Requested |
Headers | show |
Series | Add Andes PMU extension support | expand |
On Thu, Nov 30, 2023 at 4:44 AM Yu Chien Peter Lin <peterlin@andestech.com> wrote: > > Provide the andes_pmu_setup() to populate default mappings in > hw_event_map[] and fdt_pmu_evt_select[] when fdt_pmu_setup() > cannot find the PMU node. > > Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com> > Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > --- > Changes v2 -> v3: > - New patch > - Drop fdt_add_pmu_mappings() (suggested by Anup [1]) > Changes v3 -> v4: > - Include TB tag from Prabhakar > - Staticize andes_pmu_setup() when CONFIG_PLATFORM_ANDES_AE350 is not set > > [1] https://patchwork.ozlabs.org/project/opensbi/patch/20231019113713.3508153-11-peterlin@andestech.com/ > --- > include/sbi/sbi_ecall_interface.h | 5 + > platform/generic/Kconfig | 2 + > platform/generic/andes/Kconfig | 7 + > platform/generic/andes/andes_hpm.c | 405 +++++++++++++++++++++ > platform/generic/andes/objects.mk | 1 + > platform/generic/include/andes/andes_hpm.h | 69 ++++ > 6 files changed, 489 insertions(+) > create mode 100644 platform/generic/andes/andes_hpm.c > > diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h > index 1fe469e..89187e7 100644 > --- a/include/sbi/sbi_ecall_interface.h > +++ b/include/sbi/sbi_ecall_interface.h > @@ -155,6 +155,11 @@ enum sbi_pmu_hw_cache_op_result_id { > SBI_PMU_HW_CACHE_RESULT_MAX, > }; > > +#define SBI_PMU_HW_CACHE_EVENT_IDX(id, op, res) \ > + (SBI_PMU_EVENT_TYPE_HW_CACHE << SBI_PMU_EVENT_IDX_TYPE_OFFSET | \ > + SBI_PMU_HW_CACHE_##id << 3 | SBI_PMU_HW_CACHE_OP_##op << 1 | \ > + SBI_PMU_HW_CACHE_RESULT_##res) > + > /** > * Special "firmware" events provided by the OpenSBI, even if the hardware > * does not support performance events. These events are encoded as a raw > diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig > index c9b6011..e652645 100644 > --- a/platform/generic/Kconfig > +++ b/platform/generic/Kconfig > @@ -32,6 +32,7 @@ config PLATFORM_ALLWINNER_D1 > config PLATFORM_ANDES_AE350 > bool "Andes AE350 support" > select SYS_ATCSMU > + select ANDES_HPM > select ANDES_PMU > default n > > @@ -39,6 +40,7 @@ config PLATFORM_RENESAS_RZFIVE > bool "Renesas RZ/Five support" > select ANDES45_PMA > select ANDES_SBI > + select ANDES_HPM > select ANDES_PMU > default n > > diff --git a/platform/generic/andes/Kconfig b/platform/generic/andes/Kconfig > index 3665b33..eb697a6 100644 > --- a/platform/generic/andes/Kconfig > +++ b/platform/generic/andes/Kconfig > @@ -8,6 +8,13 @@ config ANDES_SBI > bool "Andes SBI support" > default n > > +config ANDES_HPM > + bool "Andes HPM support" > + default n > + help > + This provides default HPM event counter mappings > + when a pmu node is missing. > + > config ANDES_PMU > bool "Andes PMU extension (XAndesPMU) support" > default n > diff --git a/platform/generic/andes/andes_hpm.c b/platform/generic/andes/andes_hpm.c > new file mode 100644 > index 0000000..7fe5ac5 > --- /dev/null > +++ b/platform/generic/andes/andes_hpm.c > @@ -0,0 +1,405 @@ > +// SPDX-License-Identifier: BSD-2-Clause > +/* > + * andes_hpm.c - Default event mappings and helper routine > + * > + * Copyright (c) 2023 Andes Technology Corporation > + */ > + > +#include <andes/andes45.h> > +#include <andes/andes_hpm.h> > +#include <sbi/sbi_ecall_interface.h> > +#include <sbi/sbi_pmu.h> > +#include <sbi_utils/fdt/fdt_pmu.h> > + > +static const struct fdt_pmu_hw_event_select_map andes45_hw_evt_selects[] = { > + /* Hardware general events (Type #0) */ > + { > + /* perf: cycles (eidx: 0x1) */ > + .eidx = SBI_PMU_HW_CPU_CYCLES, > + .select = ANDES_CYCLES > + }, > + { > + /* perf: instructions (eidx: 0x2) */ > + .eidx = SBI_PMU_HW_INSTRUCTIONS, > + .select = ANDES_INSTRET > + }, > + { > + /* perf: cache-references (eidx: 0x3) */ > + .eidx = SBI_PMU_HW_CACHE_REFERENCES, > + .select = ANDES_DCACHE_ACCESS > + }, > + { > + /* perf: cache-misses (eidx: 0x4) */ > + .eidx = SBI_PMU_HW_CACHE_MISSES, > + .select = ANDES_DCACHE_MISS > + }, > + { > + /* perf: branches (eidx: 0x5) */ > + .eidx = SBI_PMU_HW_BRANCH_INSTRUCTIONS, > + .select = ANDES_CONDITION_BR, > + }, > + { > + /* perf: branch-misses (eidx: 0x6) */ > + .eidx = SBI_PMU_HW_BRANCH_MISSES, > + .select = ANDES_MISPREDICT_CONDITION_BR, > + }, > + /* Hardware cache events (Type #1) */ > + { > + /* perf: L1-dcache-loads (eidx: 0x10000) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), > + .select = ANDES_DCACHE_LOAD_ACCESS > + }, > + { > + /* perf: L1-dcache-loads-misses (eidx: 0x10001) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, MISS), > + .select = ANDES_DCACHE_LOAD_MISS > + }, > + { > + /* perf: L1-dcache-stores (eidx: 0x10002) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, ACCESS), > + .select = ANDES_DCACHE_STORE_ACCESS > + }, > + { > + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), > + .select = ANDES_DCACHE_STORE_MISS > + }, > + { > + /* perf: L1-icache-load (eidx: 0x10008) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), > + .select = ANDES_ICACHE_ACCESS > + }, > + { > + /* perf: L1-icache-load-misses (eidx: 0x10009) */ > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), > + .select = ANDES_ICACHE_MISS > + }, > +}; > + Is there a specific reason why the platform code populates instead of a PMU DT node added by whoever generates the DT (not at boot time in OpenSBI in your earlier version versions)? > +static const struct fdt_pmu_hw_event_counter_map andes45_hw_evt_counters[] = { > + { > + /* perf: cycles (eidx: 0x1) */ > + .eidx_start = SBI_PMU_HW_CPU_CYCLES, > + /* perf: branch-misses (eidx: 0x6) */ > + .eidx_end = SBI_PMU_HW_BRANCH_MISSES, > + .ctr_map = ANDES_MHPM_MAP, > + }, > + { > + /* perf: L1-dcache-loads (eidx: 0x10000) */ > + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), > + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ > + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), > + .ctr_map = ANDES_MHPM_MAP, > + }, > + { > + /* perf: L1-icache-load (eidx: 0x10008) */ > + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), > + /* perf: L1-icache-load-misses (eidx: 0x10009) */ > + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), > + .ctr_map = ANDES_MHPM_MAP, > + }, > +}; > + > +static const struct fdt_pmu_raw_event_counter_map andes45_raw_evt_counters[] = { > + { > + .select = ANDES_CYCLES, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INSTRET, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_LOAD_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_STORE_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_ATOMIC_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_SYS_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_COMPUTE_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CONDITION_BR, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_TAKEN_CONDITION_BR, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_JAL_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_JALR_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_RET_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CONTROL_TRANS_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_EX9_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_MUL_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_DIV_REMAINDER_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_LOAD_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_STORE_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_ADD_SUB_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_MUL_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_FUSED_MULADD_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_FLOAT_DIV_SQUARE_ROOT_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_OTHER_FLOAT_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_INT_MUL_AND_SUB_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_RETIRED_OP, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_ILM_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DLM_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_ICACHE_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_ICACHE_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_LOAD_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_LOAD_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_STORE_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_STORE_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_DCACHE_WB, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CYCLE_WAIT_ICACHE_FILL, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CYCLE_WAIT_DCACHE_FILL, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_UNCACHED_IFETCH_FROM_BUS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_UNCACHED_LOAD_FROM_BUS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CYCLE_WAIT_UNCACHED_IFETCH, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CYCLE_WAIT_UNCACHED_LOAD, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MAIN_ITLB_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MAIN_ITLB_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MAIN_DTLB_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MAIN_DTLB_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_CYCLE_WAIT_ITLB_FILL, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_PIPE_STALL_CYCLE_DTLB_MISS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_HW_PREFETCH_BUS_ACCESS, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MISPREDICT_CONDITION_BR, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MISPREDICT_TAKE_CONDITION_BR, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > + { > + .select = ANDES_MISPREDICT_TARGET_RET_INST, > + .select_mask = ANDES_RAW_EVENT_MASK, > + .ctr_map = ANDES_MHPM_MAP > + }, > +}; > + > +int andes_pmu_setup(void) > +{ > + int i, rc; > + struct fdt_pmu_hw_event_select_map *event; > + > + /* > + * At the moment, simply create mapping for any 45-series core > + * based on marchid, we may check and differentiate the mapping > + * by mimpid. > + */ > + if (!is_andes(45)) nit: A macro would be nice here. > + return 0; > + > + for (i = 0; i < array_size(andes45_hw_evt_counters); i++) { > + rc = sbi_pmu_add_hw_event_counter_map( > + andes45_hw_evt_counters[i].eidx_start, > + andes45_hw_evt_counters[i].eidx_end, > + andes45_hw_evt_counters[i].ctr_map); > + if (rc) > + return rc; > + } > + > + for (i = 0; i < array_size(andes45_hw_evt_selects); i++) { > + event = &fdt_pmu_evt_select[hw_event_count]; > + event->eidx = andes45_hw_evt_selects[i].eidx; > + event->select = andes45_hw_evt_selects[i].select; > + hw_event_count++; > + } > + > + for (i = 0; i < array_size(andes45_raw_evt_counters); i++) { > + rc = sbi_pmu_add_raw_event_counter_map( > + andes45_raw_evt_counters[i].select, > + andes45_raw_evt_counters[i].select_mask, > + andes45_raw_evt_counters[i].ctr_map); > + if (rc) > + return rc; > + } > + > + return 0; > +} > diff --git a/platform/generic/andes/objects.mk b/platform/generic/andes/objects.mk > index 6a8c66c..57caaf6 100644 > --- a/platform/generic/andes/objects.mk > +++ b/platform/generic/andes/objects.mk > @@ -8,3 +8,4 @@ platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o > platform-objs-$(CONFIG_ANDES45_PMA) += andes/andes45-pma.o > platform-objs-$(CONFIG_ANDES_SBI) += andes/andes_sbi.o > platform-objs-$(CONFIG_ANDES_PMU) += andes/andes_pmu.o > +platform-objs-$(CONFIG_ANDES_HPM) += andes/andes_hpm.o > diff --git a/platform/generic/include/andes/andes_hpm.h b/platform/generic/include/andes/andes_hpm.h > index b4d71b9..0ae391f 100644 > --- a/platform/generic/include/andes/andes_hpm.h > +++ b/platform/generic/include/andes/andes_hpm.h > @@ -7,6 +7,75 @@ > #ifndef _ANDES_HPM_H_ > #define _ANDES_HPM_H_ > > +#define ANDES_MHPM_MAP 0x78 > +#define ANDES_RAW_EVENT_MASK ~0ULL > + > +/* Event selector for instruction commit events */ > +#define ANDES_CYCLES 0x10 > +#define ANDES_INSTRET 0x20 > +#define ANDES_INT_LOAD_INST 0x30 > +#define ANDES_INT_STORE_INST 0x40 > +#define ANDES_ATOMIC_INST 0x50 > +#define ANDES_SYS_INST 0x60 > +#define ANDES_INT_COMPUTE_INST 0x70 > +#define ANDES_CONDITION_BR 0x80 > +#define ANDES_TAKEN_CONDITION_BR 0x90 > +#define ANDES_JAL_INST 0xA0 > +#define ANDES_JALR_INST 0xB0 > +#define ANDES_RET_INST 0xC0 > +#define ANDES_CONTROL_TRANS_INST 0xD0 > +#define ANDES_EX9_INST 0xE0 > +#define ANDES_INT_MUL_INST 0xF0 > +#define ANDES_INT_DIV_REMAINDER_INST 0x100 > +#define ANDES_FLOAT_LOAD_INST 0x110 > +#define ANDES_FLOAT_STORE_INST 0x120 > +#define ANDES_FLOAT_ADD_SUB_INST 0x130 > +#define ANDES_FLOAT_MUL_INST 0x140 > +#define ANDES_FLOAT_FUSED_MULADD_INST 0x150 > +#define ANDES_FLOAT_DIV_SQUARE_ROOT_INST 0x160 > +#define ANDES_OTHER_FLOAT_INST 0x170 > +#define ANDES_INT_MUL_AND_SUB_INST 0x180 > +#define ANDES_RETIRED_OP 0x190 > + > +/* Event selector for memory system events */ > +#define ANDES_ILM_ACCESS 0x01 > +#define ANDES_DLM_ACCESS 0x11 > +#define ANDES_ICACHE_ACCESS 0x21 > +#define ANDES_ICACHE_MISS 0x31 > +#define ANDES_DCACHE_ACCESS 0x41 > +#define ANDES_DCACHE_MISS 0x51 > +#define ANDES_DCACHE_LOAD_ACCESS 0x61 > +#define ANDES_DCACHE_LOAD_MISS 0x71 > +#define ANDES_DCACHE_STORE_ACCESS 0x81 > +#define ANDES_DCACHE_STORE_MISS 0x91 > +#define ANDES_DCACHE_WB 0xA1 > +#define ANDES_CYCLE_WAIT_ICACHE_FILL 0xB1 > +#define ANDES_CYCLE_WAIT_DCACHE_FILL 0xC1 > +#define ANDES_UNCACHED_IFETCH_FROM_BUS 0xD1 > +#define ANDES_UNCACHED_LOAD_FROM_BUS 0xE1 > +#define ANDES_CYCLE_WAIT_UNCACHED_IFETCH 0xF1 > +#define ANDES_CYCLE_WAIT_UNCACHED_LOAD 0x101 > +#define ANDES_MAIN_ITLB_ACCESS 0x111 > +#define ANDES_MAIN_ITLB_MISS 0x121 > +#define ANDES_MAIN_DTLB_ACCESS 0x131 > +#define ANDES_MAIN_DTLB_MISS 0x141 > +#define ANDES_CYCLE_WAIT_ITLB_FILL 0x151 > +#define ANDES_PIPE_STALL_CYCLE_DTLB_MISS 0x161 > +#define ANDES_HW_PREFETCH_BUS_ACCESS 0x171 > + > +/* Event selector for microarchitecture events */ > +#define ANDES_MISPREDICT_CONDITION_BR 0x02 > +#define ANDES_MISPREDICT_TAKE_CONDITION_BR 0x12 > +#define ANDES_MISPREDICT_TARGET_RET_INST 0x22 > + > +#ifdef CONFIG_ANDES_HPM > + > +int andes_pmu_setup(void); > + > +#else > + > static inline int andes_pmu_setup(void) { return 0; } > > +#endif /* CONFIG_ANDES_HPM */ > + > #endif /* _ANDES_HPM_H_ */ > -- > 2.34.1 >
On Tue, Dec 05, 2023 at 05:53:19PM -0800, Atish Patra wrote: > On Thu, Nov 30, 2023 at 4:44 AM Yu Chien Peter Lin > <peterlin@andestech.com> wrote: > > > > Provide the andes_pmu_setup() to populate default mappings in > > hw_event_map[] and fdt_pmu_evt_select[] when fdt_pmu_setup() > > cannot find the PMU node. > > > > Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com> > > Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > > --- > > Changes v2 -> v3: > > - New patch > > - Drop fdt_add_pmu_mappings() (suggested by Anup [1]) > > Changes v3 -> v4: > > - Include TB tag from Prabhakar > > - Staticize andes_pmu_setup() when CONFIG_PLATFORM_ANDES_AE350 is not set > > > > [1] https://patchwork.ozlabs.org/project/opensbi/patch/20231019113713.3508153-11-peterlin@andestech.com/ > > --- > > include/sbi/sbi_ecall_interface.h | 5 + > > platform/generic/Kconfig | 2 + > > platform/generic/andes/Kconfig | 7 + > > platform/generic/andes/andes_hpm.c | 405 +++++++++++++++++++++ > > platform/generic/andes/objects.mk | 1 + > > platform/generic/include/andes/andes_hpm.h | 69 ++++ > > 6 files changed, 489 insertions(+) > > create mode 100644 platform/generic/andes/andes_hpm.c > > > > diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h > > index 1fe469e..89187e7 100644 > > --- a/include/sbi/sbi_ecall_interface.h > > +++ b/include/sbi/sbi_ecall_interface.h > > @@ -155,6 +155,11 @@ enum sbi_pmu_hw_cache_op_result_id { > > SBI_PMU_HW_CACHE_RESULT_MAX, > > }; > > > > +#define SBI_PMU_HW_CACHE_EVENT_IDX(id, op, res) \ > > + (SBI_PMU_EVENT_TYPE_HW_CACHE << SBI_PMU_EVENT_IDX_TYPE_OFFSET | \ > > + SBI_PMU_HW_CACHE_##id << 3 | SBI_PMU_HW_CACHE_OP_##op << 1 | \ > > + SBI_PMU_HW_CACHE_RESULT_##res) > > + > > /** > > * Special "firmware" events provided by the OpenSBI, even if the hardware > > * does not support performance events. These events are encoded as a raw > > diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig > > index c9b6011..e652645 100644 > > --- a/platform/generic/Kconfig > > +++ b/platform/generic/Kconfig > > @@ -32,6 +32,7 @@ config PLATFORM_ALLWINNER_D1 > > config PLATFORM_ANDES_AE350 > > bool "Andes AE350 support" > > select SYS_ATCSMU > > + select ANDES_HPM > > select ANDES_PMU > > default n > > > > @@ -39,6 +40,7 @@ config PLATFORM_RENESAS_RZFIVE > > bool "Renesas RZ/Five support" > > select ANDES45_PMA > > select ANDES_SBI > > + select ANDES_HPM > > select ANDES_PMU > > default n > > > > diff --git a/platform/generic/andes/Kconfig b/platform/generic/andes/Kconfig > > index 3665b33..eb697a6 100644 > > --- a/platform/generic/andes/Kconfig > > +++ b/platform/generic/andes/Kconfig > > @@ -8,6 +8,13 @@ config ANDES_SBI > > bool "Andes SBI support" > > default n > > > > +config ANDES_HPM > > + bool "Andes HPM support" > > + default n > > + help > > + This provides default HPM event counter mappings > > + when a pmu node is missing. > > + > > config ANDES_PMU > > bool "Andes PMU extension (XAndesPMU) support" > > default n > > diff --git a/platform/generic/andes/andes_hpm.c b/platform/generic/andes/andes_hpm.c > > new file mode 100644 > > index 0000000..7fe5ac5 > > --- /dev/null > > +++ b/platform/generic/andes/andes_hpm.c > > @@ -0,0 +1,405 @@ > > +// SPDX-License-Identifier: BSD-2-Clause > > +/* > > + * andes_hpm.c - Default event mappings and helper routine > > + * > > + * Copyright (c) 2023 Andes Technology Corporation > > + */ > > + > > +#include <andes/andes45.h> > > +#include <andes/andes_hpm.h> > > +#include <sbi/sbi_ecall_interface.h> > > +#include <sbi/sbi_pmu.h> > > +#include <sbi_utils/fdt/fdt_pmu.h> > > + > > +static const struct fdt_pmu_hw_event_select_map andes45_hw_evt_selects[] = { > > + /* Hardware general events (Type #0) */ > > + { > > + /* perf: cycles (eidx: 0x1) */ > > + .eidx = SBI_PMU_HW_CPU_CYCLES, > > + .select = ANDES_CYCLES > > + }, > > + { > > + /* perf: instructions (eidx: 0x2) */ > > + .eidx = SBI_PMU_HW_INSTRUCTIONS, > > + .select = ANDES_INSTRET > > + }, > > + { > > + /* perf: cache-references (eidx: 0x3) */ > > + .eidx = SBI_PMU_HW_CACHE_REFERENCES, > > + .select = ANDES_DCACHE_ACCESS > > + }, > > + { > > + /* perf: cache-misses (eidx: 0x4) */ > > + .eidx = SBI_PMU_HW_CACHE_MISSES, > > + .select = ANDES_DCACHE_MISS > > + }, > > + { > > + /* perf: branches (eidx: 0x5) */ > > + .eidx = SBI_PMU_HW_BRANCH_INSTRUCTIONS, > > + .select = ANDES_CONDITION_BR, > > + }, > > + { > > + /* perf: branch-misses (eidx: 0x6) */ > > + .eidx = SBI_PMU_HW_BRANCH_MISSES, > > + .select = ANDES_MISPREDICT_CONDITION_BR, > > + }, > > + /* Hardware cache events (Type #1) */ > > + { > > + /* perf: L1-dcache-loads (eidx: 0x10000) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), > > + .select = ANDES_DCACHE_LOAD_ACCESS > > + }, > > + { > > + /* perf: L1-dcache-loads-misses (eidx: 0x10001) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, MISS), > > + .select = ANDES_DCACHE_LOAD_MISS > > + }, > > + { > > + /* perf: L1-dcache-stores (eidx: 0x10002) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, ACCESS), > > + .select = ANDES_DCACHE_STORE_ACCESS > > + }, > > + { > > + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), > > + .select = ANDES_DCACHE_STORE_MISS > > + }, > > + { > > + /* perf: L1-icache-load (eidx: 0x10008) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), > > + .select = ANDES_ICACHE_ACCESS > > + }, > > + { > > + /* perf: L1-icache-load-misses (eidx: 0x10009) */ > > + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), > > + .select = ANDES_ICACHE_MISS > > + }, > > +}; > > + > > Is there a specific reason why the platform code populates instead of > a PMU DT node added by whoever generates the DT (not at boot time in > OpenSBI in your earlier version versions)? Hi Atish, Either way works for me. I intended to provide a default mapping when the PMU node is missing. If adding a PMU node is encouraged, I'm OK to drop PATCH14 and revert PATCH12. Hi Prabhakar, Any thought on this? Thanks. Peter Lin > > > +static const struct fdt_pmu_hw_event_counter_map andes45_hw_evt_counters[] = { > > + { > > + /* perf: cycles (eidx: 0x1) */ > > + .eidx_start = SBI_PMU_HW_CPU_CYCLES, > > + /* perf: branch-misses (eidx: 0x6) */ > > + .eidx_end = SBI_PMU_HW_BRANCH_MISSES, > > + .ctr_map = ANDES_MHPM_MAP, > > + }, > > + { > > + /* perf: L1-dcache-loads (eidx: 0x10000) */ > > + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), > > + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ > > + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), > > + .ctr_map = ANDES_MHPM_MAP, > > + }, > > + { > > + /* perf: L1-icache-load (eidx: 0x10008) */ > > + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), > > + /* perf: L1-icache-load-misses (eidx: 0x10009) */ > > + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), > > + .ctr_map = ANDES_MHPM_MAP, > > + }, > > +}; > > + > > +static const struct fdt_pmu_raw_event_counter_map andes45_raw_evt_counters[] = { > > + { > > + .select = ANDES_CYCLES, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INSTRET, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_LOAD_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_STORE_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_ATOMIC_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_SYS_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_COMPUTE_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CONDITION_BR, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_TAKEN_CONDITION_BR, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_JAL_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_JALR_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_RET_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CONTROL_TRANS_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_EX9_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_MUL_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_DIV_REMAINDER_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_LOAD_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_STORE_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_ADD_SUB_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_MUL_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_FUSED_MULADD_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_FLOAT_DIV_SQUARE_ROOT_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_OTHER_FLOAT_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_INT_MUL_AND_SUB_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_RETIRED_OP, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_ILM_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DLM_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_ICACHE_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_ICACHE_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_LOAD_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_LOAD_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_STORE_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_STORE_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_DCACHE_WB, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CYCLE_WAIT_ICACHE_FILL, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CYCLE_WAIT_DCACHE_FILL, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_UNCACHED_IFETCH_FROM_BUS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_UNCACHED_LOAD_FROM_BUS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CYCLE_WAIT_UNCACHED_IFETCH, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CYCLE_WAIT_UNCACHED_LOAD, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MAIN_ITLB_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MAIN_ITLB_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MAIN_DTLB_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MAIN_DTLB_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_CYCLE_WAIT_ITLB_FILL, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_PIPE_STALL_CYCLE_DTLB_MISS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_HW_PREFETCH_BUS_ACCESS, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MISPREDICT_CONDITION_BR, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MISPREDICT_TAKE_CONDITION_BR, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > + { > > + .select = ANDES_MISPREDICT_TARGET_RET_INST, > > + .select_mask = ANDES_RAW_EVENT_MASK, > > + .ctr_map = ANDES_MHPM_MAP > > + }, > > +}; > > + > > +int andes_pmu_setup(void) > > +{ > > + int i, rc; > > + struct fdt_pmu_hw_event_select_map *event; > > + > > + /* > > + * At the moment, simply create mapping for any 45-series core > > + * based on marchid, we may check and differentiate the mapping > > + * by mimpid. > > + */ > > + if (!is_andes(45)) > > nit: A macro would be nice here. > > > + return 0; > > + > > + for (i = 0; i < array_size(andes45_hw_evt_counters); i++) { > > + rc = sbi_pmu_add_hw_event_counter_map( > > + andes45_hw_evt_counters[i].eidx_start, > > + andes45_hw_evt_counters[i].eidx_end, > > + andes45_hw_evt_counters[i].ctr_map); > > + if (rc) > > + return rc; > > + } > > + > > + for (i = 0; i < array_size(andes45_hw_evt_selects); i++) { > > + event = &fdt_pmu_evt_select[hw_event_count]; > > + event->eidx = andes45_hw_evt_selects[i].eidx; > > + event->select = andes45_hw_evt_selects[i].select; > > + hw_event_count++; > > + } > > + > > + for (i = 0; i < array_size(andes45_raw_evt_counters); i++) { > > + rc = sbi_pmu_add_raw_event_counter_map( > > + andes45_raw_evt_counters[i].select, > > + andes45_raw_evt_counters[i].select_mask, > > + andes45_raw_evt_counters[i].ctr_map); > > + if (rc) > > + return rc; > > + } > > + > > + return 0; > > +} > > diff --git a/platform/generic/andes/objects.mk b/platform/generic/andes/objects.mk > > index 6a8c66c..57caaf6 100644 > > --- a/platform/generic/andes/objects.mk > > +++ b/platform/generic/andes/objects.mk > > @@ -8,3 +8,4 @@ platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o > > platform-objs-$(CONFIG_ANDES45_PMA) += andes/andes45-pma.o > > platform-objs-$(CONFIG_ANDES_SBI) += andes/andes_sbi.o > > platform-objs-$(CONFIG_ANDES_PMU) += andes/andes_pmu.o > > +platform-objs-$(CONFIG_ANDES_HPM) += andes/andes_hpm.o > > diff --git a/platform/generic/include/andes/andes_hpm.h b/platform/generic/include/andes/andes_hpm.h > > index b4d71b9..0ae391f 100644 > > --- a/platform/generic/include/andes/andes_hpm.h > > +++ b/platform/generic/include/andes/andes_hpm.h > > @@ -7,6 +7,75 @@ > > #ifndef _ANDES_HPM_H_ > > #define _ANDES_HPM_H_ > > > > +#define ANDES_MHPM_MAP 0x78 > > +#define ANDES_RAW_EVENT_MASK ~0ULL > > + > > +/* Event selector for instruction commit events */ > > +#define ANDES_CYCLES 0x10 > > +#define ANDES_INSTRET 0x20 > > +#define ANDES_INT_LOAD_INST 0x30 > > +#define ANDES_INT_STORE_INST 0x40 > > +#define ANDES_ATOMIC_INST 0x50 > > +#define ANDES_SYS_INST 0x60 > > +#define ANDES_INT_COMPUTE_INST 0x70 > > +#define ANDES_CONDITION_BR 0x80 > > +#define ANDES_TAKEN_CONDITION_BR 0x90 > > +#define ANDES_JAL_INST 0xA0 > > +#define ANDES_JALR_INST 0xB0 > > +#define ANDES_RET_INST 0xC0 > > +#define ANDES_CONTROL_TRANS_INST 0xD0 > > +#define ANDES_EX9_INST 0xE0 > > +#define ANDES_INT_MUL_INST 0xF0 > > +#define ANDES_INT_DIV_REMAINDER_INST 0x100 > > +#define ANDES_FLOAT_LOAD_INST 0x110 > > +#define ANDES_FLOAT_STORE_INST 0x120 > > +#define ANDES_FLOAT_ADD_SUB_INST 0x130 > > +#define ANDES_FLOAT_MUL_INST 0x140 > > +#define ANDES_FLOAT_FUSED_MULADD_INST 0x150 > > +#define ANDES_FLOAT_DIV_SQUARE_ROOT_INST 0x160 > > +#define ANDES_OTHER_FLOAT_INST 0x170 > > +#define ANDES_INT_MUL_AND_SUB_INST 0x180 > > +#define ANDES_RETIRED_OP 0x190 > > + > > +/* Event selector for memory system events */ > > +#define ANDES_ILM_ACCESS 0x01 > > +#define ANDES_DLM_ACCESS 0x11 > > +#define ANDES_ICACHE_ACCESS 0x21 > > +#define ANDES_ICACHE_MISS 0x31 > > +#define ANDES_DCACHE_ACCESS 0x41 > > +#define ANDES_DCACHE_MISS 0x51 > > +#define ANDES_DCACHE_LOAD_ACCESS 0x61 > > +#define ANDES_DCACHE_LOAD_MISS 0x71 > > +#define ANDES_DCACHE_STORE_ACCESS 0x81 > > +#define ANDES_DCACHE_STORE_MISS 0x91 > > +#define ANDES_DCACHE_WB 0xA1 > > +#define ANDES_CYCLE_WAIT_ICACHE_FILL 0xB1 > > +#define ANDES_CYCLE_WAIT_DCACHE_FILL 0xC1 > > +#define ANDES_UNCACHED_IFETCH_FROM_BUS 0xD1 > > +#define ANDES_UNCACHED_LOAD_FROM_BUS 0xE1 > > +#define ANDES_CYCLE_WAIT_UNCACHED_IFETCH 0xF1 > > +#define ANDES_CYCLE_WAIT_UNCACHED_LOAD 0x101 > > +#define ANDES_MAIN_ITLB_ACCESS 0x111 > > +#define ANDES_MAIN_ITLB_MISS 0x121 > > +#define ANDES_MAIN_DTLB_ACCESS 0x131 > > +#define ANDES_MAIN_DTLB_MISS 0x141 > > +#define ANDES_CYCLE_WAIT_ITLB_FILL 0x151 > > +#define ANDES_PIPE_STALL_CYCLE_DTLB_MISS 0x161 > > +#define ANDES_HW_PREFETCH_BUS_ACCESS 0x171 > > + > > +/* Event selector for microarchitecture events */ > > +#define ANDES_MISPREDICT_CONDITION_BR 0x02 > > +#define ANDES_MISPREDICT_TAKE_CONDITION_BR 0x12 > > +#define ANDES_MISPREDICT_TARGET_RET_INST 0x22 > > + > > +#ifdef CONFIG_ANDES_HPM > > + > > +int andes_pmu_setup(void); > > + > > +#else > > + > > static inline int andes_pmu_setup(void) { return 0; } > > > > +#endif /* CONFIG_ANDES_HPM */ > > + > > #endif /* _ANDES_HPM_H_ */ > > -- > > 2.34.1 > > > > > -- > Regards, > Atish
diff --git a/include/sbi/sbi_ecall_interface.h b/include/sbi/sbi_ecall_interface.h index 1fe469e..89187e7 100644 --- a/include/sbi/sbi_ecall_interface.h +++ b/include/sbi/sbi_ecall_interface.h @@ -155,6 +155,11 @@ enum sbi_pmu_hw_cache_op_result_id { SBI_PMU_HW_CACHE_RESULT_MAX, }; +#define SBI_PMU_HW_CACHE_EVENT_IDX(id, op, res) \ + (SBI_PMU_EVENT_TYPE_HW_CACHE << SBI_PMU_EVENT_IDX_TYPE_OFFSET | \ + SBI_PMU_HW_CACHE_##id << 3 | SBI_PMU_HW_CACHE_OP_##op << 1 | \ + SBI_PMU_HW_CACHE_RESULT_##res) + /** * Special "firmware" events provided by the OpenSBI, even if the hardware * does not support performance events. These events are encoded as a raw diff --git a/platform/generic/Kconfig b/platform/generic/Kconfig index c9b6011..e652645 100644 --- a/platform/generic/Kconfig +++ b/platform/generic/Kconfig @@ -32,6 +32,7 @@ config PLATFORM_ALLWINNER_D1 config PLATFORM_ANDES_AE350 bool "Andes AE350 support" select SYS_ATCSMU + select ANDES_HPM select ANDES_PMU default n @@ -39,6 +40,7 @@ config PLATFORM_RENESAS_RZFIVE bool "Renesas RZ/Five support" select ANDES45_PMA select ANDES_SBI + select ANDES_HPM select ANDES_PMU default n diff --git a/platform/generic/andes/Kconfig b/platform/generic/andes/Kconfig index 3665b33..eb697a6 100644 --- a/platform/generic/andes/Kconfig +++ b/platform/generic/andes/Kconfig @@ -8,6 +8,13 @@ config ANDES_SBI bool "Andes SBI support" default n +config ANDES_HPM + bool "Andes HPM support" + default n + help + This provides default HPM event counter mappings + when a pmu node is missing. + config ANDES_PMU bool "Andes PMU extension (XAndesPMU) support" default n diff --git a/platform/generic/andes/andes_hpm.c b/platform/generic/andes/andes_hpm.c new file mode 100644 index 0000000..7fe5ac5 --- /dev/null +++ b/platform/generic/andes/andes_hpm.c @@ -0,0 +1,405 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * andes_hpm.c - Default event mappings and helper routine + * + * Copyright (c) 2023 Andes Technology Corporation + */ + +#include <andes/andes45.h> +#include <andes/andes_hpm.h> +#include <sbi/sbi_ecall_interface.h> +#include <sbi/sbi_pmu.h> +#include <sbi_utils/fdt/fdt_pmu.h> + +static const struct fdt_pmu_hw_event_select_map andes45_hw_evt_selects[] = { + /* Hardware general events (Type #0) */ + { + /* perf: cycles (eidx: 0x1) */ + .eidx = SBI_PMU_HW_CPU_CYCLES, + .select = ANDES_CYCLES + }, + { + /* perf: instructions (eidx: 0x2) */ + .eidx = SBI_PMU_HW_INSTRUCTIONS, + .select = ANDES_INSTRET + }, + { + /* perf: cache-references (eidx: 0x3) */ + .eidx = SBI_PMU_HW_CACHE_REFERENCES, + .select = ANDES_DCACHE_ACCESS + }, + { + /* perf: cache-misses (eidx: 0x4) */ + .eidx = SBI_PMU_HW_CACHE_MISSES, + .select = ANDES_DCACHE_MISS + }, + { + /* perf: branches (eidx: 0x5) */ + .eidx = SBI_PMU_HW_BRANCH_INSTRUCTIONS, + .select = ANDES_CONDITION_BR, + }, + { + /* perf: branch-misses (eidx: 0x6) */ + .eidx = SBI_PMU_HW_BRANCH_MISSES, + .select = ANDES_MISPREDICT_CONDITION_BR, + }, + /* Hardware cache events (Type #1) */ + { + /* perf: L1-dcache-loads (eidx: 0x10000) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), + .select = ANDES_DCACHE_LOAD_ACCESS + }, + { + /* perf: L1-dcache-loads-misses (eidx: 0x10001) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, MISS), + .select = ANDES_DCACHE_LOAD_MISS + }, + { + /* perf: L1-dcache-stores (eidx: 0x10002) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, ACCESS), + .select = ANDES_DCACHE_STORE_ACCESS + }, + { + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), + .select = ANDES_DCACHE_STORE_MISS + }, + { + /* perf: L1-icache-load (eidx: 0x10008) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), + .select = ANDES_ICACHE_ACCESS + }, + { + /* perf: L1-icache-load-misses (eidx: 0x10009) */ + .eidx = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), + .select = ANDES_ICACHE_MISS + }, +}; + +static const struct fdt_pmu_hw_event_counter_map andes45_hw_evt_counters[] = { + { + /* perf: cycles (eidx: 0x1) */ + .eidx_start = SBI_PMU_HW_CPU_CYCLES, + /* perf: branch-misses (eidx: 0x6) */ + .eidx_end = SBI_PMU_HW_BRANCH_MISSES, + .ctr_map = ANDES_MHPM_MAP, + }, + { + /* perf: L1-dcache-loads (eidx: 0x10000) */ + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, READ, ACCESS), + /* perf: L1-dcache-store-misses (eidx: 0x10003) */ + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1D, WRITE, MISS), + .ctr_map = ANDES_MHPM_MAP, + }, + { + /* perf: L1-icache-load (eidx: 0x10008) */ + .eidx_start = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, ACCESS), + /* perf: L1-icache-load-misses (eidx: 0x10009) */ + .eidx_end = SBI_PMU_HW_CACHE_EVENT_IDX(L1I, READ, MISS), + .ctr_map = ANDES_MHPM_MAP, + }, +}; + +static const struct fdt_pmu_raw_event_counter_map andes45_raw_evt_counters[] = { + { + .select = ANDES_CYCLES, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INSTRET, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_LOAD_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_STORE_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_ATOMIC_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_SYS_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_COMPUTE_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CONDITION_BR, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_TAKEN_CONDITION_BR, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_JAL_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_JALR_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_RET_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CONTROL_TRANS_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_EX9_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_MUL_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_DIV_REMAINDER_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_LOAD_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_STORE_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_ADD_SUB_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_MUL_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_FUSED_MULADD_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_FLOAT_DIV_SQUARE_ROOT_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_OTHER_FLOAT_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_INT_MUL_AND_SUB_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_RETIRED_OP, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_ILM_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DLM_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_ICACHE_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_ICACHE_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_LOAD_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_LOAD_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_STORE_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_STORE_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_DCACHE_WB, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CYCLE_WAIT_ICACHE_FILL, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CYCLE_WAIT_DCACHE_FILL, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_UNCACHED_IFETCH_FROM_BUS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_UNCACHED_LOAD_FROM_BUS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CYCLE_WAIT_UNCACHED_IFETCH, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CYCLE_WAIT_UNCACHED_LOAD, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MAIN_ITLB_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MAIN_ITLB_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MAIN_DTLB_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MAIN_DTLB_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_CYCLE_WAIT_ITLB_FILL, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_PIPE_STALL_CYCLE_DTLB_MISS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_HW_PREFETCH_BUS_ACCESS, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MISPREDICT_CONDITION_BR, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MISPREDICT_TAKE_CONDITION_BR, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, + { + .select = ANDES_MISPREDICT_TARGET_RET_INST, + .select_mask = ANDES_RAW_EVENT_MASK, + .ctr_map = ANDES_MHPM_MAP + }, +}; + +int andes_pmu_setup(void) +{ + int i, rc; + struct fdt_pmu_hw_event_select_map *event; + + /* + * At the moment, simply create mapping for any 45-series core + * based on marchid, we may check and differentiate the mapping + * by mimpid. + */ + if (!is_andes(45)) + return 0; + + for (i = 0; i < array_size(andes45_hw_evt_counters); i++) { + rc = sbi_pmu_add_hw_event_counter_map( + andes45_hw_evt_counters[i].eidx_start, + andes45_hw_evt_counters[i].eidx_end, + andes45_hw_evt_counters[i].ctr_map); + if (rc) + return rc; + } + + for (i = 0; i < array_size(andes45_hw_evt_selects); i++) { + event = &fdt_pmu_evt_select[hw_event_count]; + event->eidx = andes45_hw_evt_selects[i].eidx; + event->select = andes45_hw_evt_selects[i].select; + hw_event_count++; + } + + for (i = 0; i < array_size(andes45_raw_evt_counters); i++) { + rc = sbi_pmu_add_raw_event_counter_map( + andes45_raw_evt_counters[i].select, + andes45_raw_evt_counters[i].select_mask, + andes45_raw_evt_counters[i].ctr_map); + if (rc) + return rc; + } + + return 0; +} diff --git a/platform/generic/andes/objects.mk b/platform/generic/andes/objects.mk index 6a8c66c..57caaf6 100644 --- a/platform/generic/andes/objects.mk +++ b/platform/generic/andes/objects.mk @@ -8,3 +8,4 @@ platform-objs-$(CONFIG_PLATFORM_ANDES_AE350) += andes/ae350.o andes/sleep.o platform-objs-$(CONFIG_ANDES45_PMA) += andes/andes45-pma.o platform-objs-$(CONFIG_ANDES_SBI) += andes/andes_sbi.o platform-objs-$(CONFIG_ANDES_PMU) += andes/andes_pmu.o +platform-objs-$(CONFIG_ANDES_HPM) += andes/andes_hpm.o diff --git a/platform/generic/include/andes/andes_hpm.h b/platform/generic/include/andes/andes_hpm.h index b4d71b9..0ae391f 100644 --- a/platform/generic/include/andes/andes_hpm.h +++ b/platform/generic/include/andes/andes_hpm.h @@ -7,6 +7,75 @@ #ifndef _ANDES_HPM_H_ #define _ANDES_HPM_H_ +#define ANDES_MHPM_MAP 0x78 +#define ANDES_RAW_EVENT_MASK ~0ULL + +/* Event selector for instruction commit events */ +#define ANDES_CYCLES 0x10 +#define ANDES_INSTRET 0x20 +#define ANDES_INT_LOAD_INST 0x30 +#define ANDES_INT_STORE_INST 0x40 +#define ANDES_ATOMIC_INST 0x50 +#define ANDES_SYS_INST 0x60 +#define ANDES_INT_COMPUTE_INST 0x70 +#define ANDES_CONDITION_BR 0x80 +#define ANDES_TAKEN_CONDITION_BR 0x90 +#define ANDES_JAL_INST 0xA0 +#define ANDES_JALR_INST 0xB0 +#define ANDES_RET_INST 0xC0 +#define ANDES_CONTROL_TRANS_INST 0xD0 +#define ANDES_EX9_INST 0xE0 +#define ANDES_INT_MUL_INST 0xF0 +#define ANDES_INT_DIV_REMAINDER_INST 0x100 +#define ANDES_FLOAT_LOAD_INST 0x110 +#define ANDES_FLOAT_STORE_INST 0x120 +#define ANDES_FLOAT_ADD_SUB_INST 0x130 +#define ANDES_FLOAT_MUL_INST 0x140 +#define ANDES_FLOAT_FUSED_MULADD_INST 0x150 +#define ANDES_FLOAT_DIV_SQUARE_ROOT_INST 0x160 +#define ANDES_OTHER_FLOAT_INST 0x170 +#define ANDES_INT_MUL_AND_SUB_INST 0x180 +#define ANDES_RETIRED_OP 0x190 + +/* Event selector for memory system events */ +#define ANDES_ILM_ACCESS 0x01 +#define ANDES_DLM_ACCESS 0x11 +#define ANDES_ICACHE_ACCESS 0x21 +#define ANDES_ICACHE_MISS 0x31 +#define ANDES_DCACHE_ACCESS 0x41 +#define ANDES_DCACHE_MISS 0x51 +#define ANDES_DCACHE_LOAD_ACCESS 0x61 +#define ANDES_DCACHE_LOAD_MISS 0x71 +#define ANDES_DCACHE_STORE_ACCESS 0x81 +#define ANDES_DCACHE_STORE_MISS 0x91 +#define ANDES_DCACHE_WB 0xA1 +#define ANDES_CYCLE_WAIT_ICACHE_FILL 0xB1 +#define ANDES_CYCLE_WAIT_DCACHE_FILL 0xC1 +#define ANDES_UNCACHED_IFETCH_FROM_BUS 0xD1 +#define ANDES_UNCACHED_LOAD_FROM_BUS 0xE1 +#define ANDES_CYCLE_WAIT_UNCACHED_IFETCH 0xF1 +#define ANDES_CYCLE_WAIT_UNCACHED_LOAD 0x101 +#define ANDES_MAIN_ITLB_ACCESS 0x111 +#define ANDES_MAIN_ITLB_MISS 0x121 +#define ANDES_MAIN_DTLB_ACCESS 0x131 +#define ANDES_MAIN_DTLB_MISS 0x141 +#define ANDES_CYCLE_WAIT_ITLB_FILL 0x151 +#define ANDES_PIPE_STALL_CYCLE_DTLB_MISS 0x161 +#define ANDES_HW_PREFETCH_BUS_ACCESS 0x171 + +/* Event selector for microarchitecture events */ +#define ANDES_MISPREDICT_CONDITION_BR 0x02 +#define ANDES_MISPREDICT_TAKE_CONDITION_BR 0x12 +#define ANDES_MISPREDICT_TARGET_RET_INST 0x22 + +#ifdef CONFIG_ANDES_HPM + +int andes_pmu_setup(void); + +#else + static inline int andes_pmu_setup(void) { return 0; } +#endif /* CONFIG_ANDES_HPM */ + #endif /* _ANDES_HPM_H_ */