* [PATCH v3 0/1] Common csr_read_num() and csr_write_num() for RISC-V
@ 2025-10-14 13:21 Anup Patel
2025-10-14 13:21 ` [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
0 siblings, 1 reply; 6+ messages in thread
From: Anup Patel @ 2025-10-14 13:21 UTC (permalink / raw)
To: Sunil V L, Rafael J . Wysocki
Cc: Palmer Dabbelt, Paul Walmsley, Alexandre Ghiti, Len Brown,
Atish Patra, Andrew Jones, Anup Patel, Will Deacon, Mark Rutland,
linux-acpi, linux-riscv, linux-kernel, Anup Patel
Some of the RISC-V drivers (such as RISC-V PMU and ACPI CPPC) need to
access CSR based on CSR number discovered from somewhere. Add common
RISC-V csr_read_num() and csr_write_num() functions under arch/riscv
for such drivers.
These patches can be found in the riscv_csr_read_num_v3 branch at:
https://github.com/avpatel/linux.git
Changes since v2:
- Rebase on Linux-6.18-rc1
- Added reviewed-by tags
Changes since v1:
- Make "out_err" mandatory for csr_read_num() and csr_write_num()
in PATCH2 as suggested by Sunil and Drew. This also helps further
simplify csr_read_num() and csr_write_num().
Anup Patel (1):
RISC-V: Add common csr_read_num() and csr_write_num() functions
arch/riscv/include/asm/csr.h | 3 +
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/csr.c | 165 +++++++++++++++++++++++++++++++++++
drivers/acpi/riscv/cppc.c | 17 ++--
drivers/perf/riscv_pmu.c | 54 ++----------
5 files changed, 184 insertions(+), 56 deletions(-)
create mode 100644 arch/riscv/kernel/csr.c
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-10-14 13:21 [PATCH v3 0/1] Common csr_read_num() and csr_write_num() for RISC-V Anup Patel
@ 2025-10-14 13:21 ` Anup Patel
2025-10-29 19:04 ` Paul Walmsley
0 siblings, 1 reply; 6+ messages in thread
From: Anup Patel @ 2025-10-14 13:21 UTC (permalink / raw)
To: Sunil V L, Rafael J . Wysocki
Cc: Palmer Dabbelt, Paul Walmsley, Alexandre Ghiti, Len Brown,
Atish Patra, Andrew Jones, Anup Patel, Will Deacon, Mark Rutland,
linux-acpi, linux-riscv, linux-kernel, Anup Patel, Atish Patra,
Nutty Liu
In RISC-V, there is no CSR read/write instruction which takes CSR
number via register so add common csr_read_num() and csr_write_num()
functions which allow accessing certain CSRs by passing CSR number
as parameter. These common functions will be first used by the
ACPI CPPC driver and RISC-V PMU driver.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
---
arch/riscv/include/asm/csr.h | 3 +
arch/riscv/kernel/Makefile | 1 +
arch/riscv/kernel/csr.c | 165 +++++++++++++++++++++++++++++++++++
drivers/acpi/riscv/cppc.c | 17 ++--
drivers/perf/riscv_pmu.c | 54 ++----------
5 files changed, 184 insertions(+), 56 deletions(-)
create mode 100644 arch/riscv/kernel/csr.c
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 4a37a98398ad..46e1fcd82fd0 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -575,6 +575,9 @@
: "memory"); \
})
+extern unsigned long csr_read_num(unsigned long csr_num, int *out_err);
+extern void csr_write_num(unsigned long csr_num, unsigned long val, int *out_err);
+
#endif /* __ASSEMBLER__ */
#endif /* _ASM_RISCV_CSR_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index f60fce69b725..a75e79192531 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -50,6 +50,7 @@ obj-y += soc.o
obj-$(CONFIG_RISCV_ALTERNATIVE) += alternative.o
obj-y += cpu.o
obj-y += cpufeature.o
+obj-y += csr.o
obj-y += entry.o
obj-y += irq.o
obj-y += process.o
diff --git a/arch/riscv/kernel/csr.c b/arch/riscv/kernel/csr.c
new file mode 100644
index 000000000000..e96b129c1a99
--- /dev/null
+++ b/arch/riscv/kernel/csr.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Ventana Micro Systems Inc.
+ */
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/types.h>
+#include <asm/csr.h>
+
+#define CSR_CUSTOM0_U_RW_BASE 0x800
+#define CSR_CUSTOM0_U_RW_COUNT 0x100
+
+#define CSR_CUSTOM1_U_RO_BASE 0xCC0
+#define CSR_CUSTOM1_U_RO_COUNT 0x040
+
+#define CSR_CUSTOM2_S_RW_BASE 0x5C0
+#define CSR_CUSTOM2_S_RW_COUNT 0x040
+
+#define CSR_CUSTOM3_S_RW_BASE 0x9C0
+#define CSR_CUSTOM3_S_RW_COUNT 0x040
+
+#define CSR_CUSTOM4_S_RO_BASE 0xDC0
+#define CSR_CUSTOM4_S_RO_COUNT 0x040
+
+#define CSR_CUSTOM5_HS_RW_BASE 0x6C0
+#define CSR_CUSTOM5_HS_RW_COUNT 0x040
+
+#define CSR_CUSTOM6_HS_RW_BASE 0xAC0
+#define CSR_CUSTOM6_HS_RW_COUNT 0x040
+
+#define CSR_CUSTOM7_HS_RO_BASE 0xEC0
+#define CSR_CUSTOM7_HS_RO_COUNT 0x040
+
+#define CSR_CUSTOM8_M_RW_BASE 0x7C0
+#define CSR_CUSTOM8_M_RW_COUNT 0x040
+
+#define CSR_CUSTOM9_M_RW_BASE 0xBC0
+#define CSR_CUSTOM9_M_RW_COUNT 0x040
+
+#define CSR_CUSTOM10_M_RO_BASE 0xFC0
+#define CSR_CUSTOM10_M_RO_COUNT 0x040
+
+unsigned long csr_read_num(unsigned long csr_num, int *out_err)
+{
+#define switchcase_csr_read(__csr_num) \
+ case (__csr_num): \
+ return csr_read(__csr_num)
+#define switchcase_csr_read_2(__csr_num) \
+ switchcase_csr_read(__csr_num + 0); \
+ switchcase_csr_read(__csr_num + 1)
+#define switchcase_csr_read_4(__csr_num) \
+ switchcase_csr_read_2(__csr_num + 0); \
+ switchcase_csr_read_2(__csr_num + 2)
+#define switchcase_csr_read_8(__csr_num) \
+ switchcase_csr_read_4(__csr_num + 0); \
+ switchcase_csr_read_4(__csr_num + 4)
+#define switchcase_csr_read_16(__csr_num) \
+ switchcase_csr_read_8(__csr_num + 0); \
+ switchcase_csr_read_8(__csr_num + 8)
+#define switchcase_csr_read_32(__csr_num) \
+ switchcase_csr_read_16(__csr_num + 0); \
+ switchcase_csr_read_16(__csr_num + 16)
+#define switchcase_csr_read_64(__csr_num) \
+ switchcase_csr_read_32(__csr_num + 0); \
+ switchcase_csr_read_32(__csr_num + 32)
+#define switchcase_csr_read_128(__csr_num) \
+ switchcase_csr_read_64(__csr_num + 0); \
+ switchcase_csr_read_64(__csr_num + 64)
+#define switchcase_csr_read_256(__csr_num) \
+ switchcase_csr_read_128(__csr_num + 0); \
+ switchcase_csr_read_128(__csr_num + 128)
+
+ *out_err = 0;
+ switch (csr_num) {
+ switchcase_csr_read_32(CSR_CYCLE);
+ switchcase_csr_read_32(CSR_CYCLEH);
+ switchcase_csr_read_256(CSR_CUSTOM0_U_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM1_U_RO_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM2_S_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM3_S_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM4_S_RO_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM5_HS_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM6_HS_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM7_HS_RO_BASE);
+#ifdef CONFIG_RISCV_M_MODE
+ switchcase_csr_read_64(CSR_CUSTOM8_M_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM9_M_RW_BASE);
+ switchcase_csr_read_64(CSR_CUSTOM10_M_RO_BASE);
+#endif
+ default:
+ *out_err = -EINVAL;
+ break;
+ }
+
+ return 0;
+#undef switchcase_csr_read_256
+#undef switchcase_csr_read_128
+#undef switchcase_csr_read_64
+#undef switchcase_csr_read_32
+#undef switchcase_csr_read_16
+#undef switchcase_csr_read_8
+#undef switchcase_csr_read_4
+#undef switchcase_csr_read_2
+#undef switchcase_csr_read
+}
+EXPORT_SYMBOL_GPL(csr_read_num);
+
+void csr_write_num(unsigned long csr_num, unsigned long val, int *out_err)
+{
+#define switchcase_csr_write(__csr_num, __val) \
+ case (__csr_num): \
+ csr_write(__csr_num, __val); \
+ break
+#define switchcase_csr_write_2(__csr_num, __val) \
+ switchcase_csr_write(__csr_num + 0, __val); \
+ switchcase_csr_write(__csr_num + 1, __val)
+#define switchcase_csr_write_4(__csr_num, __val) \
+ switchcase_csr_write_2(__csr_num + 0, __val); \
+ switchcase_csr_write_2(__csr_num + 2, __val)
+#define switchcase_csr_write_8(__csr_num, __val) \
+ switchcase_csr_write_4(__csr_num + 0, __val); \
+ switchcase_csr_write_4(__csr_num + 4, __val)
+#define switchcase_csr_write_16(__csr_num, __val) \
+ switchcase_csr_write_8(__csr_num + 0, __val); \
+ switchcase_csr_write_8(__csr_num + 8, __val)
+#define switchcase_csr_write_32(__csr_num, __val) \
+ switchcase_csr_write_16(__csr_num + 0, __val); \
+ switchcase_csr_write_16(__csr_num + 16, __val)
+#define switchcase_csr_write_64(__csr_num, __val) \
+ switchcase_csr_write_32(__csr_num + 0, __val); \
+ switchcase_csr_write_32(__csr_num + 32, __val)
+#define switchcase_csr_write_128(__csr_num, __val) \
+ switchcase_csr_write_64(__csr_num + 0, __val); \
+ switchcase_csr_write_64(__csr_num + 64, __val)
+#define switchcase_csr_write_256(__csr_num, __val) \
+ switchcase_csr_write_128(__csr_num + 0, __val); \
+ switchcase_csr_write_128(__csr_num + 128, __val)
+
+ *out_err = 0;
+ switch (csr_num) {
+ switchcase_csr_write_256(CSR_CUSTOM0_U_RW_BASE, val);
+ switchcase_csr_write_64(CSR_CUSTOM2_S_RW_BASE, val);
+ switchcase_csr_write_64(CSR_CUSTOM3_S_RW_BASE, val);
+ switchcase_csr_write_64(CSR_CUSTOM5_HS_RW_BASE, val);
+ switchcase_csr_write_64(CSR_CUSTOM6_HS_RW_BASE, val);
+#ifdef CONFIG_RISCV_M_MODE
+ switchcase_csr_write_64(CSR_CUSTOM8_M_RW_BASE, val);
+ switchcase_csr_write_64(CSR_CUSTOM9_M_RW_BASE, val);
+#endif
+ default:
+ *out_err = -EINVAL;
+ break;
+ }
+#undef switchcase_csr_write_256
+#undef switchcase_csr_write_128
+#undef switchcase_csr_write_64
+#undef switchcase_csr_write_32
+#undef switchcase_csr_write_16
+#undef switchcase_csr_write_8
+#undef switchcase_csr_write_4
+#undef switchcase_csr_write_2
+#undef switchcase_csr_write
+}
+EXPORT_SYMBOL_GPL(csr_write_num);
diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
index 42c1a9052470..fe491937ed25 100644
--- a/drivers/acpi/riscv/cppc.c
+++ b/drivers/acpi/riscv/cppc.c
@@ -65,24 +65,19 @@ static void sbi_cppc_write(void *write_data)
static void cppc_ffh_csr_read(void *read_data)
{
struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
+ int err;
- switch (data->reg) {
- /* Support only TIME CSR for now */
- case CSR_TIME:
- data->ret.value = csr_read(CSR_TIME);
- data->ret.error = 0;
- break;
- default:
- data->ret.error = -EINVAL;
- break;
- }
+ data->ret.value = csr_read_num(data->reg, &err);
+ data->ret.error = err;
}
static void cppc_ffh_csr_write(void *write_data)
{
struct sbi_cppc_data *data = (struct sbi_cppc_data *)write_data;
+ int err;
- data->ret.error = -EINVAL;
+ csr_write_num(data->reg, data->val, &err);
+ data->ret.error = err;
}
/*
diff --git a/drivers/perf/riscv_pmu.c b/drivers/perf/riscv_pmu.c
index 7644147d50b4..b41f353ba964 100644
--- a/drivers/perf/riscv_pmu.c
+++ b/drivers/perf/riscv_pmu.c
@@ -16,6 +16,7 @@
#include <linux/smp.h>
#include <linux/sched_clock.h>
+#include <asm/csr.h>
#include <asm/sbi.h>
static bool riscv_perf_user_access(struct perf_event *event)
@@ -88,58 +89,21 @@ void arch_perf_update_userpage(struct perf_event *event,
userpg->cap_user_time_short = 1;
}
-static unsigned long csr_read_num(int csr_num)
-{
-#define switchcase_csr_read(__csr_num, __val) {\
- case __csr_num: \
- __val = csr_read(__csr_num); \
- break; }
-#define switchcase_csr_read_2(__csr_num, __val) {\
- switchcase_csr_read(__csr_num + 0, __val) \
- switchcase_csr_read(__csr_num + 1, __val)}
-#define switchcase_csr_read_4(__csr_num, __val) {\
- switchcase_csr_read_2(__csr_num + 0, __val) \
- switchcase_csr_read_2(__csr_num + 2, __val)}
-#define switchcase_csr_read_8(__csr_num, __val) {\
- switchcase_csr_read_4(__csr_num + 0, __val) \
- switchcase_csr_read_4(__csr_num + 4, __val)}
-#define switchcase_csr_read_16(__csr_num, __val) {\
- switchcase_csr_read_8(__csr_num + 0, __val) \
- switchcase_csr_read_8(__csr_num + 8, __val)}
-#define switchcase_csr_read_32(__csr_num, __val) {\
- switchcase_csr_read_16(__csr_num + 0, __val) \
- switchcase_csr_read_16(__csr_num + 16, __val)}
-
- unsigned long ret = 0;
-
- switch (csr_num) {
- switchcase_csr_read_32(CSR_CYCLE, ret)
- switchcase_csr_read_32(CSR_CYCLEH, ret)
- default :
- break;
- }
-
- return ret;
-#undef switchcase_csr_read_32
-#undef switchcase_csr_read_16
-#undef switchcase_csr_read_8
-#undef switchcase_csr_read_4
-#undef switchcase_csr_read_2
-#undef switchcase_csr_read
-}
-
/*
* Read the CSR of a corresponding counter.
*/
unsigned long riscv_pmu_ctr_read_csr(unsigned long csr)
{
- if (csr < CSR_CYCLE || csr > CSR_HPMCOUNTER31H ||
- (csr > CSR_HPMCOUNTER31 && csr < CSR_CYCLEH)) {
- pr_err("Invalid performance counter csr %lx\n", csr);
- return -EINVAL;
+ unsigned long val;
+ int rc;
+
+ val = csr_read_num(csr, &rc);
+ if (rc) {
+ pr_err("Failed to read performance counter csr %lx (error %d)\n", csr, rc);
+ return rc;
}
- return csr_read_num(csr);
+ return val;
}
u64 riscv_pmu_ctr_get_width_mask(struct perf_event *event)
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-10-14 13:21 ` [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
@ 2025-10-29 19:04 ` Paul Walmsley
2025-10-30 6:07 ` Anup Patel
0 siblings, 1 reply; 6+ messages in thread
From: Paul Walmsley @ 2025-10-29 19:04 UTC (permalink / raw)
To: Anup Patel
Cc: Sunil V L, Rafael J . Wysocki, Palmer Dabbelt, Paul Walmsley,
Alexandre Ghiti, Len Brown, Atish Patra, Andrew Jones, Anup Patel,
Will Deacon, Mark Rutland, linux-acpi, linux-riscv, linux-kernel,
Atish Patra, Nutty Liu
Hi Anup,
On Tue, 14 Oct 2025, Anup Patel wrote:
> In RISC-V, there is no CSR read/write instruction which takes CSR
> number via register so add common csr_read_num() and csr_write_num()
> functions which allow accessing certain CSRs by passing CSR number
> as parameter. These common functions will be first used by the
> ACPI CPPC driver and RISC-V PMU driver.
>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
This patch also (silently) removes the CSR number filtering, e.g.
> diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> index 42c1a9052470..fe491937ed25 100644
> --- a/drivers/acpi/riscv/cppc.c
> +++ b/drivers/acpi/riscv/cppc.c
> @@ -65,24 +65,19 @@ static void sbi_cppc_write(void *write_data)
> static void cppc_ffh_csr_read(void *read_data)
> {
> struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
> + int err;
>
> - switch (data->reg) {
> - /* Support only TIME CSR for now */
> - case CSR_TIME:
> - data->ret.value = csr_read(CSR_TIME);
> - data->ret.error = 0;
> - break;
> - default:
> - data->ret.error = -EINVAL;
> - break;
> - }
... the above code, and:
> /*
> * Read the CSR of a corresponding counter.
> */
> unsigned long riscv_pmu_ctr_read_csr(unsigned long csr)
> {
> - if (csr < CSR_CYCLE || csr > CSR_HPMCOUNTER31H ||
> - (csr > CSR_HPMCOUNTER31 && csr < CSR_CYCLEH)) {
> - pr_err("Invalid performance counter csr %lx\n", csr);
> - return -EINVAL;
... the above code.
I'm thinking that we probably want to keep the CSR number filtering code
in; at least, I can't think of a good reason to remove it. Care to add it
back in?
- Paul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-10-29 19:04 ` Paul Walmsley
@ 2025-10-30 6:07 ` Anup Patel
2025-11-22 1:14 ` Paul Walmsley
0 siblings, 1 reply; 6+ messages in thread
From: Anup Patel @ 2025-10-30 6:07 UTC (permalink / raw)
To: Paul Walmsley
Cc: Anup Patel, Sunil V L, Rafael J . Wysocki, Palmer Dabbelt,
Paul Walmsley, Alexandre Ghiti, Len Brown, Atish Patra,
Andrew Jones, Will Deacon, Mark Rutland, linux-acpi, linux-riscv,
linux-kernel, Atish Patra, Nutty Liu
On Thu, Oct 30, 2025 at 12:35 AM Paul Walmsley <pjw@kernel.org> wrote:
>
> Hi Anup,
>
> On Tue, 14 Oct 2025, Anup Patel wrote:
>
> > In RISC-V, there is no CSR read/write instruction which takes CSR
> > number via register so add common csr_read_num() and csr_write_num()
> > functions which allow accessing certain CSRs by passing CSR number
> > as parameter. These common functions will be first used by the
> > ACPI CPPC driver and RISC-V PMU driver.
> >
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
> > Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> > Reviewed-by: Atish Patra <atishp@rivosinc.com>
> > Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
>
> This patch also (silently) removes the CSR number filtering, e.g.
>
> > diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> > index 42c1a9052470..fe491937ed25 100644
> > --- a/drivers/acpi/riscv/cppc.c
> > +++ b/drivers/acpi/riscv/cppc.c
> > @@ -65,24 +65,19 @@ static void sbi_cppc_write(void *write_data)
> > static void cppc_ffh_csr_read(void *read_data)
> > {
> > struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
> > + int err;
> >
> > - switch (data->reg) {
> > - /* Support only TIME CSR for now */
> > - case CSR_TIME:
> > - data->ret.value = csr_read(CSR_TIME);
> > - data->ret.error = 0;
> > - break;
> > - default:
> > - data->ret.error = -EINVAL;
> > - break;
> > - }
>
> ... the above code, and:
The switch case is incomplete for cppc_ffh_csr_read().
Also, csr_read_num() already does appropriate filtering
so the switch case over here is now redundant.
>
> > /*
> > * Read the CSR of a corresponding counter.
> > */
> > unsigned long riscv_pmu_ctr_read_csr(unsigned long csr)
> > {
> > - if (csr < CSR_CYCLE || csr > CSR_HPMCOUNTER31H ||
> > - (csr > CSR_HPMCOUNTER31 && csr < CSR_CYCLEH)) {
> > - pr_err("Invalid performance counter csr %lx\n", csr);
> > - return -EINVAL;
>
> ... the above code.
>
> I'm thinking that we probably want to keep the CSR number filtering code
> in; at least, I can't think of a good reason to remove it. Care to add it
> back in?
We can potentially have custom CSRs as hardware counters
hence the CSR filtering over here is already incomplete. Plus,
csr_read_num() already does the CSR filtering and returns
failure for inappropriate CSR number.
Regards,
Anup
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-10-30 6:07 ` Anup Patel
@ 2025-11-22 1:14 ` Paul Walmsley
2025-11-24 4:49 ` Anup Patel
0 siblings, 1 reply; 6+ messages in thread
From: Paul Walmsley @ 2025-11-22 1:14 UTC (permalink / raw)
To: Anup Patel
Cc: Paul Walmsley, Anup Patel, Mark Rutland, Alexandre Ghiti,
Rafael J . Wysocki, Atish Patra, Atish Patra, linux-kernel,
linux-acpi, Palmer Dabbelt, Paul Walmsley, Nutty Liu, linux-riscv,
Andrew Jones, Will Deacon, Len Brown
[-- Attachment #1: Type: text/plain, Size: 2833 bytes --]
On Thu, 30 Oct 2025, Anup Patel wrote:
> On Thu, Oct 30, 2025 at 12:35 AM Paul Walmsley <pjw@kernel.org> wrote:
> > On Tue, 14 Oct 2025, Anup Patel wrote:
> >
> > > In RISC-V, there is no CSR read/write instruction which takes CSR
> > > number via register so add common csr_read_num() and csr_write_num()
> > > functions which allow accessing certain CSRs by passing CSR number
> > > as parameter. These common functions will be first used by the
> > > ACPI CPPC driver and RISC-V PMU driver.
> >
> > This patch also (silently) removes the CSR number filtering, e.g.
> >
> > > diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> > > index 42c1a9052470..fe491937ed25 100644
> > > --- a/drivers/acpi/riscv/cppc.c
> > > +++ b/drivers/acpi/riscv/cppc.c
> > > @@ -65,24 +65,19 @@ static void sbi_cppc_write(void *write_data)
> > > static void cppc_ffh_csr_read(void *read_data)
> > > {
> > > struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
> > > + int err;
> > >
> > > - switch (data->reg) {
> > > - /* Support only TIME CSR for now */
> > > - case CSR_TIME:
> > > - data->ret.value = csr_read(CSR_TIME);
> > > - data->ret.error = 0;
> > > - break;
> > > - default:
> > > - data->ret.error = -EINVAL;
> > > - break;
> > > - }
> >
> > ... the above code, and:
>
> The switch case is incomplete for cppc_ffh_csr_read().
> Also, csr_read_num() already does appropriate filtering
> so the switch case over here is now redundant.
>
> >
> > > /*
> > > * Read the CSR of a corresponding counter.
> > > */
> > > unsigned long riscv_pmu_ctr_read_csr(unsigned long csr)
> > > {
> > > - if (csr < CSR_CYCLE || csr > CSR_HPMCOUNTER31H ||
> > > - (csr > CSR_HPMCOUNTER31 && csr < CSR_CYCLEH)) {
> > > - pr_err("Invalid performance counter csr %lx\n", csr);
> > > - return -EINVAL;
> >
> > ... the above code.
> >
> > I'm thinking that we probably want to keep the CSR number filtering code
> > in; at least, I can't think of a good reason to remove it. Care to add it
> > back in?
>
> We can potentially have custom CSRs as hardware counters
> hence the CSR filtering over here is already incomplete. Plus,
> csr_read_num() already does the CSR filtering and returns
> failure for inappropriate CSR number.
OK. To me, the most notable changes in this patch are the changes in the
filters for both reads and writes for the two different call sites, ACPI
FFH and PMU. It would be good to document these filter changes directly
in the patch description, along with the rationale.
I'm also not yet completely convinced that we should allow both of these
call sites to read and write any custom CSR. But maybe the updated patch
description might be convincing...
- Paul
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-11-22 1:14 ` Paul Walmsley
@ 2025-11-24 4:49 ` Anup Patel
0 siblings, 0 replies; 6+ messages in thread
From: Anup Patel @ 2025-11-24 4:49 UTC (permalink / raw)
To: Paul Walmsley
Cc: Anup Patel, Mark Rutland, Alexandre Ghiti, Rafael J . Wysocki,
Atish Patra, Atish Patra, linux-kernel, linux-acpi,
Palmer Dabbelt, Paul Walmsley, Nutty Liu, linux-riscv,
Andrew Jones, Will Deacon, Len Brown
On Sat, Nov 22, 2025 at 6:44 AM Paul Walmsley <pjw@kernel.org> wrote:
>
> On Thu, 30 Oct 2025, Anup Patel wrote:
>
> > On Thu, Oct 30, 2025 at 12:35 AM Paul Walmsley <pjw@kernel.org> wrote:
> > > On Tue, 14 Oct 2025, Anup Patel wrote:
> > >
> > > > In RISC-V, there is no CSR read/write instruction which takes CSR
> > > > number via register so add common csr_read_num() and csr_write_num()
> > > > functions which allow accessing certain CSRs by passing CSR number
> > > > as parameter. These common functions will be first used by the
> > > > ACPI CPPC driver and RISC-V PMU driver.
> > >
> > > This patch also (silently) removes the CSR number filtering, e.g.
> > >
> > > > diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> > > > index 42c1a9052470..fe491937ed25 100644
> > > > --- a/drivers/acpi/riscv/cppc.c
> > > > +++ b/drivers/acpi/riscv/cppc.c
> > > > @@ -65,24 +65,19 @@ static void sbi_cppc_write(void *write_data)
> > > > static void cppc_ffh_csr_read(void *read_data)
> > > > {
> > > > struct sbi_cppc_data *data = (struct sbi_cppc_data *)read_data;
> > > > + int err;
> > > >
> > > > - switch (data->reg) {
> > > > - /* Support only TIME CSR for now */
> > > > - case CSR_TIME:
> > > > - data->ret.value = csr_read(CSR_TIME);
> > > > - data->ret.error = 0;
> > > > - break;
> > > > - default:
> > > > - data->ret.error = -EINVAL;
> > > > - break;
> > > > - }
> > >
> > > ... the above code, and:
> >
> > The switch case is incomplete for cppc_ffh_csr_read().
> > Also, csr_read_num() already does appropriate filtering
> > so the switch case over here is now redundant.
> >
> > >
> > > > /*
> > > > * Read the CSR of a corresponding counter.
> > > > */
> > > > unsigned long riscv_pmu_ctr_read_csr(unsigned long csr)
> > > > {
> > > > - if (csr < CSR_CYCLE || csr > CSR_HPMCOUNTER31H ||
> > > > - (csr > CSR_HPMCOUNTER31 && csr < CSR_CYCLEH)) {
> > > > - pr_err("Invalid performance counter csr %lx\n", csr);
> > > > - return -EINVAL;
> > >
> > > ... the above code.
> > >
> > > I'm thinking that we probably want to keep the CSR number filtering code
> > > in; at least, I can't think of a good reason to remove it. Care to add it
> > > back in?
> >
> > We can potentially have custom CSRs as hardware counters
> > hence the CSR filtering over here is already incomplete. Plus,
> > csr_read_num() already does the CSR filtering and returns
> > failure for inappropriate CSR number.
>
> OK. To me, the most notable changes in this patch are the changes in the
> filters for both reads and writes for the two different call sites, ACPI
> FFH and PMU. It would be good to document these filter changes directly
> in the patch description, along with the rationale.
>
> I'm also not yet completely convinced that we should allow both of these
> call sites to read and write any custom CSR. But maybe the updated patch
> description might be convincing...
The RISC-V ACPI FFH specification allows a 12-bit CSR number in
_CPC object encoding so any CSR can be mapped as a CPPC register
(including custom CSRs).
Similarly, the RISC-V SBI PMU specification return 12-bit CSR number
in sbi_pmu_counter_get_info() so a platform can use custom CSRs for
additional HW counters.
I will update the commit description accordingly.
Regards,
Anup
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-11-24 4:49 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-14 13:21 [PATCH v3 0/1] Common csr_read_num() and csr_write_num() for RISC-V Anup Patel
2025-10-14 13:21 ` [PATCH v3 1/1] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
2025-10-29 19:04 ` Paul Walmsley
2025-10-30 6:07 ` Anup Patel
2025-11-22 1:14 ` Paul Walmsley
2025-11-24 4:49 ` Anup Patel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox