riscv: add RISC-V Svpbmt extension supports

A patch from »svpbmt und so« in state Mainline for linux-kernel

From: Heiko Stuebner <heiko@...> Date: Mon, 29 Nov 2021 09:40:07 +0800

Commit-Message

This patch follows the standard pure RISC-V Svpbmt extension in privilege spec to solve the non-coherent SOC dma synchronization issues. Here is the svpbmt PTE format: | 63 | 62-61 | 60-8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 N MT RSW D A G U X W R V ^ Of the Reserved bits [63:54] in a leaf PTE, the high bit is already allocated (as the N bit), so bits [62:61] are used as the MT (aka MemType) field. This field specifies one of three memory types that are close equivalents (or equivalent in effect) to the three main x86 and ARMv8 memory types - as shown in the following table. RISC-V Encoding & MemType RISC-V Description ---------- ------------------------------------------------ 00 - PMA Normal Cacheable, No change to implied PMA memory type 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory 11 - Rsvd Reserved for future standard use The standard protection_map[] needn't be modified because the "PMA" type keeps the highest bits zero. And the whole modification is limited in the arch/riscv/* and using a global variable (__svpbmt) as _PAGE_MASK/IO/NOCACHE for pgprot_noncached (&writecombine) in pgtable.h. We also add _PAGE_CHG_MASK to filter PFN than before. Enable it in devicetree - (Add "riscv,svpbmt" in the mmu of cpu node) - mmu: riscv,svpmbt Signed-off-by: Heiko Stuebner <heiko@...>

Patch-Comment

arch/riscv/errata/cpufeatures.c | 32 +++++++++++++++ arch/riscv/include/asm/errata_list.h | 12 +++++- arch/riscv/include/asm/fixmap.h | 2 - arch/riscv/include/asm/pgtable-32.h | 10 +++++ arch/riscv/include/asm/pgtable-64.h | 59 +++++++++++++++++++++++++++ arch/riscv/include/asm/pgtable-bits.h | 4 -- arch/riscv/include/asm/pgtable.h | 32 ++++++++++++--- 7 files changed, 138 insertions(+), 13 deletions(-)

Statistics

  • 138 lines added
  • 13 lines removed

Changes

----------------------- arch/riscv/errata/cpufeatures.c ------------------------
index 99b7c5fe8dd4..cc392a922443 100644
@@ -16,7 +16,39 @@ struct cpufeature_info_t {
bool (*check_func)(void);
};
+static bool cpufeature_svpbmt_check_func(void)
+{
+ bool ret = false;
+
+#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
+ struct device_node *node;
+ const char *str;
+
+ for_each_of_cpu_node(node) {
+ if (of_property_read_string(node, "mmu-type", &str))
+ continue;
+
+ if (!strncmp(str + 6, "none", 4))
+ continue;
+
+ if (of_property_read_string(node, "mmu", &str))
+ continue;
+
+ if (!strncmp(str + 6, "svpbmt", 6)) {
+ ret = true;
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
static struct cpufeature_info_t cpufeature_list[CPUFEATURE_NUMBER] = {
+ {
+ .name = "svpbmt",
+ .check_func = cpufeature_svpbmt_check_func
+ },
};
static u32 __init cpufeature_probe(void)
--------------------- arch/riscv/include/asm/errata_list.h ---------------------
index 6b95bd9aee82..8faff6990ad0 100644
@@ -14,7 +14,8 @@
#define ERRATA_SIFIVE_NUMBER 2
#endif
-#define CPUFEATURE_NUMBER 0
+#define CPUFEATURE_SVPBMT 0
+#define CPUFEATURE_NUMBER 1
#ifdef __ASSEMBLY__
@@ -36,6 +37,15 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \
: : "r" (addr) : "memory")
+/*
+ * _val is marked as "will be overwritten", so need to set it to 0
+ * in the default case.
+ */
+#define ALT_SVPBMT(_val, prot) \
+asm(ALTERNATIVE("li %0, 0\t\nnop", "li %0, %1\t\nslli %0,%0,59", 0, \
+ CPUFEATURE_SVPBMT, CONFIG_64BIT) \
+ : "=r"(_val) : "I"( prot##_SVPBMT >> 59))
+
#endif /* __ASSEMBLY__ */
#endif
----------------------- arch/riscv/include/asm/fixmap.h ------------------------
index 54cbf07fb4e9..899b59bdb9eb 100644
@@ -43,8 +43,6 @@ enum fixed_addresses {
__end_of_fixed_addresses
};
-#define FIXMAP_PAGE_IO PAGE_KERNEL
-
#define __early_set_fixmap __set_fixmap
#define __late_set_fixmap __set_fixmap
--------------------- arch/riscv/include/asm/pgtable-32.h ----------------------
index 5b2e79e5bfa5..f4eac23fb300 100644
@@ -16,4 +16,14 @@
#define MAX_POSSIBLE_PHYSMEM_BITS 34
+#define _PAGE_PMA 0
+#define _PAGE_NOCACHE 0
+#define _PAGE_IO 0
+#define _PAGE_MTMASK 0
+
+/* 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))
+
#endif /* _ASM_RISCV_PGTABLE_32_H */
--------------------- arch/riscv/include/asm/pgtable-64.h ----------------------
index 6df493b55dde..7a3438be1c26 100644
@@ -7,6 +7,7 @@
#define _ASM_RISCV_PGTABLE_64_H
#include <linux/const.h>
+#include <asm/errata_list.h>
#define PGDIR_SHIFT 30
/* Size of region mapped by a page global directory */
@@ -28,6 +29,64 @@ typedef struct {
#define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t))
+/*
+ * rv64 PTE format:
+ * | 63 | 62 61 | 60 54 | 53 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
+ * N MT RSV PFN reserved for SW D A G U X W R V
+ * [62:61] Memory Type definitions:
+ * 00 - PMA Normal Cacheable, No change to implied PMA memory type
+ * 01 - NC Non-cacheable, idempotent, weakly-ordered Main Memory
+ * 10 - IO Non-cacheable, non-idempotent, strongly-ordered I/O memory
+ * 11 - Rsvd Reserved for future standard use
+ */
+#define _PAGE_PMA_SVPBMT 0UL
+#define _PAGE_NOCACHE_SVPBMT (1UL << 61)
+#define _PAGE_IO_SVPBMT (1UL << 62)
+#define _PAGE_MTMASK_SVPBMT (_PAGE_NOCACHE_SVPBMT | _PAGE_IO_SVPBMT)
+
+static inline u64 riscv_page_mtmask(void)
+{
+ u64 val;
+
+ ALT_SVPBMT(val, _PAGE_MTMASK);
+ return val;
+}
+
+static inline u64 riscv_page_pma(void)
+{
+ u64 val;
+
+ ALT_SVPBMT(val, _PAGE_PMA);
+ return val;
+}
+
+static inline u64 riscv_page_nocache(void)
+{
+ u64 val;
+
+ ALT_SVPBMT(val, _PAGE_NOCACHE);
+ return val;
+}
+
+static inline u64 riscv_page_io(void)
+{
+ u64 val;
+
+ ALT_SVPBMT(val, _PAGE_IO);
+ return val;
+}
+
+#define _PAGE_PMA riscv_page_pma()
+#define _PAGE_NOCACHE riscv_page_nocache()
+#define _PAGE_IO riscv_page_io()
+#define _PAGE_MTMASK riscv_page_mtmask()
+
+/* 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_MTMASK))
+
static inline int pud_present(pud_t pud)
{
return (pud_val(pud) & _PAGE_PRESENT);
-------------------- arch/riscv/include/asm/pgtable-bits.h ---------------------
index 2ee413912926..c639c563ac2c 100644
@@ -35,10 +35,6 @@
#define _PAGE_PFN_SHIFT 10
-/* 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))
/*
* when all of R/W/X are zero, the PTE is a pointer to the next level
* of the page table; otherwise, it is a leaf PTE.
----------------------- arch/riscv/include/asm/pgtable.h -----------------------
index 450804c263b5..293ee94949bc 100644
@@ -138,7 +138,8 @@
| _PAGE_PRESENT \
| _PAGE_ACCESSED \
| _PAGE_DIRTY \
- | _PAGE_GLOBAL)
+ | _PAGE_GLOBAL \
+ | _PAGE_PMA)
#define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
#define PAGE_KERNEL_READ __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
@@ -148,11 +149,8 @@
#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_MTMASK) | _PAGE_IO)
+#define PAGE_KERNEL_IO __pgprot(_PAGE_IOREMAP)
extern pgd_t swapper_pg_dir[];
@@ -492,6 +490,28 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
return ptep_test_and_clear_young(vma, address, ptep);
}
+#define pgprot_noncached pgprot_noncached
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+{
+ unsigned long prot = pgprot_val(_prot);
+
+ prot &= ~_PAGE_MTMASK;
+ prot |= _PAGE_IO;
+
+ return __pgprot(prot);
+}
+
+#define pgprot_writecombine pgprot_writecombine
+static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
+{
+ unsigned long prot = pgprot_val(_prot);
+
+ prot &= ~_PAGE_MTMASK;
+ prot |= _PAGE_NOCACHE;
+
+ return __pgprot(prot);
+}
+
/*
* THP functions
*/
 
 

Recent Patches

About Us

Sed lacus. Donec lectus. Nullam pretium nibh ut turpis. Nam bibendum. In nulla tortor, elementum vel, tempor at, varius non, purus. Mauris vitae nisl nec metus placerat consectetuer.

Read More...