From: Lad Prabhakar <[email protected]>
Hi All,
non-coherent DMA support for AX45MP
====================================
On the Andes AX45MP core, cache coherency is a specification option so it
may not be supported. In this case DMA will fail. To get around with this
issue this patch series does the below:
1] Andes alternative ports is implemented as errata which checks if the
IOCP is missing and only then applies to CMO errata. One vendor specific
SBI EXT (ANDES_SBI_EXT_IOCP_SW_WORKAROUND) is implemented as part of
errata.
Below are the configs which Andes port provides (and are selected by
RZ/Five):
- ERRATA_ANDES
- ERRATA_ANDES_CMO
OpenSBI patch supporting ANDES_SBI_EXT_IOCP_SW_WORKAROUND SBI is now
part v1.3 release.
2] Andes AX45MP core has a Programmable Physical Memory Attributes (PMA)
block that allows dynamic adjustment of memory attributes in the runtime.
It contains a configurable amount of PMA entries implemented as CSR
registers to control the attributes of memory locations in interest.
OpenSBI configures the PMA regions as required and creates a reserve memory
node and propagates it to the higher boot stack.
Currently OpenSBI (upstream) configures the required PMA region and passes
this a shared DMA pool to Linux.
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
pma_resv0@58000000 {
compatible = "shared-dma-pool";
reg = <0x0 0x58000000 0x0 0x08000000>;
no-map;
linux,dma-default;
};
};
The above shared DMA pool gets appended to Linux DTB so the DMA memory
requests go through this region.
3] We provide callbacks to synchronize specific content between memory and
cache.
4] RZ/Five SoC selects the below configs
- AX45MP_L2_CACHE
- DMA_GLOBAL_POOL
- ERRATA_ANDES
- ERRATA_ANDES_CMO
----------x---------------------x--------------------x---------------x----
Note,
- Ive used GCC 12.2.0 for compilation
- Tested all the IP blocks on RZ/Five which use DMA
- Patch series is dependent on the series from Arnd,
https://patchwork.kernel.org/project/linux-riscv/cover/[email protected]/.
(Ive rebased Arnd's series on v6.4-rc-1)
- Patches applies on top of palmer/for-next (669ee914f515)
- Ive pushed the complete tree here https://github.com/prabhakarlad/linux/commits/rzfive-cmo-v10
- Previously the function pointer approach was NAKed by Christoph Hellwig
but based on the discussion on #riscv Ive implemented this approach.
v9 -> v10
* Included RB/TB tags from Conor
* Fixed review comments pointed by Geert to rename cache callbacks
* Dropped preserving the cache lines in ax45mp_dma_cache_inv() callback
v8 -> v9
* Dropped adding ALTERNATIVE_3
* Implemented function pointer support for nonstandard noncoherent systems
* Added a new config option CONFIG_RISCV_NONSTANDARD_CACHE_OPS
* Updated Andes errata code to drop patching the calls as we no more use
ALTERNATIVE_X() macro.
* Updated Andes CMO code to use function pointer for doing cache management.
v7 -> v8
* Dropped using function pointers and switched to ALTERNATIVE_X()
* Added new patches (#1, #2)
v6 -> v7
* Reworked the code based on Arnd's work
* Fixed review comments pointed by Arnd
* Fixed review comments pointed by Conor
v5.1 -> v6
* Dropped use of ALTERNATIVE_x() macro
* Now switched to used function pointers for CMO
* Moved driver to drivers/cache folder
v5 -> v5.1
* https://patchwork.kernel.org/project/linux-riscv/list/?series=708610&state=%2A&archive=both
v4 -> v5
* Rebased ALTERNATIVE_3() macro on top of Andrew's patches
* Rebased the changes on top of Heiko's alternative call patches
* Dropped configuring the PMA from Linux
* Dropped configuring the L2 cache from Linux and dropped the binding for same
* Now using runtime patching mechanism instead of compile time config
RFC v3 -> v4
* Implemented ALTERNATIVE_3() macro
* Now using runtime patching mechanism instead of compile time config
* Added Andes CMO as and errata
* Fixed comments pointed by Geert
RFC v2-> RFC v3
* Fixed review comments pointed by Conor
* Move DT binding into cache folder
* Fixed DT binding check issue
* Added andestech,ax45mp-cache.h header file
* Now passing the flags for the PMA setup as part of andestech,pma-regions
property.
* Added andestech,inst/data-prefetch and andestech,tag/data-ram-ctl
properties to configure the L2 cache.
* Registered the cache driver as platform driver
RFC v1-> RFC v2
* Moved out the code from arc/riscv to drivers/soc/renesas
* Now handling the PMA setup as part of the L2 cache
* Now making use of dma-noncoherent.c instead SoC specific implementation.
* Dropped arch_dma_alloc() and arch_dma_free()
* Switched to RISCV_DMA_NONCOHERENT
* Included DT binding doc
RFC v2: https://patchwork.kernel.org/project/linux-renesas-soc/cover/[email protected]/
RFC v1: https://patchwork.kernel.org/project/linux-renesas-soc/cover/[email protected]/
Cheers,
Prabhakar
Lad Prabhakar (6):
riscv: asm: vendorid_list: Add Andes Technology to the vendors list
riscv: errata: Add Andes alternative ports
riscv: mm: dma-noncoherent: nonstandard cache operations support
dt-bindings: cache: andestech,ax45mp-cache: Add DT binding
documentation for L2 cache controller
cache: Add L2 cache management for Andes AX45MP RISC-V core
soc: renesas: Kconfig: Select the required configs for RZ/Five SoC
.../cache/andestech,ax45mp-cache.yaml | 81 +++++++
MAINTAINERS | 7 +
arch/riscv/Kconfig | 7 +
arch/riscv/Kconfig.errata | 21 ++
arch/riscv/errata/Makefile | 1 +
arch/riscv/errata/andes/Makefile | 1 +
arch/riscv/errata/andes/errata.c | 66 ++++++
arch/riscv/include/asm/alternative.h | 3 +
arch/riscv/include/asm/dma-noncoherent.h | 28 +++
arch/riscv/include/asm/errata_list.h | 5 +
arch/riscv/include/asm/vendorid_list.h | 1 +
arch/riscv/kernel/alternative.c | 5 +
arch/riscv/mm/dma-noncoherent.c | 43 ++++
arch/riscv/mm/pmem.c | 13 ++
drivers/Kconfig | 2 +
drivers/Makefile | 1 +
drivers/cache/Kconfig | 11 +
drivers/cache/Makefile | 3 +
drivers/cache/ax45mp_cache.c | 213 ++++++++++++++++++
drivers/soc/renesas/Kconfig | 4 +
20 files changed, 516 insertions(+)
create mode 100644 Documentation/devicetree/bindings/cache/andestech,ax45mp-cache.yaml
create mode 100644 arch/riscv/errata/andes/Makefile
create mode 100644 arch/riscv/errata/andes/errata.c
create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
create mode 100644 drivers/cache/Kconfig
create mode 100644 drivers/cache/Makefile
create mode 100644 drivers/cache/ax45mp_cache.c
--
2.34.1
From: Lad Prabhakar <[email protected]>
Add required ports of the Alternative scheme for Andes CPU cores.
I/O Coherence Port (IOCP) provides an AXI interface for connecting external
non-caching masters, such as DMA controllers. IOCP is a specification
option and is disabled on the Renesas RZ/Five SoC due to this reason cache
management needs a software workaround.
Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Conor Dooley <[email protected]>
Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
---
v9 -> v10
* Included TB tag from Conor
v8 -> v9
* Rebased to code on Palmer's for/next
* Dropped calling patch_text_nosync() as dont use
patch_text_nosync() call
v7 -> v8
* Now patching the code using patch_text_nosync() and riscv_alternative_fix_offsets()
v6 -> v7
* Renamed RZFIVE_SBI_EXT_IOCP_SW_WORKAROUND -> ANDES_SBI_EXT_IOCP_SW_WORKAROUND
* Dropped "depends on !XIP_KERNEL" for ERRATA_ANDES config
v5 -> v6
* Dropped patching alternative and now just probing IOCP
v4 -> v5
* Sorted the Kconfig/Makefile/Switch based on Core name
* Added a comments
* Introduced RZFIVE_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT ID to check if
CMO needs to be applied. Is there a way we can access the DTB while patching
as we can drop this SBI EXT ID and add a DT property instead for cmo?
RFC v3 -> v4
* New patch
---
arch/riscv/Kconfig.errata | 21 +++++++++
arch/riscv/errata/Makefile | 1 +
arch/riscv/errata/andes/Makefile | 1 +
arch/riscv/errata/andes/errata.c | 66 ++++++++++++++++++++++++++++
arch/riscv/include/asm/alternative.h | 3 ++
arch/riscv/include/asm/errata_list.h | 5 +++
arch/riscv/kernel/alternative.c | 5 +++
7 files changed, 102 insertions(+)
create mode 100644 arch/riscv/errata/andes/Makefile
create mode 100644 arch/riscv/errata/andes/errata.c
diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
index 0c8f4652cd82..92c779764b27 100644
--- a/arch/riscv/Kconfig.errata
+++ b/arch/riscv/Kconfig.errata
@@ -1,5 +1,26 @@
menu "CPU errata selection"
+config ERRATA_ANDES
+ bool "Andes AX45MP errata"
+ depends on RISCV_ALTERNATIVE
+ help
+ All Andes errata Kconfig depend on this Kconfig. Disabling
+ this Kconfig will disable all Andes errata. Please say "Y"
+ here if your platform uses Andes CPU cores.
+
+ Otherwise, please say "N" here to avoid unnecessary overhead.
+
+config ERRATA_ANDES_CMO
+ bool "Apply Andes cache management errata"
+ depends on ERRATA_ANDES && MMU && ARCH_R9A07G043
+ select RISCV_DMA_NONCOHERENT
+ default y
+ help
+ This will apply the cache management errata to handle the
+ non-standard handling on non-coherent operations on Andes cores.
+
+ If you don't know what to do here, say "Y".
+
config ERRATA_SIFIVE
bool "SiFive errata"
depends on RISCV_ALTERNATIVE
diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
index 7b2637c8c332..8a2739485123 100644
--- a/arch/riscv/errata/Makefile
+++ b/arch/riscv/errata/Makefile
@@ -2,5 +2,6 @@ ifdef CONFIG_RELOCATABLE
KBUILD_CFLAGS += -fno-pie
endif
+obj-$(CONFIG_ERRATA_ANDES) += andes/
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
obj-$(CONFIG_ERRATA_THEAD) += thead/
diff --git a/arch/riscv/errata/andes/Makefile b/arch/riscv/errata/andes/Makefile
new file mode 100644
index 000000000000..2d644e19caef
--- /dev/null
+++ b/arch/riscv/errata/andes/Makefile
@@ -0,0 +1 @@
+obj-y += errata.o
diff --git a/arch/riscv/errata/andes/errata.c b/arch/riscv/errata/andes/errata.c
new file mode 100644
index 000000000000..197db68cc8da
--- /dev/null
+++ b/arch/riscv/errata/andes/errata.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Erratas to be applied for Andes CPU cores
+ *
+ * Copyright (C) 2023 Renesas Electronics Corporation.
+ *
+ * Author: Lad Prabhakar <[email protected]>
+ */
+
+#include <linux/memory.h>
+#include <linux/module.h>
+
+#include <asm/alternative.h>
+#include <asm/cacheflush.h>
+#include <asm/errata_list.h>
+#include <asm/patch.h>
+#include <asm/processor.h>
+#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
+
+#define ANDESTECH_AX45MP_MARCHID 0x8000000000008a45UL
+#define ANDESTECH_AX45MP_MIMPID 0x500UL
+#define ANDESTECH_SBI_EXT_ANDES 0x0900031E
+
+#define ANDES_SBI_EXT_IOCP_SW_WORKAROUND 1
+
+static long ax45mp_iocp_sw_workaround(void)
+{
+ struct sbiret ret;
+
+ /*
+ * ANDES_SBI_EXT_IOCP_SW_WORKAROUND SBI EXT checks if the IOCP is missing and
+ * cache is controllable only then CMO will be applied to the platform.
+ */
+ ret = sbi_ecall(ANDESTECH_SBI_EXT_ANDES, ANDES_SBI_EXT_IOCP_SW_WORKAROUND,
+ 0, 0, 0, 0, 0, 0);
+
+ return ret.error ? 0 : ret.value;
+}
+
+static bool errata_probe_iocp(unsigned int stage, unsigned long arch_id, unsigned long impid)
+{
+ if (!IS_ENABLED(CONFIG_ERRATA_ANDES_CMO))
+ return false;
+
+ if (arch_id != ANDESTECH_AX45MP_MARCHID || impid != ANDESTECH_AX45MP_MIMPID)
+ return false;
+
+ if (!ax45mp_iocp_sw_workaround())
+ return false;
+
+ /* Set this just to make core cbo code happy */
+ riscv_cbom_block_size = 1;
+ riscv_noncoherent_supported();
+
+ return true;
+}
+
+void __init_or_module andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage)
+{
+ errata_probe_iocp(stage, archid, impid);
+
+ /* we have nothing to patch here ATM so just return back */
+}
diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
index 6a41537826a7..f6cfca939c92 100644
--- a/arch/riscv/include/asm/alternative.h
+++ b/arch/riscv/include/asm/alternative.h
@@ -46,6 +46,9 @@ struct alt_entry {
u32 patch_id; /* The patch ID (erratum ID or cpufeature ID) */
};
+void andes_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
+ unsigned long archid, unsigned long impid,
+ unsigned int stage);
void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
unsigned long archid, unsigned long impid,
unsigned int stage);
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index fb1a810f3d8c..e2ecd01bfac7 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -11,6 +11,11 @@
#include <asm/hwcap.h>
#include <asm/vendorid_list.h>
+#ifdef CONFIG_ERRATA_ANDES
+#define ERRATA_ANDESTECH_NO_IOCP 0
+#define ERRATA_ANDESTECH_NUMBER 1
+#endif
+
#ifdef CONFIG_ERRATA_SIFIVE
#define ERRATA_SIFIVE_CIP_453 0
#define ERRATA_SIFIVE_CIP_1200 1
diff --git a/arch/riscv/kernel/alternative.c b/arch/riscv/kernel/alternative.c
index 6b75788c18e6..b0345992a35e 100644
--- a/arch/riscv/kernel/alternative.c
+++ b/arch/riscv/kernel/alternative.c
@@ -45,6 +45,11 @@ static void riscv_fill_cpu_mfr_info(struct cpu_manufacturer_info_t *cpu_mfr_info
cpu_mfr_info->feature_probe_func = NULL;
switch (cpu_mfr_info->vendor_id) {
+#ifdef CONFIG_ERRATA_ANDES
+ case ANDESTECH_VENDOR_ID:
+ cpu_mfr_info->patch_func = andes_errata_patch_func;
+ break;
+#endif
#ifdef CONFIG_ERRATA_SIFIVE
case SIFIVE_VENDOR_ID:
cpu_mfr_info->patch_func = sifive_errata_patch_func;
--
2.34.1
From: Lad Prabhakar <[email protected]>
Add Andes Technology to the vendors list.
Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Heiko Stuebner <[email protected]>
Reviewed-by: Conor Dooley <[email protected]>
Reviewed-by: Geert Uytterhoeven <[email protected]>
Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
---
v9 -> v10
* Included TB tag from Conor
v8 -> v9
* Included RB tag from Geert
v7 -> v8
* No change
v6 -> v7
* No change
v5 -> v6
* No change
v4 -> v5
* Included RB tags
RFC v3 -> v4
* New patch
---
arch/riscv/include/asm/vendorid_list.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index cb89af3f0704..e55407ace0c3 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -5,6 +5,7 @@
#ifndef ASM_VENDOR_LIST_H
#define ASM_VENDOR_LIST_H
+#define ANDESTECH_VENDOR_ID 0x31e
#define SIFIVE_VENDOR_ID 0x489
#define THEAD_VENDOR_ID 0x5b7
--
2.34.1
From: Lad Prabhakar <[email protected]>
Introduce support for nonstandard noncoherent systems in the RISC-V
architecture. It enables function pointer support to handle cache
management in such systems.
This patch adds a new configuration option called
"RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
support for cache management in nonstandard noncoherent systems.
Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Conor Dooley <[email protected]>
Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
---
v9 -> v10
* Added __ro_after_init compiler attribute for noncoherent_cache_ops
* Renamed clean -> wback
* Renamed inval -> inv
* Renamed flush -> wback_inv
v8 -> v9
* New patch
---
arch/riscv/Kconfig | 7 ++++
arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
arch/riscv/mm/pmem.c | 13 +++++++
4 files changed, 91 insertions(+)
create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index d9e451ac862a..42c86b13c5e1 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
select DMA_DIRECT_REMAP
+config RISCV_NONSTANDARD_CACHE_OPS
+ bool
+ depends on RISCV_DMA_NONCOHERENT
+ help
+ This enables function pointer support for non-standard noncoherent
+ systems to handle cache management.
+
config AS_HAS_INSN
def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
new file mode 100644
index 000000000000..969cf1f1363a
--- /dev/null
+++ b/arch/riscv/include/asm/dma-noncoherent.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2023 Renesas Electronics Corp.
+ */
+
+#ifndef __ASM_DMA_NONCOHERENT_H
+#define __ASM_DMA_NONCOHERENT_H
+
+#include <linux/dma-direct.h>
+
+/*
+ * struct riscv_cache_ops - Structure for CMO function pointers
+ *
+ * @wback: Function pointer for cache writeback
+ * @inv: Function pointer for invalidating cache
+ * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
+ */
+struct riscv_cache_ops {
+ void (*wback)(phys_addr_t paddr, unsigned long size);
+ void (*inv)(phys_addr_t paddr, unsigned long size);
+ void (*wback_inv)(phys_addr_t paddr, unsigned long size);
+};
+
+extern struct riscv_cache_ops noncoherent_cache_ops;
+
+void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops);
+
+#endif /* __ASM_DMA_NONCOHERENT_H */
diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
index b9a9f57e02be..4c2e3f1cdfe6 100644
--- a/arch/riscv/mm/dma-noncoherent.c
+++ b/arch/riscv/mm/dma-noncoherent.c
@@ -9,13 +9,26 @@
#include <linux/dma-map-ops.h>
#include <linux/mm.h>
#include <asm/cacheflush.h>
+#include <asm/dma-noncoherent.h>
static bool noncoherent_supported;
+struct riscv_cache_ops noncoherent_cache_ops __ro_after_init = {
+ .wback = NULL,
+ .inv = NULL,
+ .wback_inv = NULL,
+};
+
static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.wback)) {
+ noncoherent_cache_ops.wback(paddr, size);
+ return;
+ }
+#endif
ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
}
@@ -23,6 +36,13 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.inv)) {
+ noncoherent_cache_ops.inv(paddr, size);
+ return;
+ }
+#endif
+
ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
}
@@ -30,6 +50,13 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
{
void *vaddr = phys_to_virt(paddr);
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.wback_inv)) {
+ noncoherent_cache_ops.wback_inv(paddr, size);
+ return;
+ }
+#endif
+
ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
}
@@ -50,6 +77,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
{
void *flush_addr = page_address(page);
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.wback_inv)) {
+ noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
+ return;
+ }
+#endif
+
ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
}
@@ -75,3 +109,12 @@ void riscv_noncoherent_supported(void)
"Non-coherent DMA support enabled without a block size\n");
noncoherent_supported = true;
}
+
+void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops)
+{
+ if (!ops)
+ return;
+
+ noncoherent_cache_ops = *ops;
+}
+EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
index 089df92ae876..c5fc5ec96f6d 100644
--- a/arch/riscv/mm/pmem.c
+++ b/arch/riscv/mm/pmem.c
@@ -7,15 +7,28 @@
#include <linux/libnvdimm.h>
#include <asm/cacheflush.h>
+#include <asm/dma-noncoherent.h>
void arch_wb_cache_pmem(void *addr, size_t size)
{
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.wback)) {
+ noncoherent_cache_ops.wback(virt_to_phys(addr), size);
+ return;
+ }
+#endif
ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
void arch_invalidate_pmem(void *addr, size_t size)
{
+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
+ if (unlikely(noncoherent_cache_ops.inv)) {
+ noncoherent_cache_ops.inv(virt_to_phys(addr), size);
+ return;
+ }
+#endif
ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
}
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
--
2.34.1
On Sun, 2 Jul 2023 at 22:36, Prabhakar <[email protected]> wrote:
>
> From: Lad Prabhakar <[email protected]>
>
> Introduce support for nonstandard noncoherent systems in the RISC-V
> architecture. It enables function pointer support to handle cache
> management in such systems.
>
> This patch adds a new configuration option called
> "RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
> depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
> support for cache management in nonstandard noncoherent systems.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> Reviewed-by: Conor Dooley <[email protected]>
> Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
> ---
> v9 -> v10
> * Added __ro_after_init compiler attribute for noncoherent_cache_ops
> * Renamed clean -> wback
> * Renamed inval -> inv
> * Renamed flush -> wback_inv
>
> v8 -> v9
> * New patch
> ---
> arch/riscv/Kconfig | 7 ++++
> arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
> arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
> arch/riscv/mm/pmem.c | 13 +++++++
> 4 files changed, 91 insertions(+)
> create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index d9e451ac862a..42c86b13c5e1 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
> select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> select DMA_DIRECT_REMAP
>
> +config RISCV_NONSTANDARD_CACHE_OPS
> + bool
> + depends on RISCV_DMA_NONCOHERENT
> + help
> + This enables function pointer support for non-standard noncoherent
> + systems to handle cache management.
> +
> config AS_HAS_INSN
> def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
>
> diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> new file mode 100644
> index 000000000000..969cf1f1363a
> --- /dev/null
> +++ b/arch/riscv/include/asm/dma-noncoherent.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2023 Renesas Electronics Corp.
> + */
> +
> +#ifndef __ASM_DMA_NONCOHERENT_H
> +#define __ASM_DMA_NONCOHERENT_H
> +
> +#include <linux/dma-direct.h>
> +
> +/*
> + * struct riscv_cache_ops - Structure for CMO function pointers
> + *
> + * @wback: Function pointer for cache writeback
> + * @inv: Function pointer for invalidating cache
> + * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
> + */
> +struct riscv_cache_ops {
> + void (*wback)(phys_addr_t paddr, unsigned long size);
> + void (*inv)(phys_addr_t paddr, unsigned long size);
> + void (*wback_inv)(phys_addr_t paddr, unsigned long size);
Hi Prabhakar
Just a quick question. After Arnd's patchset the
arch_dma_cache{inv,wback,wback_inv} functions take a phys_addr_t and
size_t, but here you want these callbacks to take a phys_addr_t and
unsigned long instead. Why not keep them using size_t?
> +};
> +
> +extern struct riscv_cache_ops noncoherent_cache_ops;
> +
> +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops);
> +
> +#endif /* __ASM_DMA_NONCOHERENT_H */
> diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> index b9a9f57e02be..4c2e3f1cdfe6 100644
> --- a/arch/riscv/mm/dma-noncoherent.c
> +++ b/arch/riscv/mm/dma-noncoherent.c
> @@ -9,13 +9,26 @@
> #include <linux/dma-map-ops.h>
> #include <linux/mm.h>
> #include <asm/cacheflush.h>
> +#include <asm/dma-noncoherent.h>
>
> static bool noncoherent_supported;
>
> +struct riscv_cache_ops noncoherent_cache_ops __ro_after_init = {
> + .wback = NULL,
> + .inv = NULL,
> + .wback_inv = NULL,
> +};
> +
> static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback)) {
> + noncoherent_cache_ops.wback(paddr, size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -23,6 +36,13 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.inv)) {
> + noncoherent_cache_ops.inv(paddr, size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -30,6 +50,13 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> + noncoherent_cache_ops.wback_inv(paddr, size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -50,6 +77,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
> {
> void *flush_addr = page_address(page);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> + noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
> }
>
> @@ -75,3 +109,12 @@ void riscv_noncoherent_supported(void)
> "Non-coherent DMA support enabled without a block size\n");
> noncoherent_supported = true;
> }
> +
> +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops)
> +{
> + if (!ops)
> + return;
> +
> + noncoherent_cache_ops = *ops;
> +}
> +EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
> diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
> index 089df92ae876..c5fc5ec96f6d 100644
> --- a/arch/riscv/mm/pmem.c
> +++ b/arch/riscv/mm/pmem.c
> @@ -7,15 +7,28 @@
> #include <linux/libnvdimm.h>
>
> #include <asm/cacheflush.h>
> +#include <asm/dma-noncoherent.h>
>
> void arch_wb_cache_pmem(void *addr, size_t size)
> {
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback)) {
> + noncoherent_cache_ops.wback(virt_to_phys(addr), size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
> }
> EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
>
> void arch_invalidate_pmem(void *addr, size_t size)
> {
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.inv)) {
> + noncoherent_cache_ops.inv(virt_to_phys(addr), size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
> }
> EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
> --
> 2.34.1
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Hi Emil,
Thank you for the review.
On Mon, Jul 24, 2023 at 11:18 AM Emil Renner Berthing
<[email protected]> wrote:
>
> On Sun, 2 Jul 2023 at 22:36, Prabhakar <[email protected]> wrote:
> >
> > From: Lad Prabhakar <[email protected]>
> >
> > Introduce support for nonstandard noncoherent systems in the RISC-V
> > architecture. It enables function pointer support to handle cache
> > management in such systems.
> >
> > This patch adds a new configuration option called
> > "RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
> > depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
> > support for cache management in nonstandard noncoherent systems.
> >
> > Signed-off-by: Lad Prabhakar <[email protected]>
> > Reviewed-by: Conor Dooley <[email protected]>
> > Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
> > ---
> > v9 -> v10
> > * Added __ro_after_init compiler attribute for noncoherent_cache_ops
> > * Renamed clean -> wback
> > * Renamed inval -> inv
> > * Renamed flush -> wback_inv
> >
> > v8 -> v9
> > * New patch
> > ---
> > arch/riscv/Kconfig | 7 ++++
> > arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
> > arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
> > arch/riscv/mm/pmem.c | 13 +++++++
> > 4 files changed, 91 insertions(+)
> > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index d9e451ac862a..42c86b13c5e1 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> > select DMA_DIRECT_REMAP
> >
> > +config RISCV_NONSTANDARD_CACHE_OPS
> > + bool
> > + depends on RISCV_DMA_NONCOHERENT
> > + help
> > + This enables function pointer support for non-standard noncoherent
> > + systems to handle cache management.
> > +
> > config AS_HAS_INSN
> > def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
> >
> > diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> > new file mode 100644
> > index 000000000000..969cf1f1363a
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/dma-noncoherent.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2023 Renesas Electronics Corp.
> > + */
> > +
> > +#ifndef __ASM_DMA_NONCOHERENT_H
> > +#define __ASM_DMA_NONCOHERENT_H
> > +
> > +#include <linux/dma-direct.h>
> > +
> > +/*
> > + * struct riscv_cache_ops - Structure for CMO function pointers
> > + *
> > + * @wback: Function pointer for cache writeback
> > + * @inv: Function pointer for invalidating cache
> > + * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
> > + */
> > +struct riscv_cache_ops {
> > + void (*wback)(phys_addr_t paddr, unsigned long size);
> > + void (*inv)(phys_addr_t paddr, unsigned long size);
> > + void (*wback_inv)(phys_addr_t paddr, unsigned long size);
>
> Hi Prabhakar
>
> Just a quick question. After Arnd's patchset the
> arch_dma_cache{inv,wback,wback_inv} functions take a phys_addr_t and
> size_t, but here you want these callbacks to take a phys_addr_t and
> unsigned long instead. Why not keep them using size_t?
>
Agreed, I will update it to use size_t instead.
Cheers,
Prabhakar
On Sun, Jul 02, 2023 at 09:34:26PM +0100, Prabhakar wrote:
> From: Lad Prabhakar <[email protected]>
>
> Introduce support for nonstandard noncoherent systems in the RISC-V
> architecture. It enables function pointer support to handle cache
> management in such systems.
>
> This patch adds a new configuration option called
> "RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
> depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
> support for cache management in nonstandard noncoherent systems.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> Reviewed-by: Conor Dooley <[email protected]>
> Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
> ---
> v9 -> v10
> * Added __ro_after_init compiler attribute for noncoherent_cache_ops
> * Renamed clean -> wback
> * Renamed inval -> inv
> * Renamed flush -> wback_inv
>
> v8 -> v9
> * New patch
> ---
> arch/riscv/Kconfig | 7 ++++
> arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
> arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
> arch/riscv/mm/pmem.c | 13 +++++++
> 4 files changed, 91 insertions(+)
> create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
>
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index d9e451ac862a..42c86b13c5e1 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
> select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> select DMA_DIRECT_REMAP
>
> +config RISCV_NONSTANDARD_CACHE_OPS
> + bool
> + depends on RISCV_DMA_NONCOHERENT
> + help
> + This enables function pointer support for non-standard noncoherent
> + systems to handle cache management.
Per Documentation/riscv/patch-acceptance.rst:
"we'll only consider patches for extensions that either:
- Have been officially frozen or ratified by the RISC-V Foundation, or
- Have been implemented in hardware that is widely available, per standard
Linux practice."
I'm not sure which item this patch series belongs to.
> +
> config AS_HAS_INSN
> def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
>
> diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> new file mode 100644
> index 000000000000..969cf1f1363a
> --- /dev/null
> +++ b/arch/riscv/include/asm/dma-noncoherent.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2023 Renesas Electronics Corp.
> + */
> +
> +#ifndef __ASM_DMA_NONCOHERENT_H
> +#define __ASM_DMA_NONCOHERENT_H
> +
> +#include <linux/dma-direct.h>
> +
> +/*
> + * struct riscv_cache_ops - Structure for CMO function pointers
can we reword this line as
"struct riscv_nonstd_cache_ops - Structure for non-standard CMO function
pointers" to explictly note this is only for non-standard CMO.
> + *
> + * @wback: Function pointer for cache writeback
> + * @inv: Function pointer for invalidating cache
> + * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
> + */
> +struct riscv_cache_ops {
> + void (*wback)(phys_addr_t paddr, unsigned long size);
> + void (*inv)(phys_addr_t paddr, unsigned long size);
> + void (*wback_inv)(phys_addr_t paddr, unsigned long size);
> +};
> +
> +extern struct riscv_cache_ops noncoherent_cache_ops;
> +
> +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops);
> +
> +#endif /* __ASM_DMA_NONCOHERENT_H */
> diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> index b9a9f57e02be..4c2e3f1cdfe6 100644
> --- a/arch/riscv/mm/dma-noncoherent.c
> +++ b/arch/riscv/mm/dma-noncoherent.c
> @@ -9,13 +9,26 @@
> #include <linux/dma-map-ops.h>
> #include <linux/mm.h>
> #include <asm/cacheflush.h>
> +#include <asm/dma-noncoherent.h>
>
> static bool noncoherent_supported;
>
> +struct riscv_cache_ops noncoherent_cache_ops __ro_after_init = {
> + .wback = NULL,
> + .inv = NULL,
> + .wback_inv = NULL,
> +};
> +
> static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback)) {
I'm worried about the performance impact here.
For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
enabled by default, so standard CMO and T-HEAD's CMO platform's
performance will be impacted, because even an unlikely is put
here, the check action still needs to be done.
> + noncoherent_cache_ops.wback(paddr, size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -23,6 +36,13 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.inv)) {
> + noncoherent_cache_ops.inv(paddr, size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -30,6 +50,13 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
> {
> void *vaddr = phys_to_virt(paddr);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> + noncoherent_cache_ops.wback_inv(paddr, size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
> }
>
> @@ -50,6 +77,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
> {
> void *flush_addr = page_address(page);
>
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> + noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
> + return;
> + }
> +#endif
> +
> ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
> }
>
> @@ -75,3 +109,12 @@ void riscv_noncoherent_supported(void)
> "Non-coherent DMA support enabled without a block size\n");
> noncoherent_supported = true;
> }
> +
> +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops)
> +{
> + if (!ops)
> + return;
> +
> + noncoherent_cache_ops = *ops;
> +}
> +EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
> diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
> index 089df92ae876..c5fc5ec96f6d 100644
> --- a/arch/riscv/mm/pmem.c
> +++ b/arch/riscv/mm/pmem.c
> @@ -7,15 +7,28 @@
> #include <linux/libnvdimm.h>
>
> #include <asm/cacheflush.h>
> +#include <asm/dma-noncoherent.h>
>
> void arch_wb_cache_pmem(void *addr, size_t size)
> {
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.wback)) {
> + noncoherent_cache_ops.wback(virt_to_phys(addr), size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
> }
> EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
>
> void arch_invalidate_pmem(void *addr, size_t size)
> {
> +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> + if (unlikely(noncoherent_cache_ops.inv)) {
> + noncoherent_cache_ops.inv(virt_to_phys(addr), size);
> + return;
> + }
> +#endif
> ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
> }
> EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
> --
> 2.34.1
>
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
On Sun, 30 Jul 2023 at 17:11, Jisheng Zhang <[email protected]> wrote:
>
> On Sun, Jul 02, 2023 at 09:34:26PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <[email protected]>
> >
> > Introduce support for nonstandard noncoherent systems in the RISC-V
> > architecture. It enables function pointer support to handle cache
> > management in such systems.
> >
> > This patch adds a new configuration option called
> > "RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
> > depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
> > support for cache management in nonstandard noncoherent systems.
> >
> > Signed-off-by: Lad Prabhakar <[email protected]>
> > Reviewed-by: Conor Dooley <[email protected]>
> > Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
> > ---
> > v9 -> v10
> > * Added __ro_after_init compiler attribute for noncoherent_cache_ops
> > * Renamed clean -> wback
> > * Renamed inval -> inv
> > * Renamed flush -> wback_inv
> >
> > v8 -> v9
> > * New patch
> > ---
> > arch/riscv/Kconfig | 7 ++++
> > arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
> > arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
> > arch/riscv/mm/pmem.c | 13 +++++++
> > 4 files changed, 91 insertions(+)
> > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index d9e451ac862a..42c86b13c5e1 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> > select DMA_DIRECT_REMAP
> >
> > +config RISCV_NONSTANDARD_CACHE_OPS
> > + bool
> > + depends on RISCV_DMA_NONCOHERENT
> > + help
> > + This enables function pointer support for non-standard noncoherent
> > + systems to handle cache management.
>
> Per Documentation/riscv/patch-acceptance.rst:
>
> "we'll only consider patches for extensions that either:
>
> - Have been officially frozen or ratified by the RISC-V Foundation, or
> - Have been implemented in hardware that is widely available, per standard
> Linux practice."
>
> I'm not sure which item this patch series belongs to.
Prabhakar can probably answer better, but my understanding is that
this needed on the Renesas RZ/Five SoC on the Asus Tinker V board:
https://tinker-board.asus.com/product/tinker-v.html
> > +
> > config AS_HAS_INSN
> > def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
> >
> > diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> > new file mode 100644
> > index 000000000000..969cf1f1363a
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/dma-noncoherent.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2023 Renesas Electronics Corp.
> > + */
> > +
> > +#ifndef __ASM_DMA_NONCOHERENT_H
> > +#define __ASM_DMA_NONCOHERENT_H
> > +
> > +#include <linux/dma-direct.h>
> > +
> > +/*
> > + * struct riscv_cache_ops - Structure for CMO function pointers
>
> can we reword this line as
> "struct riscv_nonstd_cache_ops - Structure for non-standard CMO function
> pointers" to explictly note this is only for non-standard CMO.
>
> > + *
> > + * @wback: Function pointer for cache writeback
> > + * @inv: Function pointer for invalidating cache
> > + * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
> > + */
> > +struct riscv_cache_ops {
> > + void (*wback)(phys_addr_t paddr, unsigned long size);
> > + void (*inv)(phys_addr_t paddr, unsigned long size);
> > + void (*wback_inv)(phys_addr_t paddr, unsigned long size);
> > +};
> > +
> > +extern struct riscv_cache_ops noncoherent_cache_ops;
> > +
> > +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops);
> > +
> > +#endif /* __ASM_DMA_NONCOHERENT_H */
> > diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> > index b9a9f57e02be..4c2e3f1cdfe6 100644
> > --- a/arch/riscv/mm/dma-noncoherent.c
> > +++ b/arch/riscv/mm/dma-noncoherent.c
> > @@ -9,13 +9,26 @@
> > #include <linux/dma-map-ops.h>
> > #include <linux/mm.h>
> > #include <asm/cacheflush.h>
> > +#include <asm/dma-noncoherent.h>
> >
> > static bool noncoherent_supported;
> >
> > +struct riscv_cache_ops noncoherent_cache_ops __ro_after_init = {
> > + .wback = NULL,
> > + .inv = NULL,
> > + .wback_inv = NULL,
> > +};
> > +
> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback)) {
>
> I'm worried about the performance impact here.
> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
> enabled by default, so standard CMO and T-HEAD's CMO platform's
> performance will be impacted, because even an unlikely is put
> here, the check action still needs to be done.
On IRC I asked why not use a static key so the overhead is just a
single nop when the standard CMO ops are available, but the consensus
seemed to be that the flushing would completely dominate this branch.
And on platforms with the standard CMO ops the branch be correctly
predicted anyway.
But I agree, in the future it would be great to convert the T-Head
non-standard CMO ops to this, so there is only one way to do
non-standard ops.
/Emil
> > + noncoherent_cache_ops.wback(paddr, size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -23,6 +36,13 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.inv)) {
> > + noncoherent_cache_ops.inv(paddr, size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -30,6 +50,13 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> > + noncoherent_cache_ops.wback_inv(paddr, size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -50,6 +77,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
> > {
> > void *flush_addr = page_address(page);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> > + noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -75,3 +109,12 @@ void riscv_noncoherent_supported(void)
> > "Non-coherent DMA support enabled without a block size\n");
> > noncoherent_supported = true;
> > }
> > +
> > +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops)
> > +{
> > + if (!ops)
> > + return;
> > +
> > + noncoherent_cache_ops = *ops;
> > +}
> > +EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
> > diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
> > index 089df92ae876..c5fc5ec96f6d 100644
> > --- a/arch/riscv/mm/pmem.c
> > +++ b/arch/riscv/mm/pmem.c
> > @@ -7,15 +7,28 @@
> > #include <linux/libnvdimm.h>
> >
> > #include <asm/cacheflush.h>
> > +#include <asm/dma-noncoherent.h>
> >
> > void arch_wb_cache_pmem(void *addr, size_t size)
> > {
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback)) {
> > + noncoherent_cache_ops.wback(virt_to_phys(addr), size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
> > }
> > EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
> >
> > void arch_invalidate_pmem(void *addr, size_t size)
> > {
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.inv)) {
> > + noncoherent_cache_ops.inv(virt_to_phys(addr), size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
> > }
> > EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
> > --
> > 2.34.1
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
>
> _______________________________________________
> linux-riscv mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-riscv
On Sun, Jul 30, 2023, at 17:42, Emil Renner Berthing wrote:
> On Sun, 30 Jul 2023 at 17:11, Jisheng Zhang <[email protected]> wrote:
>> > +
>> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
>> > {
>> > void *vaddr = phys_to_virt(paddr);
>> >
>> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
>> > + if (unlikely(noncoherent_cache_ops.wback)) {
>>
>> I'm worried about the performance impact here.
>> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
>> enabled by default, so standard CMO and T-HEAD's CMO platform's
>> performance will be impacted, because even an unlikely is put
>> here, the check action still needs to be done.
>
> On IRC I asked why not use a static key so the overhead is just a
> single nop when the standard CMO ops are available, but the consensus
> seemed to be that the flushing would completely dominate this branch.
> And on platforms with the standard CMO ops the branch be correctly
> predicted anyway.
Not just the flushing, but also loading back the invalidated
cache lines afterwards is just very expensive. I don't think
you would be able to measure a difference between the static
key and a correctly predicted branch on any relevant usecase here.
Arnd
On Mon, Jul 31, 2023 at 4:36 AM Arnd Bergmann <[email protected]> wrote:
>
> On Sun, Jul 30, 2023, at 17:42, Emil Renner Berthing wrote:
> > On Sun, 30 Jul 2023 at 17:11, Jisheng Zhang <[email protected]> wrote:
>
> >> > +
> >> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> >> > {
> >> > void *vaddr = phys_to_virt(paddr);
> >> >
> >> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> >> > + if (unlikely(noncoherent_cache_ops.wback)) {
> >>
> >> I'm worried about the performance impact here.
> >> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
> >> enabled by default, so standard CMO and T-HEAD's CMO platform's
> >> performance will be impacted, because even an unlikely is put
> >> here, the check action still needs to be done.
> >
> > On IRC I asked why not use a static key so the overhead is just a
> > single nop when the standard CMO ops are available, but the consensus
> > seemed to be that the flushing would completely dominate this branch.
> > And on platforms with the standard CMO ops the branch be correctly
> > predicted anyway.
>
> Not just the flushing, but also loading back the invalidated
> cache lines afterwards is just very expensive. I don't think
> you would be able to measure a difference between the static
> key and a correctly predicted branch on any relevant usecase here.
Maybe we should move CMO & THEAD ops to the noncoherent_cache_ops, and
only keep one of them.
I prefer noncoherent_cache_ops, it's more maintance than ALTERNATIVE.
Heiko, How do you think about this?
>
> Arnd
--
Best Regards
Guo Ren
On Mon, Jul 31, 2023, at 02:49, Guo Ren wrote:
> On Mon, Jul 31, 2023 at 4:36 AM Arnd Bergmann <[email protected]> wrote:
>>
>> On Sun, Jul 30, 2023, at 17:42, Emil Renner Berthing wrote:
>> > On Sun, 30 Jul 2023 at 17:11, Jisheng Zhang <[email protected]> wrote:
>>
>> >> > +
>> >> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
>> >> > {
>> >> > void *vaddr = phys_to_virt(paddr);
>> >> >
>> >> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
>> >> > + if (unlikely(noncoherent_cache_ops.wback)) {
>> >>
>> >> I'm worried about the performance impact here.
>> >> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
>> >> enabled by default, so standard CMO and T-HEAD's CMO platform's
>> >> performance will be impacted, because even an unlikely is put
>> >> here, the check action still needs to be done.
>> >
>> > On IRC I asked why not use a static key so the overhead is just a
>> > single nop when the standard CMO ops are available, but the consensus
>> > seemed to be that the flushing would completely dominate this branch.
>> > And on platforms with the standard CMO ops the branch be correctly
>> > predicted anyway.
>>
>> Not just the flushing, but also loading back the invalidated
>> cache lines afterwards is just very expensive. I don't think
>> you would be able to measure a difference between the static
>> key and a correctly predicted branch on any relevant usecase here.
> Maybe we should move CMO & THEAD ops to the noncoherent_cache_ops, and
> only keep one of them.
>
> I prefer noncoherent_cache_ops, it's more maintance than ALTERNATIVE.
I think moving the THEAD ops at the same level as all nonstandard
operations makes sense, but I'd still leave CMO as an explicit
fast path that avoids the indirect branch. This seems like the right
thing to do both for readability and for platforms on which the
indirect branch has a noticeable overhead.
Arnd
Hi Conor,
On Mon, Jul 31, 2023 at 12:39 PM Conor Dooley
<[email protected]> wrote:
>
> On Mon, Jul 31, 2023 at 12:30:43PM +0100, Lad, Prabhakar wrote:
> > On Sun, Jul 30, 2023 at 4:09 PM Jisheng Zhang <[email protected]> wrote:
> > > On Sun, Jul 02, 2023 at 09:34:26PM +0100, Prabhakar wrote:
> > > > From: Lad Prabhakar <[email protected]>
>
> > > > +config RISCV_NONSTANDARD_CACHE_OPS
> > > > + bool
> > > > + depends on RISCV_DMA_NONCOHERENT
> > > > + help
> > > > + This enables function pointer support for non-standard noncoherent
> > > > + systems to handle cache management.
> > >
> > > Per Documentation/riscv/patch-acceptance.rst:
> > >
> > > "we'll only consider patches for extensions that either:
> > >
> > > - Have been officially frozen or ratified by the RISC-V Foundation, or
> > > - Have been implemented in hardware that is widely available, per standard
> > > Linux practice."
> > >
> > > I'm not sure which item this patch series belongs to.
> > >
> > Maybe Conor can help me here ;)
>
> I'm not entirely sure why you need my help, it's your company that
> manufactures the SoC that needs this after all.. I think Emil already
> pointed out that it was the latter of the two. I guess it is not an
> "extension" in the strictest sense of the word, but it fills the same
> gap as one, so /shrug.
>
Aaha I was wondering If there had to be an additional entry here to
fit this case, but if it already does fit in ignore me. Thanks for the
clarification.
Cheers,
Prabhakar
Hi Jisheng,
Thank you for the review.
On Sun, Jul 30, 2023 at 4:09 PM Jisheng Zhang <[email protected]> wrote:
>
> On Sun, Jul 02, 2023 at 09:34:26PM +0100, Prabhakar wrote:
> > From: Lad Prabhakar <[email protected]>
> >
> > Introduce support for nonstandard noncoherent systems in the RISC-V
> > architecture. It enables function pointer support to handle cache
> > management in such systems.
> >
> > This patch adds a new configuration option called
> > "RISCV_NONSTANDARD_CACHE_OPS." This option is a boolean flag that
> > depends on "RISCV_DMA_NONCOHERENT" and enables the function pointer
> > support for cache management in nonstandard noncoherent systems.
> >
> > Signed-off-by: Lad Prabhakar <[email protected]>
> > Reviewed-by: Conor Dooley <[email protected]>
> > Tested-by: Conor Dooley <[email protected]> # tyre-kicking on a d1
> > ---
> > v9 -> v10
> > * Added __ro_after_init compiler attribute for noncoherent_cache_ops
> > * Renamed clean -> wback
> > * Renamed inval -> inv
> > * Renamed flush -> wback_inv
> >
> > v8 -> v9
> > * New patch
> > ---
> > arch/riscv/Kconfig | 7 ++++
> > arch/riscv/include/asm/dma-noncoherent.h | 28 +++++++++++++++
> > arch/riscv/mm/dma-noncoherent.c | 43 ++++++++++++++++++++++++
> > arch/riscv/mm/pmem.c | 13 +++++++
> > 4 files changed, 91 insertions(+)
> > create mode 100644 arch/riscv/include/asm/dma-noncoherent.h
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index d9e451ac862a..42c86b13c5e1 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -265,6 +265,13 @@ config RISCV_DMA_NONCOHERENT
> > select ARCH_HAS_SYNC_DMA_FOR_DEVICE
> > select DMA_DIRECT_REMAP
> >
> > +config RISCV_NONSTANDARD_CACHE_OPS
> > + bool
> > + depends on RISCV_DMA_NONCOHERENT
> > + help
> > + This enables function pointer support for non-standard noncoherent
> > + systems to handle cache management.
>
> Per Documentation/riscv/patch-acceptance.rst:
>
> "we'll only consider patches for extensions that either:
>
> - Have been officially frozen or ratified by the RISC-V Foundation, or
> - Have been implemented in hardware that is widely available, per standard
> Linux practice."
>
> I'm not sure which item this patch series belongs to.
>
Maybe Conor can help me here ;)
> > +
> > config AS_HAS_INSN
> > def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
> >
> > diff --git a/arch/riscv/include/asm/dma-noncoherent.h b/arch/riscv/include/asm/dma-noncoherent.h
> > new file mode 100644
> > index 000000000000..969cf1f1363a
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/dma-noncoherent.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2023 Renesas Electronics Corp.
> > + */
> > +
> > +#ifndef __ASM_DMA_NONCOHERENT_H
> > +#define __ASM_DMA_NONCOHERENT_H
> > +
> > +#include <linux/dma-direct.h>
> > +
> > +/*
> > + * struct riscv_cache_ops - Structure for CMO function pointers
>
> can we reword this line as
> "struct riscv_nonstd_cache_ops - Structure for non-standard CMO function
> pointers" to explictly note this is only for non-standard CMO.
>
Sure I will update it.
Cheers,
Prabhakar
> > + *
> > + * @wback: Function pointer for cache writeback
> > + * @inv: Function pointer for invalidating cache
> > + * @wback_inv: Function pointer for flushing the cache (writeback + invalidating)
> > + */
> > +struct riscv_cache_ops {
> > + void (*wback)(phys_addr_t paddr, unsigned long size);
> > + void (*inv)(phys_addr_t paddr, unsigned long size);
> > + void (*wback_inv)(phys_addr_t paddr, unsigned long size);
> > +};
> > +
> > +extern struct riscv_cache_ops noncoherent_cache_ops;
> > +
> > +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops);
> > +
> > +#endif /* __ASM_DMA_NONCOHERENT_H */
> > diff --git a/arch/riscv/mm/dma-noncoherent.c b/arch/riscv/mm/dma-noncoherent.c
> > index b9a9f57e02be..4c2e3f1cdfe6 100644
> > --- a/arch/riscv/mm/dma-noncoherent.c
> > +++ b/arch/riscv/mm/dma-noncoherent.c
> > @@ -9,13 +9,26 @@
> > #include <linux/dma-map-ops.h>
> > #include <linux/mm.h>
> > #include <asm/cacheflush.h>
> > +#include <asm/dma-noncoherent.h>
> >
> > static bool noncoherent_supported;
> >
> > +struct riscv_cache_ops noncoherent_cache_ops __ro_after_init = {
> > + .wback = NULL,
> > + .inv = NULL,
> > + .wback_inv = NULL,
> > +};
> > +
> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback)) {
>
> I'm worried about the performance impact here.
> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
> enabled by default, so standard CMO and T-HEAD's CMO platform's
> performance will be impacted, because even an unlikely is put
> here, the check action still needs to be done.
>
> > + noncoherent_cache_ops.wback(paddr, size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(clean, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -23,6 +36,13 @@ static inline void arch_dma_cache_inv(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.inv)) {
> > + noncoherent_cache_ops.inv(paddr, size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(inval, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -30,6 +50,13 @@ static inline void arch_dma_cache_wback_inv(phys_addr_t paddr, size_t size)
> > {
> > void *vaddr = phys_to_virt(paddr);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> > + noncoherent_cache_ops.wback_inv(paddr, size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(flush, vaddr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -50,6 +77,13 @@ void arch_dma_prep_coherent(struct page *page, size_t size)
> > {
> > void *flush_addr = page_address(page);
> >
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback_inv)) {
> > + noncoherent_cache_ops.wback_inv(page_to_phys(page), size);
> > + return;
> > + }
> > +#endif
> > +
> > ALT_CMO_OP(flush, flush_addr, size, riscv_cbom_block_size);
> > }
> >
> > @@ -75,3 +109,12 @@ void riscv_noncoherent_supported(void)
> > "Non-coherent DMA support enabled without a block size\n");
> > noncoherent_supported = true;
> > }
> > +
> > +void riscv_noncoherent_register_cache_ops(const struct riscv_cache_ops *ops)
> > +{
> > + if (!ops)
> > + return;
> > +
> > + noncoherent_cache_ops = *ops;
> > +}
> > +EXPORT_SYMBOL_GPL(riscv_noncoherent_register_cache_ops);
> > diff --git a/arch/riscv/mm/pmem.c b/arch/riscv/mm/pmem.c
> > index 089df92ae876..c5fc5ec96f6d 100644
> > --- a/arch/riscv/mm/pmem.c
> > +++ b/arch/riscv/mm/pmem.c
> > @@ -7,15 +7,28 @@
> > #include <linux/libnvdimm.h>
> >
> > #include <asm/cacheflush.h>
> > +#include <asm/dma-noncoherent.h>
> >
> > void arch_wb_cache_pmem(void *addr, size_t size)
> > {
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.wback)) {
> > + noncoherent_cache_ops.wback(virt_to_phys(addr), size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size);
> > }
> > EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
> >
> > void arch_invalidate_pmem(void *addr, size_t size)
> > {
> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> > + if (unlikely(noncoherent_cache_ops.inv)) {
> > + noncoherent_cache_ops.inv(virt_to_phys(addr), size);
> > + return;
> > + }
> > +#endif
> > ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size);
> > }
> > EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
> > --
> > 2.34.1
> >
> >
> > _______________________________________________
> > linux-riscv mailing list
> > [email protected]
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
On Mon, Jul 31, 2023 at 12:30:43PM +0100, Lad, Prabhakar wrote:
> On Sun, Jul 30, 2023 at 4:09 PM Jisheng Zhang <[email protected]> wrote:
> > On Sun, Jul 02, 2023 at 09:34:26PM +0100, Prabhakar wrote:
> > > From: Lad Prabhakar <[email protected]>
> > > +config RISCV_NONSTANDARD_CACHE_OPS
> > > + bool
> > > + depends on RISCV_DMA_NONCOHERENT
> > > + help
> > > + This enables function pointer support for non-standard noncoherent
> > > + systems to handle cache management.
> >
> > Per Documentation/riscv/patch-acceptance.rst:
> >
> > "we'll only consider patches for extensions that either:
> >
> > - Have been officially frozen or ratified by the RISC-V Foundation, or
> > - Have been implemented in hardware that is widely available, per standard
> > Linux practice."
> >
> > I'm not sure which item this patch series belongs to.
> >
> Maybe Conor can help me here ;)
I'm not entirely sure why you need my help, it's your company that
manufactures the SoC that needs this after all.. I think Emil already
pointed out that it was the latter of the two. I guess it is not an
"extension" in the strictest sense of the word, but it fills the same
gap as one, so /shrug.
On Mon, Jul 31, 2023 at 07:39:30AM +0200, Arnd Bergmann wrote:
> On Mon, Jul 31, 2023, at 02:49, Guo Ren wrote:
> > On Mon, Jul 31, 2023 at 4:36 AM Arnd Bergmann <[email protected]> wrote:
> >>
> >> On Sun, Jul 30, 2023, at 17:42, Emil Renner Berthing wrote:
> >> > On Sun, 30 Jul 2023 at 17:11, Jisheng Zhang <[email protected]> wrote:
> >>
> >> >> > +
> >> >> > static inline void arch_dma_cache_wback(phys_addr_t paddr, size_t size)
> >> >> > {
> >> >> > void *vaddr = phys_to_virt(paddr);
> >> >> >
> >> >> > +#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
> >> >> > + if (unlikely(noncoherent_cache_ops.wback)) {
> >> >>
> >> >> I'm worried about the performance impact here.
> >> >> For unified kernel Image reason, RISCV_NONSTANDARD_CACHE_OPS will be
> >> >> enabled by default, so standard CMO and T-HEAD's CMO platform's
> >> >> performance will be impacted, because even an unlikely is put
> >> >> here, the check action still needs to be done.
> >> >
> >> > On IRC I asked why not use a static key so the overhead is just a
> >> > single nop when the standard CMO ops are available, but the consensus
> >> > seemed to be that the flushing would completely dominate this branch.
> >> > And on platforms with the standard CMO ops the branch be correctly
> >> > predicted anyway.
> >>
> >> Not just the flushing, but also loading back the invalidated
> >> cache lines afterwards is just very expensive. I don't think
> >> you would be able to measure a difference between the static
I read this as: the cache clean/inv is so expensive that the static
key saving percentage is trivial, is this understanding right?
this could be measured by writing a small benchmark kernel module
which just calls cache clean/inv a buf(for example 1500Bytes)in a loop.
> >> key and a correctly predicted branch on any relevant usecase here.
> > Maybe we should move CMO & THEAD ops to the noncoherent_cache_ops, and
> > only keep one of them.
> >
> > I prefer noncoherent_cache_ops, it's more maintance than ALTERNATIVE.
>
> I think moving the THEAD ops at the same level as all nonstandard
> operations makes sense, but I'd still leave CMO as an explicit
> fast path that avoids the indirect branch. This seems like the right
> thing to do both for readability and for platforms on which the
> indirect branch has a noticeable overhead.
>
> Arnd
On Mon, Jul 31, 2023, at 17:43, Jisheng Zhang wrote:
> On Mon, Jul 31, 2023 at 07:39:30AM +0200, Arnd Bergmann wrote:
>> >> Not just the flushing, but also loading back the invalidated
>> >> cache lines afterwards is just very expensive. I don't think
>> >> you would be able to measure a difference between the static
>
> I read this as: the cache clean/inv is so expensive that the static
> key saving percentage is trivial, is this understanding right?
>
> this could be measured by writing a small benchmark kernel module
> which just calls cache clean/inv a buf(for example 1500Bytes)in a loop.
While you can trivially measure the cost of the clean/inv operation,
I think the higher cost is the fact that the cache lines are
invalidated and have to be reloaded when accessing the data the next
time. So if the loop test shows that the static key is not worth
it, that is a clear answer, but if it shows that the cache operation
itself is cheap, that does not automatically mean that the
static key makes a difference compared to a cache miss.
Arnd