diff mbox series

[RFC,v2,06/11] riscv: pgtable: Add DMA_COHERENT with custom PTE attributes

Message ID 1622970249-50770-10-git-send-email-guoren@kernel.org (mailing list archive)
State New
Headers show
Series riscv: Add DMA_COHERENT support for Allwinner D1 | expand

Commit Message

Guo Ren June 6, 2021, 9:04 a.m. UTC
From: Guo Ren <guoren@linux.alibaba.com>

The dma-noncoherent SOCs need different virtual memory mappings
with different attributes:
 - noncached + Strong Order (for IO/DMA descriptor)
 - noncached + Weak Order (for writecombine usage, eg: frame
   buffer)

All above base on PTE attributes by MMU hardware. That means
address attributes are determined by PTE entry, not PMA. RISC-V
soc vendors have defined their own custom PTE attributes for
dma-noncoherency.

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Signed-off-by: Liu Shaohua <liush@allwinnertech.com>
Cc: Palmer Dabbelt <palmerdabbelt@google.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Anup Patel <anup.patel@wdc.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Drew Fustini <drew@beagleboard.org>
Cc: Wei Fu <wefu@redhat.com>
Cc: Wei Wu <lazyparser@gmail.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Maxime Ripard <maxime@cerno.tech>
---
 arch/riscv/include/asm/pgtable-bits.h  | 20 +++++++++++++++++++-
 arch/riscv/include/asm/pgtable.h       | 11 ++++-------
 arch/riscv/include/asm/soc.h           |  1 +
 arch/riscv/include/asm/vendorid_list.h |  1 +
 arch/riscv/kernel/soc.c                | 22 ++++++++++++++++++++++
 arch/riscv/mm/init.c                   |  4 ++++
 6 files changed, 51 insertions(+), 8 deletions(-)

Comments

Christoph Hellwig June 6, 2021, 2:39 p.m. UTC | #1
NAK, no SOC must ever mess with pagetable attributes.
Guo Ren June 6, 2021, 3:08 p.m. UTC | #2
On Sun, Jun 6, 2021 at 10:39 PM Christoph Hellwig <hch@lst.de> wrote:
>
> NAK, no SOC must ever mess with pagetable attributes.

I don't think it messes with page table attributes. _PAGE_BASE
contains variable won't cause any problem.
Nick Kossifidis June 6, 2021, 5:22 p.m. UTC | #3
Στις 2021-06-06 12:04, guoren@kernel.org έγραψε:
> From: Guo Ren <guoren@linux.alibaba.com>
> 
> The dma-noncoherent SOCs need different virtual memory mappings
> with different attributes:
>  - noncached + Strong Order (for IO/DMA descriptor)
>  - noncached + Weak Order (for writecombine usage, eg: frame
>    buffer)
> 
> All above base on PTE attributes by MMU hardware. That means
> address attributes are determined by PTE entry, not PMA. RISC-V
> soc vendors have defined their own custom PTE attributes for
> dma-noncoherency.
> 

This patch violates the Privilege Spec section 4.4.1 that clearly 
states:

"Bits63–54 are reserved for future standard use and must be zeroed by 
software for forward compatibility"

Standard use means that valid values can only be defined by the Priv. 
Spec, not by the vendor (otherwise they'd be marked as "custom use" or 
"platform use"), and since they "must" be zeroed by software we 'll be 
violating the Privilege Spec if we do otherwise.
Christoph Hellwig June 7, 2021, 6:19 a.m. UTC | #4
On Sun, Jun 06, 2021 at 08:22:14PM +0300, Nick Kossifidis wrote:
> This patch violates the Privilege Spec section 4.4.1 that clearly states:
>
> "Bits63–54 are reserved for future standard use and must be zeroed by 
> software for forward compatibility"
>
> Standard use means that valid values can only be defined by the Priv. Spec, 
> not by the vendor (otherwise they'd be marked as "custom use" or "platform 
> use"), and since they "must" be zeroed by software we 'll be violating the 
> Privilege Spec if we do otherwise.

Yes, that is why I think it is a no-go.
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h
index bbaeb5d..080a9eb 100644
--- a/arch/riscv/include/asm/pgtable-bits.h
+++ b/arch/riscv/include/asm/pgtable-bits.h
@@ -24,6 +24,11 @@ 
 #define _PAGE_DIRTY     (1 << 7)    /* Set by hardware on any write */
 #define _PAGE_SOFT      (1 << 8)    /* Reserved for software */
 
+#define _PAGE_DMA_MASK	__riscv_custom_pte.mask
+#define _PAGE_DMA_CACHE	__riscv_custom_pte.cache
+#define _PAGE_DMA_IO	__riscv_custom_pte.io
+#define _PAGE_DMA_WC	__riscv_custom_pte.wc
+
 #define _PAGE_SPECIAL   _PAGE_SOFT
 #define _PAGE_TABLE     _PAGE_PRESENT
 
@@ -35,9 +40,22 @@ 
 
 #define _PAGE_PFN_SHIFT 10
 
+#ifndef __ASSEMBLY__
+
+struct riscv_custom_pte {
+	unsigned long cache;
+	unsigned long mask;
+	unsigned long io;
+	unsigned long wc;
+};
+
+extern struct riscv_custom_pte __riscv_custom_pte;
+
 /* Set of bits to preserve across pte_modify() */
 #define _PAGE_CHG_MASK  (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ |	\
 					  _PAGE_WRITE | _PAGE_EXEC |	\
-					  _PAGE_USER | _PAGE_GLOBAL))
+					  _PAGE_USER | _PAGE_GLOBAL |	\
+					  _PAGE_DMA_MASK))
+#endif
 
 #endif /* _ASM_RISCV_PGTABLE_BITS_H */
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 13a79643..6ddeb49 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -114,7 +114,7 @@ 
 #define USER_PTRS_PER_PGD   (TASK_SIZE / PGDIR_SIZE)
 
 /* Page protection bits */
-#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
+#define _PAGE_BASE	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER | _PAGE_DMA_CACHE)
 
 #define PAGE_NONE		__pgprot(_PAGE_PROT_NONE)
 #define PAGE_READ		__pgprot(_PAGE_BASE | _PAGE_READ)
@@ -135,7 +135,8 @@ 
 				| _PAGE_PRESENT \
 				| _PAGE_ACCESSED \
 				| _PAGE_DIRTY \
-				| _PAGE_GLOBAL)
+				| _PAGE_GLOBAL \
+				| _PAGE_DMA_CACHE)
 
 #define PAGE_KERNEL		__pgprot(_PAGE_KERNEL)
 #define PAGE_KERNEL_READ	__pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
@@ -145,11 +146,7 @@ 
 
 #define PAGE_TABLE		__pgprot(_PAGE_TABLE)
 
-/*
- * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't
- * change the properties of memory regions.
- */
-#define _PAGE_IOREMAP _PAGE_KERNEL
+#define _PAGE_IOREMAP	((_PAGE_KERNEL & ~_PAGE_DMA_MASK) | _PAGE_DMA_IO)
 
 extern pgd_t swapper_pg_dir[];
 
diff --git a/arch/riscv/include/asm/soc.h b/arch/riscv/include/asm/soc.h
index f494066..fc587d7 100644
--- a/arch/riscv/include/asm/soc.h
+++ b/arch/riscv/include/asm/soc.h
@@ -17,6 +17,7 @@ 
 		 = { .compatible = compat, .data = fn  }
 
 void soc_early_init(void);
+void soc_setup_vm(void);
 
 extern unsigned long __soc_early_init_table_start;
 extern unsigned long __soc_early_init_table_end;
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 9d93421..c2710f3 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -6,5 +6,6 @@ 
 #define ASM_VENDOR_LIST_H
 
 #define SIFIVE_VENDOR_ID	0x489
+#define  THEAD_VENDOR_ID	0x401
 
 #endif
diff --git a/arch/riscv/kernel/soc.c b/arch/riscv/kernel/soc.c
index a051617..05fa764 100644
--- a/arch/riscv/kernel/soc.c
+++ b/arch/riscv/kernel/soc.c
@@ -3,8 +3,10 @@ 
  * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  */
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/libfdt.h>
 #include <linux/pgtable.h>
+#include <asm/image.h>
 #include <asm/soc.h>
 
 /*
@@ -26,3 +28,23 @@  void __init soc_early_init(void)
 		}
 	}
 }
+
+static void __init thead_init(void)
+{
+	__riscv_custom_pte.cache = 0x7000000000000000;
+	__riscv_custom_pte.mask  = 0xf800000000000000;
+	__riscv_custom_pte.io    = BIT(63);
+	__riscv_custom_pte.wc    = 0;
+}
+
+void __init soc_setup_vm(void)
+{
+	unsigned long vendor_id =
+		((struct riscv_image_header *)(&_start))->res1;
+
+	switch (vendor_id) {
+	case THEAD_VENDOR_ID:
+		thead_init();
+		break;
+	}
+};
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 4b398c6..fb70c49 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -524,6 +524,7 @@  asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 	pmd_t fix_bmap_spmd, fix_bmap_epmd;
 #endif
 
+	soc_setup_vm();
 	setup_protection_map();
 
 #ifdef CONFIG_XIP_KERNEL
@@ -911,3 +912,6 @@  int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
 	return vmemmap_populate_basepages(start, end, node, NULL);
 }
 #endif
+
+struct riscv_custom_pte __riscv_custom_pte __ro_after_init;
+EXPORT_SYMBOL(__riscv_custom_pte);