[PATCH v2 0/2] Risc-V cache operations

This patchset adds support for using the CBO instructions to perform the dcache flush/inval operations for the qemu-riscv board when those are enabled. The CBO instructions are defined in the Risc-V CMO specification which can be found at the link below: https://github.com/riscv/riscv-CMOs/blob/master/specifications/cmobase-v1.0....
Changes in v2: - Use cache functions in generic cache code instead of board specific code - Print the zicbom init status in case of a failure
Mayuresh Chitale (2): riscv: Add support for defining instructions riscv: cache: Add CBO instructions
arch/riscv/Kconfig | 4 ++ arch/riscv/include/asm/insn-def.h | 42 ++++++++++++++ arch/riscv/lib/cache.c | 96 +++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 arch/riscv/include/asm/insn-def.h

Add insn-def.h which is similar to that in linux and contains the macros to generate any instruction of type 'I' using the assembler's .insn directive.
Signed-off-by: Mayuresh Chitale mchitale@ventanamicro.com --- arch/riscv/include/asm/insn-def.h | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 arch/riscv/include/asm/insn-def.h
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h new file mode 100644 index 0000000000..99ad5b8f6a --- /dev/null +++ b/arch/riscv/include/asm/insn-def.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Ventana Micro Systems Ltd. + * + * Ported from linux insn-def.h. + */ + +#ifndef _ASM_RISCV_BARRIER_H +#define _ASM_RISCV_BARRIER_H + +#define INSN_I_SIMM12_SHIFT 20 +#define INSN_I_RS1_SHIFT 15 +#define INSN_I_FUNC3_SHIFT 12 +#define INSN_I_RD_SHIFT 7 +#define INSN_I_OPCODE_SHIFT 0 + +#define RV_OPCODE(v) __ASM_STR(v) +#define RV_FUNC3(v) __ASM_STR(v) +#define RV_FUNC7(v) __ASM_STR(v) +#define RV_SIMM12(v) __ASM_STR(v) +#define RV_RD(v) __ASM_STR(v) +#define RV_RS1(v) __ASM_STR(v) +#define RV_RS2(v) __ASM_STR(v) +#define __RV_REG(v) __ASM_STR(x ## v) +#define RV___RD(v) __RV_REG(v) +#define RV___RS1(v) __RV_REG(v) +#define RV___RS2(v) __RV_REG(v) + +#define RV_OPCODE_MISC_MEM RV_OPCODE(15) +#define RV_OPCODE_SYSTEM RV_OPCODE(115) + +#define RV_OPCODE_MISC_MEM RV_OPCODE(15) +#define RV_OPCODE_SYSTEM RV_OPCODE(115) + +#define __INSN_I(opcode, func3, rd, rs1, simm12) \ + ".insn i " opcode ", " func3 ", " rd ", " rs1 ", " simm12 "\n" + +#define INSN_I(opcode, func3, rd, rs1, simm12) \ + __INSN_I(RV_##opcode, RV_##func3, RV_##rd, \ + RV_##rs1, RV_##simm12) + +#endif /* _ASM_RISCV_BARRIER_H */

Hi Mayuresh,
On Fri, Aug 23, 2024 at 09:41:25AM +0000, Mayuresh Chitale wrote:
Add insn-def.h which is similar to that in linux and contains the macros to generate any instruction of type 'I' using the assembler's .insn directive.
Signed-off-by: Mayuresh Chitale mchitale@ventanamicro.com
arch/riscv/include/asm/insn-def.h | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 arch/riscv/include/asm/insn-def.h
diff --git a/arch/riscv/include/asm/insn-def.h b/arch/riscv/include/asm/insn-def.h new file mode 100644 index 0000000000..99ad5b8f6a --- /dev/null +++ b/arch/riscv/include/asm/insn-def.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/*
- Copyright (C) 2024 Ventana Micro Systems Ltd.
- Ported from linux insn-def.h.
- */
+#ifndef _ASM_RISCV_BARRIER_H +#define _ASM_RISCV_BARRIER_H
+#define INSN_I_SIMM12_SHIFT 20 +#define INSN_I_RS1_SHIFT 15 +#define INSN_I_FUNC3_SHIFT 12 +#define INSN_I_RD_SHIFT 7 +#define INSN_I_OPCODE_SHIFT 0
+#define RV_OPCODE(v) __ASM_STR(v) +#define RV_FUNC3(v) __ASM_STR(v) +#define RV_FUNC7(v) __ASM_STR(v) +#define RV_SIMM12(v) __ASM_STR(v) +#define RV_RD(v) __ASM_STR(v) +#define RV_RS1(v) __ASM_STR(v) +#define RV_RS2(v) __ASM_STR(v) +#define __RV_REG(v) __ASM_STR(x ## v) +#define RV___RD(v) __RV_REG(v) +#define RV___RS1(v) __RV_REG(v) +#define RV___RS2(v) __RV_REG(v)
+#define RV_OPCODE_MISC_MEM RV_OPCODE(15) +#define RV_OPCODE_SYSTEM RV_OPCODE(115)
+#define RV_OPCODE_MISC_MEM RV_OPCODE(15) +#define RV_OPCODE_SYSTEM RV_OPCODE(115)
These two lines are duplicated but I could fix this when merging the patch.
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com
+#define __INSN_I(opcode, func3, rd, rs1, simm12) \
- ".insn i " opcode ", " func3 ", " rd ", " rs1 ", " simm12 "\n"
+#define INSN_I(opcode, func3, rd, rs1, simm12) \
- __INSN_I(RV_##opcode, RV_##func3, RV_##rd, \
RV_##rs1, RV_##simm12)
+#endif /* _ASM_RISCV_BARRIER_H */

Define CBO inval and flush instructions and use those for the dcache inval and flush operations respectively.
Signed-off-by: Mayuresh Chitale mchitale@ventanamicro.com --- arch/riscv/Kconfig | 4 ++ arch/riscv/lib/cache.c | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index fa3b016c52..0f89d07be7 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -310,6 +310,10 @@ endmenu config RISCV_ISA_A def_bool y
+config RISCV_ISA_ZICBOM + bool "Zicbom support" + depends on !SYS_DISABLE_DCACHE_OPS + config DMA_ADDR_T_64BIT bool default y if 64BIT diff --git a/arch/riscv/lib/cache.c b/arch/riscv/lib/cache.c index afad7e117f..e184d5e205 100644 --- a/arch/riscv/lib/cache.c +++ b/arch/riscv/lib/cache.c @@ -5,6 +5,98 @@ */
#include <cpu_func.h> +#include <dm.h> +#include <asm/insn-def.h> +#include <linux/const.h> + +#define CBO_INVAL(base) \ + INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ + RS1(base), SIMM12(0)) +#define CBO_CLEAN(base) \ + INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ + RS1(base), SIMM12(1)) +#define CBO_FLUSH(base) \ + INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \ + RS1(base), SIMM12(2)) +enum { + CBO_CLEAN, + CBO_FLUSH, + CBO_INVAL +} riscv_cbo_ops; +static int zicbom_block_size; + +static inline void do_cbo_clean(unsigned long base) +{ + asm volatile ("add a0, %0, zero\n" CBO_CLEAN(%0) :: + "r"(base) : "memory"); +} + +static inline void do_cbo_flush(unsigned long base) +{ + asm volatile ("add a0, %0, zero\n" CBO_FLUSH(%0) :: + "r"(base) : "memory"); +} + +static inline void do_cbo_inval(unsigned long base) +{ + asm volatile ("add a0, %0, zero\n" CBO_INVAL(%0) :: + "r"(base) : "memory"); +} + +static void cbo_op(int op_type, unsigned long start, + unsigned long end) +{ + unsigned long op_size = end - start, size = 0; + void (*fn)(unsigned long base); + + switch (op_type) { + case CBO_CLEAN: + fn = do_cbo_clean; + break; + case CBO_FLUSH: + fn = do_cbo_flush; + break; + case CBO_INVAL: + fn = do_cbo_inval; + break; + } + start &= ~(UL(zicbom_block_size - 1)); + while (size < op_size) { + fn(start + size); + size += zicbom_block_size; + } +} + +void cbo_flush(unsigned long start, unsigned long end) +{ + if (zicbom_block_size) + cbo_op(CBO_FLUSH, start, end); +} + +void cbo_inval(unsigned long start, unsigned long end) +{ + if (zicbom_block_size) + cbo_op(CBO_INVAL, start, end); +} + +static int riscv_zicbom_init(void) +{ + struct udevice *dev; + + if (!CONFIG_IS_ENABLED(RISCV_ISA_ZICBOM) || zicbom_block_size) + return 1; + + uclass_first_device(UCLASS_CPU, &dev); + if (!dev) { + log_debug("Failed to get cpu device!\n"); + return 0; + } + + if (dev_read_u32(dev, "riscv,cbom-block-size", &zicbom_block_size)) + log_debug("riscv,cbom-block-size DT property not present\n"); + + return zicbom_block_size; +}
void invalidate_icache_all(void) { @@ -17,6 +109,7 @@ __weak void flush_dcache_all(void)
__weak void flush_dcache_range(unsigned long start, unsigned long end) { + cbo_flush(start, end); }
__weak void invalidate_icache_range(unsigned long start, unsigned long end) @@ -30,6 +123,7 @@ __weak void invalidate_icache_range(unsigned long start, unsigned long end)
__weak void invalidate_dcache_range(unsigned long start, unsigned long end) { + cbo_inval(start, end); }
void cache_flush(void) @@ -72,4 +166,6 @@ __weak int dcache_status(void)
__weak void enable_caches(void) { + if (!riscv_zicbom_init()) + log_info("Zicbom not initialized.\n"); }

On Fri, Aug 23, 2024 at 09:41:26AM +0000, Mayuresh Chitale wrote:
Define CBO inval and flush instructions and use those for the dcache inval and flush operations respectively.
Signed-off-by: Mayuresh Chitale mchitale@ventanamicro.com
arch/riscv/Kconfig | 4 ++ arch/riscv/lib/cache.c | 96 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+)
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com
participants (2)
-
Leo Liang
-
Mayuresh Chitale