Skip to content

Commit 1631ba1

Browse files
mmindpalmer-dabbelt
authored andcommitted
riscv: Add support for non-coherent devices using zicbom extension
The Zicbom ISA-extension was ratified in november 2021 and introduces instructions for dcache invalidate, clean and flush operations. Implement cache management operations for non-coherent devices based on them. Of course not all cores will support this, so implement an alternative-based mechanism that replaces empty instructions with ones done around Zicbom instructions. As discussed in previous versions, assume the platform being coherent by default so that non-coherent devices need to get marked accordingly by firmware. Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Heiko Stuebner <[email protected]> Reviewed-by: Guo Ren <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent d1afce6 commit 1631ba1

File tree

11 files changed

+208
-1
lines changed

11 files changed

+208
-1
lines changed

arch/riscv/Kconfig

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ config RISCV
113113
select MODULES_USE_ELF_RELA if MODULES
114114
select MODULE_SECTIONS if MODULES
115115
select OF
116+
select OF_DMA_DEFAULT_COHERENT
116117
select OF_EARLY_FLATTREE
117118
select OF_IRQ
118119
select PCI_DOMAINS_GENERIC if PCI
@@ -218,6 +219,14 @@ config PGTABLE_LEVELS
218219
config LOCKDEP_SUPPORT
219220
def_bool y
220221

222+
config RISCV_DMA_NONCOHERENT
223+
bool
224+
select ARCH_HAS_DMA_PREP_COHERENT
225+
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
226+
select ARCH_HAS_SYNC_DMA_FOR_CPU
227+
select ARCH_HAS_SETUP_DMA_OPS
228+
select DMA_DIRECT_REMAP
229+
221230
source "arch/riscv/Kconfig.socs"
222231
source "arch/riscv/Kconfig.erratas"
223232

@@ -376,6 +385,28 @@ config RISCV_ISA_SVPBMT
376385

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

388+
config CC_HAS_ZICBOM
389+
bool
390+
default y if 64BIT && $(cc-option,-mabi=lp64 -march=rv64ima_zicbom)
391+
default y if 32BIT && $(cc-option,-mabi=ilp32 -march=rv32ima_zicbom)
392+
393+
config RISCV_ISA_ZICBOM
394+
bool "Zicbom extension support for non-coherent DMA operation"
395+
depends on CC_HAS_ZICBOM
396+
depends on !XIP_KERNEL
397+
select RISCV_DMA_NONCOHERENT
398+
select RISCV_ALTERNATIVE
399+
default y
400+
help
401+
Adds support to dynamically detect the presence of the ZICBOM
402+
extension (Cache Block Management Operations) and enable its
403+
usage.
404+
405+
The Zicbom extension can be used to handle for example
406+
non-coherent DMA support on devices that need it.
407+
408+
If you don't know what to do here, say Y.
409+
379410
config FPU
380411
bool "FPU support"
381412
default y

arch/riscv/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
5656
toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
5757
riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
5858

59+
# Check if the toolchain supports Zicbom extension
60+
toolchain-supports-zicbom := $(call cc-option-yn, -march=$(riscv-march-y)_zicbom)
61+
riscv-march-$(toolchain-supports-zicbom) := $(riscv-march-y)_zicbom
62+
5963
KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
6064
KBUILD_AFLAGS += -march=$(riscv-march-y)
6165

arch/riscv/include/asm/cache.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
1313

14+
#ifdef CONFIG_RISCV_DMA_NONCOHERENT
15+
#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
16+
#endif
17+
1418
/*
1519
* RISC-V requires the stack pointer to be 16-byte aligned, so ensure that
1620
* the flat loader aligns it accordingly.

arch/riscv/include/asm/cacheflush.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ void flush_icache_mm(struct mm_struct *mm, bool local);
4242

4343
#endif /* CONFIG_SMP */
4444

45+
#ifdef CONFIG_RISCV_ISA_ZICBOM
46+
void riscv_init_cbom_blocksize(void);
47+
#else
48+
static inline void riscv_init_cbom_blocksize(void) { }
49+
#endif
50+
51+
#ifdef CONFIG_RISCV_DMA_NONCOHERENT
52+
void riscv_noncoherent_supported(void);
53+
#endif
54+
4555
/*
4656
* Bits in sys_riscv_flush_icache()'s flags argument.
4757
*/

arch/riscv/include/asm/errata_list.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
#endif
2121

2222
#define CPUFEATURE_SVPBMT 0
23-
#define CPUFEATURE_NUMBER 1
23+
#define CPUFEATURE_ZICBOM 1
24+
#define CPUFEATURE_NUMBER 2
2425

2526
#ifdef __ASSEMBLY__
2627

@@ -93,6 +94,22 @@ asm volatile(ALTERNATIVE( \
9394
#define ALT_THEAD_PMA(_val)
9495
#endif
9596

97+
#define ALT_CMO_OP(_op, _start, _size, _cachesize) \
98+
asm volatile(ALTERNATIVE( \
99+
__nops(5), \
100+
"mv a0, %1\n\t" \
101+
"j 2f\n\t" \
102+
"3:\n\t" \
103+
"cbo." __stringify(_op) " (a0)\n\t" \
104+
"add a0, a0, %0\n\t" \
105+
"2:\n\t" \
106+
"bltu a0, %2, 3b\n\t", 0, \
107+
CPUFEATURE_ZICBOM, CONFIG_RISCV_ISA_ZICBOM) \
108+
: : "r"(_cachesize), \
109+
"r"((unsigned long)(_start) & ~((_cachesize) - 1UL)), \
110+
"r"((unsigned long)(_start) + (_size)) \
111+
: "a0")
112+
96113
#endif /* __ASSEMBLY__ */
97114

98115
#endif

arch/riscv/include/asm/hwcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extern unsigned long elf_hwcap;
5454
enum riscv_isa_ext_id {
5555
RISCV_ISA_EXT_SSCOFPMF = RISCV_ISA_EXT_BASE,
5656
RISCV_ISA_EXT_SVPBMT,
57+
RISCV_ISA_EXT_ZICBOM,
5758
RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX,
5859
};
5960

arch/riscv/kernel/cpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ int riscv_of_parent_hartid(struct device_node *node)
8989
static struct riscv_isa_ext_data isa_ext_arr[] = {
9090
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
9191
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
92+
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
9293
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
9394
};
9495

arch/riscv/kernel/cpufeature.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/module.h>
1313
#include <linux/of.h>
1414
#include <asm/alternative.h>
15+
#include <asm/cacheflush.h>
1516
#include <asm/errata_list.h>
1617
#include <asm/hwcap.h>
1718
#include <asm/patch.h>
@@ -198,6 +199,7 @@ void __init riscv_fill_hwcap(void)
198199
} else {
199200
SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
200201
SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
202+
SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
201203
}
202204
#undef SET_ISA_EXT_MAP
203205
}
@@ -259,6 +261,25 @@ static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage)
259261
return false;
260262
}
261263

264+
static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage)
265+
{
266+
#ifdef CONFIG_RISCV_ISA_ZICBOM
267+
switch (stage) {
268+
case RISCV_ALTERNATIVES_EARLY_BOOT:
269+
return false;
270+
default:
271+
if (riscv_isa_extension_available(NULL, ZICBOM)) {
272+
riscv_noncoherent_supported();
273+
return true;
274+
} else {
275+
return false;
276+
}
277+
}
278+
#endif
279+
280+
return false;
281+
}
282+
262283
/*
263284
* Probe presence of individual extensions.
264285
*
@@ -273,6 +294,9 @@ static u32 __init_or_module cpufeature_probe(unsigned int stage)
273294
if (cpufeature_probe_svpbmt(stage))
274295
cpu_req_feature |= (1U << CPUFEATURE_SVPBMT);
275296

297+
if (cpufeature_probe_zicbom(stage))
298+
cpu_req_feature |= (1U << CPUFEATURE_ZICBOM);
299+
276300
return cpu_req_feature;
277301
}
278302

arch/riscv/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/crash_dump.h>
2323

2424
#include <asm/alternative.h>
25+
#include <asm/cacheflush.h>
2526
#include <asm/cpu_ops.h>
2627
#include <asm/early_ioremap.h>
2728
#include <asm/pgtable.h>
@@ -296,6 +297,7 @@ void __init setup_arch(char **cmdline_p)
296297
#endif
297298

298299
riscv_fill_hwcap();
300+
riscv_init_cbom_blocksize();
299301
apply_boot_alternatives();
300302
}
301303

arch/riscv/mm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ endif
3030
endif
3131

3232
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
33+
obj-$(CONFIG_RISCV_DMA_NONCOHERENT) += dma-noncoherent.o

0 commit comments

Comments
 (0)