mirror of
https://github.com/torvalds/linux.git
synced 2024-12-11 21:52:04 +00:00
perf: RISC-V: Introduce Andes PMU to support perf event sampling
Assign riscv_pmu_irq_num the value of (256 + 18) for the custome PMU and add SSCOUNTOVF and SIP alternatives to ALT_SBI_PMU_OVERFLOW() and ALT_SBI_PMU_OVF_CLEAR_PENDING() macros, respectively. To make use of Andes PMU extension, "xandespmu" needs to be appended to the riscv,isa-extensions for each cpu node in device-tree, and make sure CONFIG_ANDES_CUSTOM_PMU is enabled. Signed-off-by: Yu Chien Peter Lin <peterlin@andestech.com> Reviewed-by: Charles Ci-Jyun Wu <dminus@andestech.com> Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com> Co-developed-by: Locus Wei-Han Chen <locus84@andestech.com> Signed-off-by: Locus Wei-Han Chen <locus84@andestech.com> Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Link: https://lore.kernel.org/r/20240222083946.3977135-8-peterlin@andestech.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
parent
ea0e0178e1
commit
bc969d6cc9
@ -112,15 +112,6 @@ asm volatile(ALTERNATIVE( \
|
||||
#define THEAD_C9XX_RV_IRQ_PMU 17
|
||||
#define THEAD_C9XX_CSR_SCOUNTEROF 0x5c5
|
||||
|
||||
#define ALT_SBI_PMU_OVERFLOW(__ovl) \
|
||||
asm volatile(ALTERNATIVE( \
|
||||
"csrr %0, " __stringify(CSR_SSCOUNTOVF), \
|
||||
"csrr %0, " __stringify(THEAD_C9XX_CSR_SCOUNTEROF), \
|
||||
THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \
|
||||
CONFIG_ERRATA_THEAD_PMU) \
|
||||
: "=r" (__ovl) : \
|
||||
: "memory")
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
@ -80,6 +80,7 @@
|
||||
#define RISCV_ISA_EXT_ZFA 71
|
||||
#define RISCV_ISA_EXT_ZTSO 72
|
||||
#define RISCV_ISA_EXT_ZACAS 73
|
||||
#define RISCV_ISA_EXT_XANDESPMU 74
|
||||
|
||||
#define RISCV_ISA_EXT_MAX 128
|
||||
#define RISCV_ISA_EXT_INVALID U32_MAX
|
||||
|
@ -307,6 +307,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
|
||||
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
|
||||
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
|
||||
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
|
||||
__RISCV_ISA_EXT_DATA(xandespmu, RISCV_ISA_EXT_XANDESPMU),
|
||||
};
|
||||
|
||||
const size_t riscv_isa_ext_count = ARRAY_SIZE(riscv_isa_ext);
|
||||
|
@ -86,6 +86,20 @@ config RISCV_PMU_SBI
|
||||
full perf feature support i.e. counter overflow, privilege mode
|
||||
filtering, counter configuration.
|
||||
|
||||
config ANDES_CUSTOM_PMU
|
||||
bool "Andes custom PMU support"
|
||||
depends on ARCH_RENESAS && RISCV_ALTERNATIVE && RISCV_PMU_SBI
|
||||
default y
|
||||
help
|
||||
The Andes cores implement the PMU overflow extension very
|
||||
similar to the standard Sscofpmf and Smcntrpmf extension.
|
||||
|
||||
This will patch the overflow and pending CSRs and handle the
|
||||
non-standard behaviour via the regular SBI PMU driver and
|
||||
interface.
|
||||
|
||||
If you don't know what to do here, say "Y".
|
||||
|
||||
config ARM_PMU_ACPI
|
||||
depends on ARM_PMU && ACPI
|
||||
def_bool y
|
||||
|
@ -19,11 +19,33 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/sched/clock.h>
|
||||
#include <linux/soc/andes/irq.h>
|
||||
|
||||
#include <asm/errata_list.h>
|
||||
#include <asm/sbi.h>
|
||||
#include <asm/cpufeature.h>
|
||||
|
||||
#define ALT_SBI_PMU_OVERFLOW(__ovl) \
|
||||
asm volatile(ALTERNATIVE_2( \
|
||||
"csrr %0, " __stringify(CSR_SSCOUNTOVF), \
|
||||
"csrr %0, " __stringify(THEAD_C9XX_CSR_SCOUNTEROF), \
|
||||
THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \
|
||||
CONFIG_ERRATA_THEAD_PMU, \
|
||||
"csrr %0, " __stringify(ANDES_CSR_SCOUNTEROF), \
|
||||
0, RISCV_ISA_EXT_XANDESPMU, \
|
||||
CONFIG_ANDES_CUSTOM_PMU) \
|
||||
: "=r" (__ovl) : \
|
||||
: "memory")
|
||||
|
||||
#define ALT_SBI_PMU_OVF_CLEAR_PENDING(__irq_mask) \
|
||||
asm volatile(ALTERNATIVE( \
|
||||
"csrc " __stringify(CSR_IP) ", %0\n\t", \
|
||||
"csrc " __stringify(ANDES_CSR_SLIP) ", %0\n\t", \
|
||||
0, RISCV_ISA_EXT_XANDESPMU, \
|
||||
CONFIG_ANDES_CUSTOM_PMU) \
|
||||
: : "r"(__irq_mask) \
|
||||
: "memory")
|
||||
|
||||
#define SYSCTL_NO_USER_ACCESS 0
|
||||
#define SYSCTL_USER_ACCESS 1
|
||||
#define SYSCTL_LEGACY 2
|
||||
@ -61,6 +83,7 @@ static int sysctl_perf_user_access __read_mostly = SYSCTL_USER_ACCESS;
|
||||
static union sbi_pmu_ctr_info *pmu_ctr_list;
|
||||
static bool riscv_pmu_use_irq;
|
||||
static unsigned int riscv_pmu_irq_num;
|
||||
static unsigned int riscv_pmu_irq_mask;
|
||||
static unsigned int riscv_pmu_irq;
|
||||
|
||||
/* Cache the available counters in a bitmask */
|
||||
@ -694,7 +717,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
|
||||
|
||||
event = cpu_hw_evt->events[fidx];
|
||||
if (!event) {
|
||||
csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
|
||||
ALT_SBI_PMU_OVF_CLEAR_PENDING(riscv_pmu_irq_mask);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -708,7 +731,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
|
||||
* Overflow interrupt pending bit should only be cleared after stopping
|
||||
* all the counters to avoid any race condition.
|
||||
*/
|
||||
csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
|
||||
ALT_SBI_PMU_OVF_CLEAR_PENDING(riscv_pmu_irq_mask);
|
||||
|
||||
/* No overflow bit is set */
|
||||
if (!overflow)
|
||||
@ -780,7 +803,7 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
|
||||
|
||||
if (riscv_pmu_use_irq) {
|
||||
cpu_hw_evt->irq = riscv_pmu_irq;
|
||||
csr_clear(CSR_IP, BIT(riscv_pmu_irq_num));
|
||||
ALT_SBI_PMU_OVF_CLEAR_PENDING(riscv_pmu_irq_mask);
|
||||
enable_percpu_irq(riscv_pmu_irq, IRQ_TYPE_NONE);
|
||||
}
|
||||
|
||||
@ -814,8 +837,14 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
|
||||
riscv_cached_mimpid(0) == 0) {
|
||||
riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU;
|
||||
riscv_pmu_use_irq = true;
|
||||
} else if (riscv_isa_extension_available(NULL, XANDESPMU) &&
|
||||
IS_ENABLED(CONFIG_ANDES_CUSTOM_PMU)) {
|
||||
riscv_pmu_irq_num = ANDES_SLI_CAUSE_BASE + ANDES_RV_IRQ_PMOVI;
|
||||
riscv_pmu_use_irq = true;
|
||||
}
|
||||
|
||||
riscv_pmu_irq_mask = BIT(riscv_pmu_irq_num % BITS_PER_LONG);
|
||||
|
||||
if (!riscv_pmu_use_irq)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user