riscv: add ARCH_HAS_SET_DIRECT_MAP support
authorZong Li <zong.li@sifive.com>
Mon, 9 Mar 2020 16:55:37 +0000 (00:55 +0800)
committerPalmer Dabbelt <palmerdabbelt@google.com>
Thu, 26 Mar 2020 16:24:33 +0000 (09:24 -0700)
Add set_direct_map_*() functions for setting the direct map alias for
the page to its default permissions and to an invalid state that cannot
be cached in a TLB. (See d253ca0c ("x86/mm/cpa: Add set_direct_map_*()
functions")) Add a similar implementation for RISC-V.

Signed-off-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
arch/riscv/Kconfig
arch/riscv/include/asm/set_memory.h
arch/riscv/mm/pageattr.c

index 3da5c20..34fc745 100644 (file)
@@ -59,6 +59,7 @@ config RISCV
        select HAVE_EBPF_JIT if 64BIT
        select EDAC_SUPPORT
        select ARCH_HAS_GIGANTIC_PAGE
+       select ARCH_HAS_SET_DIRECT_MAP
        select ARCH_HAS_SET_MEMORY
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
        select SPARSEMEM_STATIC if 32BIT
index 79a810f..620d81c 100644 (file)
@@ -21,4 +21,7 @@ static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
 static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
 #endif
 
+int set_direct_map_invalid_noflush(struct page *page);
+int set_direct_map_default_noflush(struct page *page);
+
 #endif /* _ASM_RISCV_SET_MEMORY_H */
index fcd59ef..7be6cd6 100644 (file)
@@ -148,3 +148,27 @@ int set_memory_nx(unsigned long addr, int numpages)
 {
        return __set_memory(addr, numpages, __pgprot(0), __pgprot(_PAGE_EXEC));
 }
+
+int set_direct_map_invalid_noflush(struct page *page)
+{
+       unsigned long start = (unsigned long)page_address(page);
+       unsigned long end = start + PAGE_SIZE;
+       struct pageattr_masks masks = {
+               .set_mask = __pgprot(0),
+               .clear_mask = __pgprot(_PAGE_PRESENT)
+       };
+
+       return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+}
+
+int set_direct_map_default_noflush(struct page *page)
+{
+       unsigned long start = (unsigned long)page_address(page);
+       unsigned long end = start + PAGE_SIZE;
+       struct pageattr_masks masks = {
+               .set_mask = PAGE_KERNEL,
+               .clear_mask = __pgprot(0)
+       };
+
+       return walk_page_range(&init_mm, start, end, &pageattr_ops, &masks);
+}