linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/2] riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores
@ 2022-10-04 20:37 Heiko Stuebner
  2022-10-04 20:37 ` [PATCH 1/2] RISC-V: Cache SBI vendor values Heiko Stuebner
  2022-10-04 20:37 ` [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
  0 siblings, 2 replies; 7+ messages in thread
From: Heiko Stuebner @ 2022-10-04 20:37 UTC (permalink / raw)
  To: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou
  Cc: linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel,
	Heiko Stuebner

The PMU on T-Head C9xx cores is quite similar to the SSCOFPMF extension
but not completely identical, so this series


changes in v4:
- add new patch to cache sbi mvendor, march and mimp-ids (Atish)
- errata dependencies in one line (Conor)
- make driver detection conditional on CONFIG_ERRATA_THEAD_PMU too (Atish)

changes in v3:
- improve commit message (Atish, Conor)
- IS_ENABLED and BIT() in errata probe (Conor)

The change depends on my cpufeature/t-head errata probe cleanup series [1].


changes in v2:
- use alternatives for the CSR access
- make the irq num selection a bit nicer

There is of course a matching opensbi-part whose most recent implementation
can be found on [0].


[0] https://patchwork.ozlabs.org/project/opensbi/cover/20221004164227.1381825-1-heiko@sntech.de
[1] https://lore.kernel.org/all/20220905111027.2463297-1-heiko@sntech.de/

Heiko Stuebner (2):
  RISC-V: Cache SBI vendor values
  drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head
    C9xx cores

 arch/riscv/Kconfig.erratas           | 13 +++++++++++
 arch/riscv/errata/thead/errata.c     | 18 +++++++++++++++
 arch/riscv/include/asm/errata_list.h | 16 +++++++++++++-
 arch/riscv/kernel/sbi.c              | 21 +++++++++++++++---
 drivers/perf/riscv_pmu_sbi.c         | 33 +++++++++++++++++++---------
 5 files changed, 87 insertions(+), 14 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] RISC-V: Cache SBI vendor values
  2022-10-04 20:37 [PATCH v4 0/2] riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
@ 2022-10-04 20:37 ` Heiko Stuebner
  2022-10-05 17:07   ` Andrew Jones
  2022-10-04 20:37 ` [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
  1 sibling, 1 reply; 7+ messages in thread
From: Heiko Stuebner @ 2022-10-04 20:37 UTC (permalink / raw)
  To: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou
  Cc: linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel,
	Heiko Stuebner

sbi_get_mvendorid(), sbi_get_marchid() and sbi_get_mimpid() might get
called multiple times, though the values of these CSRs should not change
during the runtime of a specific machine.

So cache the values in the functions and prevent multiple ecalls
to read these values.

Suggested-by: Atish Patra <atishp@atishpatra.org>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/riscv/kernel/sbi.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index 775d3322b422..5be8f90f325e 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -625,17 +625,32 @@ static inline long sbi_get_firmware_version(void)
 
 long sbi_get_mvendorid(void)
 {
-	return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
+	static long id = -1;
+
+	if (id < 0)
+		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
+
+	return id;
 }
 
 long sbi_get_marchid(void)
 {
-	return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
+	static long id = -1;
+
+	if (id < 0)
+		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
+
+	return id;
 }
 
 long sbi_get_mimpid(void)
 {
-	return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
+	static long id = -1;
+
+	if (id < 0)
+		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
+
+	return id;
 }
 
 static void sbi_send_cpumask_ipi(const struct cpumask *target)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores
  2022-10-04 20:37 [PATCH v4 0/2] riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
  2022-10-04 20:37 ` [PATCH 1/2] RISC-V: Cache SBI vendor values Heiko Stuebner
@ 2022-10-04 20:37 ` Heiko Stuebner
  2022-10-05 17:38   ` Andrew Jones
  2022-10-06 19:20   ` Conor Dooley
  1 sibling, 2 replies; 7+ messages in thread
From: Heiko Stuebner @ 2022-10-04 20:37 UTC (permalink / raw)
  To: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou
  Cc: linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel,
	Heiko Stuebner

With the T-HEAD C9XX cores being designed before or during the ratification
to the SSCOFPMF extension, it implements functionality very similar but
not equal to it.

It implements overflow handling and also some privilege-mode filtering.
While SSCOFPMF supports this for all modes, the C9XX only implements the
filtering for M-mode and S-mode but not user-mode.

So add some adaptions to allow the C9XX to still handle
its PMU through the regular SBI PMU interface instead of defining new
interfaces or drivers.

To work properly, this requires a matching change in SBI, though the actual
interface between kernel and SBI does not change.

The main differences are a the overflow CSR and irq number.

As the reading of the overflow-csr is in the hot-path during irq handling,
use an errata and alternatives to not introduce new conditionals there.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 arch/riscv/Kconfig.erratas           | 13 +++++++++++
 arch/riscv/errata/thead/errata.c     | 18 +++++++++++++++
 arch/riscv/include/asm/errata_list.h | 16 +++++++++++++-
 drivers/perf/riscv_pmu_sbi.c         | 33 +++++++++++++++++++---------
 4 files changed, 69 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
index f3623df23b5f..69621ae6d647 100644
--- a/arch/riscv/Kconfig.erratas
+++ b/arch/riscv/Kconfig.erratas
@@ -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"
diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
index 21546937db39..67fa078f303f 100644
--- a/arch/riscv/errata/thead/errata.c
+++ b/arch/riscv/errata/thead/errata.c
@@ -47,6 +47,21 @@ 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;
+
+	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 +73,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;
 }
 
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index 19a771085781..4180312d2a70 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -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
diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index 8de4ca2fef21..ec0972c7c562 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/cpu_pm.h>
 
+#include <asm/errata_list.h>
 #include <asm/sbi.h>
 #include <asm/hwcap.h>
 
@@ -46,6 +47,8 @@ static const struct attribute_group *riscv_pmu_attr_groups[] = {
  * per_cpu in case of harts with different pmu counters
  */
 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;
 
 struct sbi_pmu_event_data {
@@ -575,7 +578,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 	fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
 	event = cpu_hw_evt->events[fidx];
 	if (!event) {
-		csr_clear(CSR_SIP, SIP_LCOFIP);
+		csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
 		return IRQ_NONE;
 	}
 
@@ -583,13 +586,13 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
 	pmu_sbi_stop_hw_ctrs(pmu);
 
 	/* Overflow status register should only be read after counter are stopped */
-	overflow = csr_read(CSR_SSCOUNTOVF);
+	ALT_SBI_PMU_OVERFLOW(overflow);
 
 	/*
 	 * Overflow interrupt pending bit should only be cleared after stopping
 	 * all the counters to avoid any race condition.
 	 */
-	csr_clear(CSR_SIP, SIP_LCOFIP);
+	csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
 
 	/* No overflow bit is set */
 	if (!overflow)
@@ -651,10 +654,10 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
 	/* Stop all the counters so that they can be enabled from perf */
 	pmu_sbi_stop_all(pmu);
 
-	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
+	if (riscv_pmu_use_irq) {
 		cpu_hw_evt->irq = riscv_pmu_irq;
-		csr_clear(CSR_IP, BIT(RV_IRQ_PMU));
-		csr_set(CSR_IE, BIT(RV_IRQ_PMU));
+		csr_clear(CSR_IP, BIT(riscv_pmu_irq_num));
+		csr_set(CSR_IE, BIT(riscv_pmu_irq_num));
 		enable_percpu_irq(riscv_pmu_irq, IRQ_TYPE_NONE);
 	}
 
@@ -663,9 +666,9 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
 
 static int pmu_sbi_dying_cpu(unsigned int cpu, struct hlist_node *node)
 {
-	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
+	if (riscv_pmu_use_irq) {
 		disable_percpu_irq(riscv_pmu_irq);
-		csr_clear(CSR_IE, BIT(RV_IRQ_PMU));
+		csr_clear(CSR_IE, BIT(riscv_pmu_irq_num));
 	}
 
 	/* Disable all counters access for user mode now */
@@ -681,7 +684,17 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
 	struct device_node *cpu, *child;
 	struct irq_domain *domain = NULL;
 
-	if (!riscv_isa_extension_available(NULL, SSCOFPMF))
+	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
+		riscv_pmu_irq_num = RV_IRQ_PMU;
+		riscv_pmu_use_irq = true;
+	} else if (IS_ENABLED(CONFIG_ERRATA_THEAD_PMU) &&
+		   sbi_get_mvendorid() == THEAD_VENDOR_ID &&
+		   sbi_get_marchid() == 0 && sbi_get_mimpid() == 0) {
+		riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU;
+		riscv_pmu_use_irq = true;
+	}
+
+	if (!riscv_pmu_use_irq)
 		return -EOPNOTSUPP;
 
 	for_each_of_cpu_node(cpu) {
@@ -703,7 +716,7 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
 		return -ENODEV;
 	}
 
-	riscv_pmu_irq = irq_create_mapping(domain, RV_IRQ_PMU);
+	riscv_pmu_irq = irq_create_mapping(domain, riscv_pmu_irq_num);
 	if (!riscv_pmu_irq) {
 		pr_err("Failed to map PMU interrupt for node\n");
 		return -ENODEV;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] RISC-V: Cache SBI vendor values
  2022-10-04 20:37 ` [PATCH 1/2] RISC-V: Cache SBI vendor values Heiko Stuebner
@ 2022-10-05 17:07   ` Andrew Jones
  2022-10-05 23:07     ` Heiko Stuebner
  0 siblings, 1 reply; 7+ messages in thread
From: Andrew Jones @ 2022-10-05 17:07 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou,
	linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel

On Tue, Oct 04, 2022 at 10:37:23PM +0200, Heiko Stuebner wrote:
> sbi_get_mvendorid(), sbi_get_marchid() and sbi_get_mimpid() might get
> called multiple times, though the values of these CSRs should not change
> during the runtime of a specific machine.
> 
> So cache the values in the functions and prevent multiple ecalls
> to read these values.
> 
> Suggested-by: Atish Patra <atishp@atishpatra.org>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/riscv/kernel/sbi.c | 21 ++++++++++++++++++---
>  1 file changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index 775d3322b422..5be8f90f325e 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -625,17 +625,32 @@ static inline long sbi_get_firmware_version(void)
>  
>  long sbi_get_mvendorid(void)
>  {
> -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
> +	static long id = -1;
> +
> +	if (id < 0)
> +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
> +
> +	return id;
>  }
>  
>  long sbi_get_marchid(void)
>  {
> -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
> +	static long id = -1;
> +
> +	if (id < 0)
> +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);

The marchid register will be negative for commercial architecture ids
because the MSB must be set.

> +
> +	return id;
>  }
>  
>  long sbi_get_mimpid(void)
>  {
> -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
> +	static long id = -1;
> +
> +	if (id < 0)
> +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);

The spec says this register is "left to the provider" and may be
left-justified. I don't think we can be sure the MSB will not be set.

For both cases I guess we need an extra bit to determine if we've cached
or not

  static bool cached;
  static long id;

  if (!cached) {
     id = ecall();
     cached = true;
  }

  return id;

> +
> +	return id;
>  }
>  
>  static void sbi_send_cpumask_ipi(const struct cpumask *target)
> -- 
> 2.35.1
> 

Thanks,
drew

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores
  2022-10-04 20:37 ` [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
@ 2022-10-05 17:38   ` Andrew Jones
  2022-10-06 19:20   ` Conor Dooley
  1 sibling, 0 replies; 7+ messages in thread
From: Andrew Jones @ 2022-10-05 17:38 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou,
	linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel

On Tue, Oct 04, 2022 at 10:37:24PM +0200, Heiko Stuebner wrote:
> With the T-HEAD C9XX cores being designed before or during the ratification
> to the SSCOFPMF extension, it implements functionality very similar but
> not equal to it.
> 
> It implements overflow handling and also some privilege-mode filtering.
> While SSCOFPMF supports this for all modes, the C9XX only implements the
> filtering for M-mode and S-mode but not user-mode.
> 
> So add some adaptions to allow the C9XX to still handle
> its PMU through the regular SBI PMU interface instead of defining new
> interfaces or drivers.
> 
> To work properly, this requires a matching change in SBI, though the actual
> interface between kernel and SBI does not change.
> 
> The main differences are a the overflow CSR and irq number.
> 
> As the reading of the overflow-csr is in the hot-path during irq handling,
> use an errata and alternatives to not introduce new conditionals there.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/riscv/Kconfig.erratas           | 13 +++++++++++
>  arch/riscv/errata/thead/errata.c     | 18 +++++++++++++++
>  arch/riscv/include/asm/errata_list.h | 16 +++++++++++++-
>  drivers/perf/riscv_pmu_sbi.c         | 33 +++++++++++++++++++---------
>  4 files changed, 69 insertions(+), 11 deletions(-)

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] RISC-V: Cache SBI vendor values
  2022-10-05 17:07   ` Andrew Jones
@ 2022-10-05 23:07     ` Heiko Stuebner
  0 siblings, 0 replies; 7+ messages in thread
From: Heiko Stuebner @ 2022-10-05 23:07 UTC (permalink / raw)
  To: Andrew Jones
  Cc: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou,
	linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel

Hi Drew,

Am Mittwoch, 5. Oktober 2022, 19:07:02 CEST schrieb Andrew Jones:
> On Tue, Oct 04, 2022 at 10:37:23PM +0200, Heiko Stuebner wrote:
> > sbi_get_mvendorid(), sbi_get_marchid() and sbi_get_mimpid() might get
> > called multiple times, though the values of these CSRs should not change
> > during the runtime of a specific machine.
> > 
> > So cache the values in the functions and prevent multiple ecalls
> > to read these values.
> > 
> > Suggested-by: Atish Patra <atishp@atishpatra.org>
> > Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> > ---
> >  arch/riscv/kernel/sbi.c | 21 ++++++++++++++++++---
> >  1 file changed, 18 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> > index 775d3322b422..5be8f90f325e 100644
> > --- a/arch/riscv/kernel/sbi.c
> > +++ b/arch/riscv/kernel/sbi.c
> > @@ -625,17 +625,32 @@ static inline long sbi_get_firmware_version(void)
> >  
> >  long sbi_get_mvendorid(void)
> >  {
> > -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
> > +	static long id = -1;
> > +
> > +	if (id < 0)
> > +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
> > +
> > +	return id;
> >  }
> >  
> >  long sbi_get_marchid(void)
> >  {
> > -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
> > +	static long id = -1;
> > +
> > +	if (id < 0)
> > +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
> 
> The marchid register will be negative for commercial architecture ids
> because the MSB must be set.
> 
> > +
> > +	return id;
> >  }
> >  
> >  long sbi_get_mimpid(void)
> >  {
> > -	return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
> > +	static long id = -1;
> > +
> > +	if (id < 0)
> > +		id = __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
> 
> The spec says this register is "left to the provider" and may be
> left-justified. I don't think we can be sure the MSB will not be set.
> 
> For both cases I guess we need an extra bit to determine if we've cached
> or not
> 
>   static bool cached;
>   static long id;
> 
>   if (!cached) {
>      id = ecall();
>      cached = true;
>   }
> 
>   return id;
> 

thanks for noticing this issue. I did look into the mvendor
csr definition, but then wrongly assumed the other 2 being
similar.

I think for consistency it makes sense to have that extra bit
in all 3 functions too.


Thanks
Heiko

> > +
> > +	return id;
> >  }
> >  
> >  static void sbi_send_cpumask_ipi(const struct cpumask *target)
> 
> Thanks,
> drew
> 





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores
  2022-10-04 20:37 ` [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
  2022-10-05 17:38   ` Andrew Jones
@ 2022-10-06 19:20   ` Conor Dooley
  1 sibling, 0 replies; 7+ messages in thread
From: Conor Dooley @ 2022-10-06 19:20 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: atishp, anup, will, mark.rutland, paul.walmsley, palmer, aou,
	linux-riscv, linux-kernel, Conor.Dooley, cmuellner, samuel

On Tue, Oct 04, 2022 at 10:37:24PM +0200, Heiko Stuebner wrote:
> With the T-HEAD C9XX cores being designed before or during the ratification
> to the SSCOFPMF extension, it implements functionality very similar but
> not equal to it.
> 
> It implements overflow handling and also some privilege-mode filtering.
> While SSCOFPMF supports this for all modes, the C9XX only implements the
> filtering for M-mode and S-mode but not user-mode.
> 
> So add some adaptions to allow the C9XX to still handle
> its PMU through the regular SBI PMU interface instead of defining new
> interfaces or drivers.
> 
> To work properly, this requires a matching change in SBI, though the actual
> interface between kernel and SBI does not change.
> 
> The main differences are a the overflow CSR and irq number.
> 
> As the reading of the overflow-csr is in the hot-path during irq handling,
> use an errata and alternatives to not introduce new conditionals there.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  arch/riscv/Kconfig.erratas           | 13 +++++++++++
>  arch/riscv/errata/thead/errata.c     | 18 +++++++++++++++
>  arch/riscv/include/asm/errata_list.h | 16 +++++++++++++-
>  drivers/perf/riscv_pmu_sbi.c         | 33 +++++++++++++++++++---------
>  4 files changed, 69 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/riscv/Kconfig.erratas b/arch/riscv/Kconfig.erratas
> index f3623df23b5f..69621ae6d647 100644
> --- a/arch/riscv/Kconfig.erratas
> +++ b/arch/riscv/Kconfig.erratas
> @@ -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"
> diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
> index 21546937db39..67fa078f303f 100644
> --- a/arch/riscv/errata/thead/errata.c
> +++ b/arch/riscv/errata/thead/errata.c
> @@ -47,6 +47,21 @@ 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;
> +
> +	if (arch_id != 0 || impid != 0)
> +		return false;

Silly question maybe, but is it worth explaining in a comment why the
archid and impid are zero?

Anyways, on the last version I said:
> modulo Andreas' question being answered satisfactorially, this is:
> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>

I guess he just never got back about it, so you may apply the R-b I
guess. Your response seems fair to me /shrug.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>

Thanks,
Conor.

> +
> +	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 +73,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;
>  }
>  
> diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
> index 19a771085781..4180312d2a70 100644
> --- a/arch/riscv/include/asm/errata_list.h
> +++ b/arch/riscv/include/asm/errata_list.h
> @@ -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
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index 8de4ca2fef21..ec0972c7c562 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -19,6 +19,7 @@
>  #include <linux/of.h>
>  #include <linux/cpu_pm.h>
>  
> +#include <asm/errata_list.h>
>  #include <asm/sbi.h>
>  #include <asm/hwcap.h>
>  
> @@ -46,6 +47,8 @@ static const struct attribute_group *riscv_pmu_attr_groups[] = {
>   * per_cpu in case of harts with different pmu counters
>   */
>  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;
>  
>  struct sbi_pmu_event_data {
> @@ -575,7 +578,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
>  	fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS);
>  	event = cpu_hw_evt->events[fidx];
>  	if (!event) {
> -		csr_clear(CSR_SIP, SIP_LCOFIP);
> +		csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
>  		return IRQ_NONE;
>  	}
>  
> @@ -583,13 +586,13 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
>  	pmu_sbi_stop_hw_ctrs(pmu);
>  
>  	/* Overflow status register should only be read after counter are stopped */
> -	overflow = csr_read(CSR_SSCOUNTOVF);
> +	ALT_SBI_PMU_OVERFLOW(overflow);
>  
>  	/*
>  	 * Overflow interrupt pending bit should only be cleared after stopping
>  	 * all the counters to avoid any race condition.
>  	 */
> -	csr_clear(CSR_SIP, SIP_LCOFIP);
> +	csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num));
>  
>  	/* No overflow bit is set */
>  	if (!overflow)
> @@ -651,10 +654,10 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
>  	/* Stop all the counters so that they can be enabled from perf */
>  	pmu_sbi_stop_all(pmu);
>  
> -	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
> +	if (riscv_pmu_use_irq) {
>  		cpu_hw_evt->irq = riscv_pmu_irq;
> -		csr_clear(CSR_IP, BIT(RV_IRQ_PMU));
> -		csr_set(CSR_IE, BIT(RV_IRQ_PMU));
> +		csr_clear(CSR_IP, BIT(riscv_pmu_irq_num));
> +		csr_set(CSR_IE, BIT(riscv_pmu_irq_num));
>  		enable_percpu_irq(riscv_pmu_irq, IRQ_TYPE_NONE);
>  	}
>  
> @@ -663,9 +666,9 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node)
>  
>  static int pmu_sbi_dying_cpu(unsigned int cpu, struct hlist_node *node)
>  {
> -	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
> +	if (riscv_pmu_use_irq) {
>  		disable_percpu_irq(riscv_pmu_irq);
> -		csr_clear(CSR_IE, BIT(RV_IRQ_PMU));
> +		csr_clear(CSR_IE, BIT(riscv_pmu_irq_num));
>  	}
>  
>  	/* Disable all counters access for user mode now */
> @@ -681,7 +684,17 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
>  	struct device_node *cpu, *child;
>  	struct irq_domain *domain = NULL;
>  
> -	if (!riscv_isa_extension_available(NULL, SSCOFPMF))
> +	if (riscv_isa_extension_available(NULL, SSCOFPMF)) {
> +		riscv_pmu_irq_num = RV_IRQ_PMU;
> +		riscv_pmu_use_irq = true;
> +	} else if (IS_ENABLED(CONFIG_ERRATA_THEAD_PMU) &&
> +		   sbi_get_mvendorid() == THEAD_VENDOR_ID &&
> +		   sbi_get_marchid() == 0 && sbi_get_mimpid() == 0) {
> +		riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU;
> +		riscv_pmu_use_irq = true;
> +	}
> +
> +	if (!riscv_pmu_use_irq)
>  		return -EOPNOTSUPP;
>  
>  	for_each_of_cpu_node(cpu) {
> @@ -703,7 +716,7 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde
>  		return -ENODEV;
>  	}
>  
> -	riscv_pmu_irq = irq_create_mapping(domain, RV_IRQ_PMU);
> +	riscv_pmu_irq = irq_create_mapping(domain, riscv_pmu_irq_num);
>  	if (!riscv_pmu_irq) {
>  		pr_err("Failed to map PMU interrupt for node\n");
>  		return -ENODEV;
> -- 
> 2.35.1
> 
> 
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-10-06 19:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-04 20:37 [PATCH v4 0/2] riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
2022-10-04 20:37 ` [PATCH 1/2] RISC-V: Cache SBI vendor values Heiko Stuebner
2022-10-05 17:07   ` Andrew Jones
2022-10-05 23:07     ` Heiko Stuebner
2022-10-04 20:37 ` [PATCH 2/2] drivers/perf: riscv_pmu_sbi: add support for PMU variant on T-Head C9xx cores Heiko Stuebner
2022-10-05 17:38   ` Andrew Jones
2022-10-06 19:20   ` Conor Dooley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).