[PATCH 2/2] riscv: mm: add pgprot_dmacoherent for zicbom

Ben Dooks ben.dooks at codethink.co.uk
Tue Mar 7 12:58:34 PST 2023


If the system uses both ZICBOM and SVPBMT then currently SVPBMT will be
used for DMA allocated memory even though ZICBOM gives us the cache ops
to use cached memory and clean/flush them as needed by the DMA code.

Fix this by adding pgprot_dmacoherent() which is used by the allocator
code to map the dma memory, thus allowing the return of suitably mapped
memory for any use of dma_alloc_attrs() code. This s uses the added
riscv_page_dmacoherent() which will work out the correct page flags to
return using ALT_SVPBMT_ZICBOM() to runtime patch the right result.

Note, we can't just disable SVPBMT as it will be neede for things like
ioremap() which don't have assoicated cache management operations.

Signed-off-by: Ben Dooks <ben.dooks at codethink.co.uk>
---
 arch/riscv/include/asm/errata_list.h | 16 ++++++++++++++++
 arch/riscv/include/asm/pgtable-64.h  | 10 ++++++++++
 2 files changed, 26 insertions(+)

diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index fb1a810f3d8c..49ed2e7984a7 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -62,6 +62,22 @@ asm(ALTERNATIVE_2("li %0, 0\t\nnop",					\
 		  "I"(ALT_SVPBMT_SHIFT),				\
 		  "I"(ALT_THEAD_PBMT_SHIFT))
 
+#define ALT_SVPBMT_ZICBOM(_val, prot)					\
+asm(ALTERNATIVE_3("li %0, 0\t\nnop",					\
+		  "li %0, %1\t\nslli %0,%0,%3", 0,			\
+			RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT,	\
+		  "li %0, 0\t\nnop", 0,					\
+			RISCV_ISA_EXT_ZICBOM, CONFIG_RISCV_ISA_ZICBOM,	\
+		  "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID,	\
+			ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT)	\
+		: "=r"(_val)						\
+		: "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT),		\
+		  "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT),		\
+		  "I"(ALT_SVPBMT_SHIFT),				\
+		  "I"(ALT_THEAD_PBMT_SHIFT))
+
+
+
 #ifdef CONFIG_ERRATA_THEAD_PBMT
 /*
  * IO/NOCACHE memory types are handled together with svpbmt,
diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h
index 42a042c0e13e..e0d2e5fda5a4 100644
--- a/arch/riscv/include/asm/pgtable-64.h
+++ b/arch/riscv/include/asm/pgtable-64.h
@@ -126,10 +126,20 @@ static inline u64 riscv_page_io(void)
 	return val;
 }
 
+static inline u64 riscv_page_dmacoherent(void)
+{
+	u64 val;
+
+	ALT_SVPBMT_ZICBOM(val, _PAGE_IO);
+	return val;
+}
+
 #define _PAGE_NOCACHE		riscv_page_nocache()
 #define _PAGE_IO		riscv_page_io()
 #define _PAGE_MTMASK		riscv_page_mtmask()
 
+#define pgprot_dmacoherent(__prot) __pgprot(pgprot_val(__prot) | riscv_page_dmacoherent())
+
 /* Set of bits to preserve across pte_modify() */
 #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
 					  _PAGE_WRITE | _PAGE_EXEC |	\
-- 
2.39.2




More information about the linux-riscv mailing list