* [PATCH v2 0/2] Common csr_read_num() and csr_write_num() for RISC-V
@ 2025-08-18 14:35 Anup Patel
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
0 siblings, 2 replies; 14+ messages in thread
From: Anup Patel @ 2025-08-18 14:35 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_v2 branch at:
https://github.com/avpatel/linux.git
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 (2):
ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
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 | 21 ++---
drivers/perf/riscv_pmu.c | 54 ++----------
5 files changed, 186 insertions(+), 58 deletions(-)
create mode 100644 arch/riscv/kernel/csr.c
--
2.43.0
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
2025-08-18 14:35 [PATCH v2 0/2] Common csr_read_num() and csr_write_num() for RISC-V Anup Patel
@ 2025-08-18 14:35 ` Anup Patel
2025-08-18 19:26 ` Atish Patra
` (3 more replies)
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
1 sibling, 4 replies; 14+ messages in thread
From: Anup Patel @ 2025-08-18 14:35 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, Troy Mitchell
The cppc_ffh_csr_read() and cppc_ffh_csr_write() returns Linux error
code in "data->ret.error" so cpc_read_ffh() and cpc_write_ffh() must
not use sbi_err_map_linux_errno() for FFH_CPPC_CSR.
Fixes: 30f3ffbee86b ("ACPI: RISC-V: Add CPPC driver")
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
---
drivers/acpi/riscv/cppc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
index 440cf9fb91aa..42c1a9052470 100644
--- a/drivers/acpi/riscv/cppc.c
+++ b/drivers/acpi/riscv/cppc.c
@@ -119,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
*val = data.ret.value;
- return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
+ return data.ret.error;
}
return -EINVAL;
@@ -148,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
- return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
+ return data.ret.error;
}
return -EINVAL;
--
2.43.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-18 14:35 [PATCH v2 0/2] Common csr_read_num() and csr_write_num() for RISC-V Anup Patel
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
@ 2025-08-18 14:36 ` Anup Patel
2025-08-18 14:56 ` Andrew Jones
` (3 more replies)
1 sibling, 4 replies; 14+ messages in thread
From: Anup Patel @ 2025-08-18 14:36 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
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>
---
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 6fed42e37705..1540626b3540 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 /* __ASSEMBLY__ */
#endif /* _ASM_RISCV_CSR_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index c7b542573407..0a75e20bde18 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] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
@ 2025-08-18 14:56 ` Andrew Jones
2025-08-18 19:29 ` Atish Patra
` (2 subsequent siblings)
3 siblings, 0 replies; 14+ messages in thread
From: Andrew Jones @ 2025-08-18 14:56 UTC (permalink / raw)
To: Anup Patel
Cc: Sunil V L, Rafael J . Wysocki, Palmer Dabbelt, Paul Walmsley,
Alexandre Ghiti, Len Brown, Atish Patra, Anup Patel, Will Deacon,
Mark Rutland, linux-acpi, linux-riscv, linux-kernel
On Mon, Aug 18, 2025 at 08:06:00PM +0530, 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>
> ---
> 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
>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
@ 2025-08-18 19:26 ` Atish Patra
2025-08-19 4:02 ` Nutty.Liu
` (2 subsequent siblings)
3 siblings, 0 replies; 14+ messages in thread
From: Atish Patra @ 2025-08-18 19:26 UTC (permalink / raw)
To: Anup Patel, Sunil V L, Rafael J . Wysocki
Cc: Palmer Dabbelt, Paul Walmsley, Alexandre Ghiti, Len Brown,
Andrew Jones, Anup Patel, Will Deacon, Mark Rutland, linux-acpi,
linux-riscv, linux-kernel, Troy Mitchell
On 8/18/25 7:35 AM, Anup Patel wrote:
> The cppc_ffh_csr_read() and cppc_ffh_csr_write() returns Linux error
> code in "data->ret.error" so cpc_read_ffh() and cpc_write_ffh() must
> not use sbi_err_map_linux_errno() for FFH_CPPC_CSR.
>
> Fixes: 30f3ffbee86b ("ACPI: RISC-V: Add CPPC driver")
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
> ---
> drivers/acpi/riscv/cppc.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> index 440cf9fb91aa..42c1a9052470 100644
> --- a/drivers/acpi/riscv/cppc.c
> +++ b/drivers/acpi/riscv/cppc.c
> @@ -119,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
>
> *val = data.ret.value;
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
> @@ -148,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
>
> smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
Reviewed-by: Atish Patra <atishp@rivosinc.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
2025-08-18 14:56 ` Andrew Jones
@ 2025-08-18 19:29 ` Atish Patra
2025-08-19 3:26 ` Yao Zi
2025-08-19 4:04 ` Nutty.Liu
3 siblings, 0 replies; 14+ messages in thread
From: Atish Patra @ 2025-08-18 19:29 UTC (permalink / raw)
To: Anup Patel, Sunil V L, Rafael J . Wysocki
Cc: Palmer Dabbelt, Paul Walmsley, Alexandre Ghiti, Len Brown,
Andrew Jones, Anup Patel, Will Deacon, Mark Rutland, linux-acpi,
linux-riscv, linux-kernel
On 8/18/25 7:36 AM, 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.
Thanks for the cleanup. Are you planning to align the csr.h in tools so
that userpsace tools can use leverage it as well ?
tools/arch/riscv/include/asm/csr.h
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Sunil V L <sunilvl@ventanamicro.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 6fed42e37705..1540626b3540 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 /* __ASSEMBLY__ */
>
> #endif /* _ASM_RISCV_CSR_H */
> diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> index c7b542573407..0a75e20bde18 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;
> }
Otherwise, lgtm.
Reviewed-by: Atish Patra <atishp@rivosinc.com>
>
> u64 riscv_pmu_ctr_get_width_mask(struct perf_event *event)
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
2025-08-18 14:56 ` Andrew Jones
2025-08-18 19:29 ` Atish Patra
@ 2025-08-19 3:26 ` Yao Zi
2025-08-19 3:30 ` Anup Patel
2025-08-19 4:04 ` Nutty.Liu
3 siblings, 1 reply; 14+ messages in thread
From: Yao Zi @ 2025-08-19 3:26 UTC (permalink / raw)
To: Anup Patel, 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
On Mon, Aug 18, 2025 at 08:06:00PM +0530, 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>
> ---
> 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 6fed42e37705..1540626b3540 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);
I think it's more consistent to directly return the error code, and for
csr_read_num, we could pass out the read value by a pointer. e.g.
int csr_read_num(unsigned long csr_num, unsigned long *val);
int csr_write_num(unsigned long csr_num, unsigned long val);
This allows the caller to eliminate a variable for temporarily storing
the error code if they use it just after the invokation, and fits the
common convention of Linux better.
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* _ASM_RISCV_CSR_H */
...
> 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;
> }
This could be simplified as
data->ret.error = csr_write_num(data->reg, data->val);
and variable err could be dropped.
Best regards,
Yao Zi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-19 3:26 ` Yao Zi
@ 2025-08-19 3:30 ` Anup Patel
2025-08-19 4:13 ` Yao Zi
0 siblings, 1 reply; 14+ messages in thread
From: Anup Patel @ 2025-08-19 3:30 UTC (permalink / raw)
To: Yao Zi
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
On Tue, Aug 19, 2025 at 8:56 AM Yao Zi <ziyao@disroot.org> wrote:
>
> On Mon, Aug 18, 2025 at 08:06:00PM +0530, 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>
> > ---
> > 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 6fed42e37705..1540626b3540 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);
>
> I think it's more consistent to directly return the error code, and for
> csr_read_num, we could pass out the read value by a pointer. e.g.
>
> int csr_read_num(unsigned long csr_num, unsigned long *val);
> int csr_write_num(unsigned long csr_num, unsigned long val);
>
> This allows the caller to eliminate a variable for temporarily storing
> the error code if they use it just after the invokation, and fits the
> common convention of Linux better.
Drew had similar comments so see my response in the previous
patch revision. (Refer, https://www.spinics.net/lists/kernel/msg5808113.html)
Regards,
Anup
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
2025-08-18 19:26 ` Atish Patra
@ 2025-08-19 4:02 ` Nutty.Liu
2025-08-19 4:25 ` Sunil V L
2025-08-20 7:12 ` Alexandre Ghiti
3 siblings, 0 replies; 14+ messages in thread
From: Nutty.Liu @ 2025-08-19 4:02 UTC (permalink / raw)
To: Anup Patel, 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, Troy Mitchell
On 8/18/2025 10:35 PM, Anup Patel wrote:
> The cppc_ffh_csr_read() and cppc_ffh_csr_write() returns Linux error
> code in "data->ret.error" so cpc_read_ffh() and cpc_write_ffh() must
> not use sbi_err_map_linux_errno() for FFH_CPPC_CSR.
>
> Fixes: 30f3ffbee86b ("ACPI: RISC-V: Add CPPC driver")
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
> ---
> drivers/acpi/riscv/cppc.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
> diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> index 440cf9fb91aa..42c1a9052470 100644
> --- a/drivers/acpi/riscv/cppc.c
> +++ b/drivers/acpi/riscv/cppc.c
> @@ -119,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
>
> *val = data.ret.value;
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
> @@ -148,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
>
> smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
` (2 preceding siblings ...)
2025-08-19 3:26 ` Yao Zi
@ 2025-08-19 4:04 ` Nutty.Liu
3 siblings, 0 replies; 14+ messages in thread
From: Nutty.Liu @ 2025-08-19 4:04 UTC (permalink / raw)
To: Anup Patel, 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
On 8/18/2025 10:36 PM, 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>
> ---
> 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
Reviewed-by: Nutty Liu <nutty.liu@hotmail.com>
Thanks,
Nutty
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-19 3:30 ` Anup Patel
@ 2025-08-19 4:13 ` Yao Zi
2025-08-19 11:01 ` Anup Patel
0 siblings, 1 reply; 14+ messages in thread
From: Yao Zi @ 2025-08-19 4:13 UTC (permalink / raw)
To: Anup Patel
Cc: Mark Rutland, Alexandre Ghiti, Rafael J . Wysocki, Anup Patel,
Atish Patra, linux-kernel, linux-acpi, Palmer Dabbelt,
Paul Walmsley, linux-riscv, Andrew Jones, Will Deacon, Len Brown
On Tue, Aug 19, 2025 at 09:00:03AM +0530, Anup Patel wrote:
> On Tue, Aug 19, 2025 at 8:56 AM Yao Zi <ziyao@disroot.org> wrote:
> >
> > On Mon, Aug 18, 2025 at 08:06:00PM +0530, 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>
> > > ---
> > > 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 6fed42e37705..1540626b3540 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);
> >
> > I think it's more consistent to directly return the error code, and for
> > csr_read_num, we could pass out the read value by a pointer. e.g.
> >
> > int csr_read_num(unsigned long csr_num, unsigned long *val);
> > int csr_write_num(unsigned long csr_num, unsigned long val);
> >
> > This allows the caller to eliminate a variable for temporarily storing
> > the error code if they use it just after the invokation, and fits the
> > common convention of Linux better.
>
> Drew had similar comments so see my response in the previous
> patch revision. (Refer, https://www.spinics.net/lists/kernel/msg5808113.html)
Thanks for the reference.
> I had considered this but the problem with this approach is that
> individual switch cases in csr_read_num() become roughly 4
> instructions because value read from CSR has to written to a memory
> location.
You could return a structure smaller than or equal to 2 * XLEN from
csr_read_num(), according to the ABI it could be passed in a0 and a1 and
thus should require no memory operation.
Let's assume we have
struct __csr_read_ret {
long error;
unsigned long value;
};
struct __csr_read_ret __csr_read_num(unsigned long csr_num);
Then a wrapper like
/* piece of untested code */
static inline int csr_read_num(unsigned long csr_num,
unsigned long *val)
{
struct __csr_read_ret ret = __csr_read_num(csr_num);
*val = ret.value;
return ret.error;
}
could provide an interface that I've talked about earlier, and it
follows the kernel's convention.
> The current approach results in just 2 instructions for each
> switch-case. Additionally, the current prototypes of csr_read_num()
> and csr_write_num() are closer to csr_read() and csr_write()
> respectively.
But csr_read() and csr_write() never directly raise errors that is
expected to be handled by the caller. I don't think it's a fair
comparison.
> Regards,
> Anup
Best regards,
Yao Zi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
2025-08-18 19:26 ` Atish Patra
2025-08-19 4:02 ` Nutty.Liu
@ 2025-08-19 4:25 ` Sunil V L
2025-08-20 7:12 ` Alexandre Ghiti
3 siblings, 0 replies; 14+ messages in thread
From: Sunil V L @ 2025-08-19 4:25 UTC (permalink / raw)
To: Anup Patel
Cc: 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,
Troy Mitchell
On Mon, Aug 18, 2025 at 08:05:59PM +0530, Anup Patel wrote:
> The cppc_ffh_csr_read() and cppc_ffh_csr_write() returns Linux error
> code in "data->ret.error" so cpc_read_ffh() and cpc_write_ffh() must
> not use sbi_err_map_linux_errno() for FFH_CPPC_CSR.
>
> Fixes: 30f3ffbee86b ("ACPI: RISC-V: Add CPPC driver")
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
> ---
> drivers/acpi/riscv/cppc.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> index 440cf9fb91aa..42c1a9052470 100644
> --- a/drivers/acpi/riscv/cppc.c
> +++ b/drivers/acpi/riscv/cppc.c
> @@ -119,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
>
> *val = data.ret.value;
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
> @@ -148,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
>
> smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
> --
> 2.43.0
>
Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions
2025-08-19 4:13 ` Yao Zi
@ 2025-08-19 11:01 ` Anup Patel
0 siblings, 0 replies; 14+ messages in thread
From: Anup Patel @ 2025-08-19 11:01 UTC (permalink / raw)
To: Yao Zi
Cc: Mark Rutland, Alexandre Ghiti, Rafael J . Wysocki, Anup Patel,
Atish Patra, linux-kernel, linux-acpi, Palmer Dabbelt,
Paul Walmsley, linux-riscv, Andrew Jones, Will Deacon, Len Brown
On Tue, Aug 19, 2025 at 9:43 AM Yao Zi <ziyao@disroot.org> wrote:
>
> On Tue, Aug 19, 2025 at 09:00:03AM +0530, Anup Patel wrote:
> > On Tue, Aug 19, 2025 at 8:56 AM Yao Zi <ziyao@disroot.org> wrote:
> > >
> > > On Mon, Aug 18, 2025 at 08:06:00PM +0530, 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>
> > > > ---
> > > > 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 6fed42e37705..1540626b3540 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);
> > >
> > > I think it's more consistent to directly return the error code, and for
> > > csr_read_num, we could pass out the read value by a pointer. e.g.
> > >
> > > int csr_read_num(unsigned long csr_num, unsigned long *val);
> > > int csr_write_num(unsigned long csr_num, unsigned long val);
> > >
> > > This allows the caller to eliminate a variable for temporarily storing
> > > the error code if they use it just after the invokation, and fits the
> > > common convention of Linux better.
> >
> > Drew had similar comments so see my response in the previous
> > patch revision. (Refer, https://www.spinics.net/lists/kernel/msg5808113.html)
>
> Thanks for the reference.
>
> > I had considered this but the problem with this approach is that
> > individual switch cases in csr_read_num() become roughly 4
> > instructions because value read from CSR has to written to a memory
> > location.
>
> You could return a structure smaller than or equal to 2 * XLEN from
> csr_read_num(), according to the ABI it could be passed in a0 and a1 and
> thus should require no memory operation.
>
> Let's assume we have
>
> struct __csr_read_ret {
> long error;
> unsigned long value;
> };
>
> struct __csr_read_ret __csr_read_num(unsigned long csr_num);
>
> Then a wrapper like
>
> /* piece of untested code */
> static inline int csr_read_num(unsigned long csr_num,
> unsigned long *val)
> {
> struct __csr_read_ret ret = __csr_read_num(csr_num);
> *val = ret.value;
> return ret.error;
> }
>
> could provide an interface that I've talked about earlier, and it
> follows the kernel's convention.
Like I mentioned previously, the current implementation tries to
minimize instructions for each switch case and avoid unnecessary
memory load/store. Your alternate suggestion is no better in this
respect.
>
> > The current approach results in just 2 instructions for each
> > switch-case. Additionally, the current prototypes of csr_read_num()
> > and csr_write_num() are closer to csr_read() and csr_write()
> > respectively.
>
> But csr_read() and csr_write() never directly raise errors that is
> expected to be handled by the caller. I don't think it's a fair
> comparison.
csr_read_num() and csr_write_num() are different because
these functions take CSR number as parameter so caller can
pass an unsupported value to these functions which needs to
be reported back as an error.
Regards,
Anup
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
` (2 preceding siblings ...)
2025-08-19 4:25 ` Sunil V L
@ 2025-08-20 7:12 ` Alexandre Ghiti
3 siblings, 0 replies; 14+ messages in thread
From: Alexandre Ghiti @ 2025-08-20 7:12 UTC (permalink / raw)
To: Anup Patel, Sunil V L, Rafael J . Wysocki
Cc: Palmer Dabbelt, Paul Walmsley, Len Brown, Atish Patra,
Andrew Jones, Anup Patel, Will Deacon, Mark Rutland, linux-acpi,
linux-riscv, linux-kernel, Troy Mitchell
Hi Anup,
On 8/18/25 16:35, Anup Patel wrote:
> The cppc_ffh_csr_read() and cppc_ffh_csr_write() returns Linux error
> code in "data->ret.error" so cpc_read_ffh() and cpc_write_ffh() must
> not use sbi_err_map_linux_errno() for FFH_CPPC_CSR.
>
> Fixes: 30f3ffbee86b ("ACPI: RISC-V: Add CPPC driver")
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> Reviewed-by: Troy Mitchell <troy.mitchell@linux.dev>
> ---
> drivers/acpi/riscv/cppc.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/acpi/riscv/cppc.c b/drivers/acpi/riscv/cppc.c
> index 440cf9fb91aa..42c1a9052470 100644
> --- a/drivers/acpi/riscv/cppc.c
> +++ b/drivers/acpi/riscv/cppc.c
> @@ -119,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
>
> *val = data.ret.value;
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
> @@ -148,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_reg *reg, u64 val)
>
> smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1);
>
> - return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0;
> + return data.ret.error;
> }
>
> return -EINVAL;
I picked this up for fixes, cc stable and I'll send this patch for some
6.17-rcX.
Thanks,
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2025-08-20 7:26 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-18 14:35 [PATCH v2 0/2] Common csr_read_num() and csr_write_num() for RISC-V Anup Patel
2025-08-18 14:35 ` [PATCH v2 1/2] ACPI: RISC-V: Fix FFH_CPPC_CSR error handling Anup Patel
2025-08-18 19:26 ` Atish Patra
2025-08-19 4:02 ` Nutty.Liu
2025-08-19 4:25 ` Sunil V L
2025-08-20 7:12 ` Alexandre Ghiti
2025-08-18 14:36 ` [PATCH v2 2/2] RISC-V: Add common csr_read_num() and csr_write_num() functions Anup Patel
2025-08-18 14:56 ` Andrew Jones
2025-08-18 19:29 ` Atish Patra
2025-08-19 3:26 ` Yao Zi
2025-08-19 3:30 ` Anup Patel
2025-08-19 4:13 ` Yao Zi
2025-08-19 11:01 ` Anup Patel
2025-08-19 4:04 ` Nutty.Liu
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).