Unverified Commit e8c68abb authored by Palmer Dabbelt's avatar Palmer Dabbelt
Browse files

riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores

The PMU on T-Head C9xx cores is quite similar to the SSCOFPMF extension
but not completely identical, so this series adds a T-Head PMU errata
that handlen the differences.

* 'riscv-pmu' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/palmer/linux:
  drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores
  RISC-V: Cache SBI vendor values
parents d233ab3c 65e9fb08
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -66,4 +66,17 @@ config ERRATA_THEAD_CMO

	  If you don't know what to do here, say "Y".

config ERRATA_THEAD_PMU
	bool "Apply T-Head PMU errata"
	depends on ERRATA_THEAD && RISCV_PMU_SBI
	default y
	help
	  The T-Head C9xx cores implement a PMU overflow extension very
	  similar to the core SSCOFPMF extension.

	  This will apply the overflow errata to handle the non-standard
	  behaviour via the regular SBI PMU driver and interface.

	  If you don't know what to do here, say "Y".

endmenu # "CPU errata selection"
+19 −0
Original line number Diff line number Diff line
@@ -47,6 +47,22 @@ static bool errata_probe_cmo(unsigned int stage,
	return true;
}

static bool errata_probe_pmu(unsigned int stage,
			     unsigned long arch_id, unsigned long impid)
{
	if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU))
		return false;

	/* target-c9xx cores report arch_id and impid as 0 */
	if (arch_id != 0 || impid != 0)
		return false;

	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
		return false;

	return true;
}

static u32 thead_errata_probe(unsigned int stage,
			      unsigned long archid, unsigned long impid)
{
@@ -58,6 +74,9 @@ static u32 thead_errata_probe(unsigned int stage,
	if (errata_probe_cmo(stage, archid, impid))
		cpu_req_errata |= BIT(ERRATA_THEAD_CMO);

	if (errata_probe_pmu(stage, archid, impid))
		cpu_req_errata |= BIT(ERRATA_THEAD_PMU);

	return cpu_req_errata;
}

+15 −1
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#define ASM_ERRATA_LIST_H

#include <asm/alternative.h>
#include <asm/csr.h>
#include <asm/vendorid_list.h>

#ifdef CONFIG_ERRATA_SIFIVE
@@ -17,7 +18,8 @@
#ifdef CONFIG_ERRATA_THEAD
#define	ERRATA_THEAD_PBMT 0
#define	ERRATA_THEAD_CMO 1
#define	ERRATA_THEAD_NUMBER 2
#define	ERRATA_THEAD_PMU 2
#define	ERRATA_THEAD_NUMBER 3
#endif

#define	CPUFEATURE_SVPBMT 0
@@ -142,6 +144,18 @@ asm volatile(ALTERNATIVE_2( \
	    "r"((unsigned long)(_start) + (_size))			\
	: "a0")

#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
+5 −0
Original line number Diff line number Diff line
@@ -327,4 +327,9 @@ int sbi_err_map_linux_errno(int err);
static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; }
static inline void sbi_init(void) {}
#endif /* CONFIG_RISCV_SBI */

unsigned long riscv_cached_mvendorid(unsigned int cpu_id);
unsigned long riscv_cached_marchid(unsigned int cpu_id);
unsigned long riscv_cached_mimpid(unsigned int cpu_id);

#endif /* _ASM_RISCV_SBI_H */
+27 −3
Original line number Diff line number Diff line
@@ -70,8 +70,6 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
	return -1;
}

#ifdef CONFIG_PROC_FS

struct riscv_cpuinfo {
	unsigned long mvendorid;
	unsigned long marchid;
@@ -79,6 +77,30 @@ struct riscv_cpuinfo {
};
static DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);

unsigned long riscv_cached_mvendorid(unsigned int cpu_id)
{
	struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);

	return ci->mvendorid;
}
EXPORT_SYMBOL(riscv_cached_mvendorid);

unsigned long riscv_cached_marchid(unsigned int cpu_id)
{
	struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);

	return ci->marchid;
}
EXPORT_SYMBOL(riscv_cached_marchid);

unsigned long riscv_cached_mimpid(unsigned int cpu_id)
{
	struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id);

	return ci->mimpid;
}
EXPORT_SYMBOL(riscv_cached_mimpid);

static int riscv_cpuinfo_starting(unsigned int cpu)
{
	struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo);
@@ -113,7 +135,9 @@ static int __init riscv_cpuinfo_init(void)

	return 0;
}
device_initcall(riscv_cpuinfo_init);
arch_initcall(riscv_cpuinfo_init);

#ifdef CONFIG_PROC_FS

#define __RISCV_ISA_EXT_DATA(UPROP, EXTID) \
	{							\
Loading