[PATCH 3/6] platform: andes: Add Andes custom PMU support
Yu-Chien Peter Lin
peterlin at andestech.com
Wed Sep 20 22:40:57 PDT 2023
Hi Prabhakar,
On Mon, Sep 18, 2023 at 03:03:00PM +0100, Lad, Prabhakar wrote:
> Hi Lin-san,
>
> Thank you for the patch.
>
> On Wed, Sep 6, 2023 at 10:43 AM Yu Chien Peter Lin
> <peterlin at andestech.com> wrote:
> >
> > Before the ratification of Sscofpmf, the Andes PMU extension was
> > designed to support the sampling and filtering of hardware performance
> > counters, compatible with the current SBI PMU extension and Linux perf
> > driver.
> >
> > This patch implements the PMU extension platform callback and PMU device
> > callbacks to update the corresponding custom CSRs.
> >
> > Signed-off-by: Yu Chien Peter Lin <peterlin at andestech.com>
> > Reviewed-by: Leo Yu-Chi Liang <ycliang at andestech.com>
> > ---
> > platform/generic/andes/Kconfig | 4 +
> > platform/generic/andes/andes_pmu.c | 85 ++++++++++++++++++++++
> > platform/generic/andes/objects.mk | 1 +
> > platform/generic/include/andes/andes_pmu.h | 12 +++
> > 4 files changed, 102 insertions(+)
> > create mode 100644 platform/generic/andes/andes_pmu.c
> > create mode 100644 platform/generic/include/andes/andes_pmu.h
> >
> > diff --git a/platform/generic/andes/Kconfig b/platform/generic/andes/Kconfig
> > index a91fb9c..056327b 100644
> > --- a/platform/generic/andes/Kconfig
> > +++ b/platform/generic/andes/Kconfig
> > @@ -7,3 +7,7 @@ config ANDES45_PMA
> > config ANDES_SBI
> > bool "Andes SBI support"
> > default n
> > +
> > +config ANDES_PMU
> > + bool "Andes PMU support"
> > + default n
> > diff --git a/platform/generic/andes/andes_pmu.c b/platform/generic/andes/andes_pmu.c
> > new file mode 100644
> > index 0000000..d2574c7
> > --- /dev/null
> > +++ b/platform/generic/andes/andes_pmu.c
> > @@ -0,0 +1,85 @@
> > +// SPDX-License-Identifier: BSD-2-Clause
> > +/*
> > + * Copyright (C) 2022 Andes Technology Corporation
> 2023?
OK, will update.
> > + *
> > + */
> > +#include <andes/andes45.h>
> > +#include <andes/andes_pmu.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi/sbi_pmu.h>
> > +#include <sbi/sbi_scratch.h>
> > +
> > +static void andes_hw_counter_enable_irq(uint32_t ctr_idx)
> > +{
> > + unsigned long mip_val;
> > +
> > + if (ctr_idx >= SBI_PMU_HW_CTR_MAX)
> > + return;
> > +
> > + mip_val = csr_read(CSR_MIP);
> > + if (!(mip_val & MIP_PMOVI))
> > + csr_clear(CSR_MCOUNTEROVF, BIT(ctr_idx));
> > +
> > + csr_set(CSR_MCOUNTERINTEN, BIT(ctr_idx));
> > +}
> > +
> > +static void andes_hw_counter_disable_irq(uint32_t ctr_idx)
> > +{
> Any reason why we dont check for ctr_idx >= SBI_PMU_HW_CTR_MAX?
Its function caller [1] has done the check.
> > + csr_clear(CSR_MCOUNTERINTEN, BIT(ctr_idx));
> > +}
> > +
> > +static void andes_hw_counter_filter_mode(unsigned long flags, int ctr_idx)
> > +{
> > + if (!flags) {
> > + csr_write(CSR_MCOUNTERMASK_S, 0);
> > + csr_write(CSR_MCOUNTERMASK_U, 0);
> > + }
> > + if (flags & SBI_PMU_CFG_FLAG_SET_UINH) {
> > + csr_clear(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
> > + csr_set(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
> > + }
> > + if (flags & SBI_PMU_CFG_FLAG_SET_SINH) {
> > + csr_set(CSR_MCOUNTERMASK_S, BIT(ctr_idx));
> > + csr_clear(CSR_MCOUNTERMASK_U, BIT(ctr_idx));
> > + }
> > +}
> > +
> > +static struct sbi_pmu_device andes_pmu = {
> > + .name = "andes_pmu",
> > + .hw_counter_enable_irq = andes_hw_counter_enable_irq,
> > + .hw_counter_disable_irq = andes_hw_counter_disable_irq,
> > + /*
> > + * In andes_pmu_extensions_init(), we set mslideleg[18] for each
> > + * hart instead of mideleg, so leave hw_counter_irq_bit() hook
> > + * unimplemented.
> > + */
> > + .hw_counter_irq_bit = NULL,
> > + .hw_counter_filter_mode = andes_hw_counter_filter_mode
> > +};
> > +
> > +int andes_pmu_extensions_init(const struct fdt_match *match,
> > + struct sbi_hart_features *hfeatures)
> > +{
> > + if (andes_pmu()) {
> You can reverse the check here and return early?
Sure, will do.
> > + /*
> > + * It is not rational for a hardware to support
> > + * both Andes PMU and standard Sscofpmf, as they
> > + * serve the same purpose.
> > + */
> > + if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
> > + SBI_HART_EXT_SSCOFPMF))
> > + ebreak();
> > +
> > + /* Machine counter write enable */
> > + csr_write(CSR_MCOUNTERWEN, 0xfffffffd);
> > + /* disable HPM counter in M-mode */
> > + csr_write(CSR_MCOUNTERMASK_M, 0xfffffffd);
> > + /* delegate S-mode local interrupt to S-mode */
> > + csr_write(CSR_MSLIDELEG, MIP_PMOVI);
> > +
> > + sbi_pmu_set_device(&andes_pmu);
> In my opinion we might want to append the PMU node to DT here
Sure, I will add fdt fixup so RZ/Five users won't need to manually
append the PMU node.
> and pass that DT fragment to the higher stack instead of adding it in Linux.
The PMU node is not visible to S-mode SW (U-Boot proper or Linux) since
it is only used to initialize the event counter mappings and erased in
the generic_final_init() [2].
Thanks,
Peter Lin
[1] https://github.com/riscv-software-src/opensbi/blob/v1.3.1/lib/sbi/sbi_pmu.c#L583
[2] https://github.com/riscv-software-src/opensbi/blob/master/platform/generic/platform.c#L172
> Cheers,
> Prabhakar
More information about the opensbi
mailing list