OSDN Git Service

riscv: mm: support Svnapot in huge vmap
authorQinglin Pan <panqinglin2020@iscas.ac.cn>
Thu, 9 Feb 2023 13:16:47 +0000 (21:16 +0800)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 8 Mar 2023 03:39:17 +0000 (19:39 -0800)
As HAVE_ARCH_HUGE_VMAP and HAVE_ARCH_HUGE_VMALLOC is supported, we can
implement arch_vmap_pte_range_map_size and arch_vmap_pte_supported_shift
for Svnapot to support huge vmap about napot size.

It can be tested by huge vmap used in pci driver. Huge vmalloc with svnapot
can be tested by test_vmalloc with [1] applied, and probe this
module to run fix_size_alloc_test with use_huge true.

[1]https://lore.kernel.org/all/20221212055657.698420-1-panqinglin2020@iscas.ac.cn/

Signed-off-by: Qinglin Pan <panqinglin00@gmail.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230209131647.17245-4-panqinglin00@gmail.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/vmalloc.h

index 48da537..58d3e44 100644 (file)
@@ -17,6 +17,65 @@ static inline bool arch_vmap_pmd_supported(pgprot_t prot)
        return true;
 }
 
-#endif
+#ifdef CONFIG_RISCV_ISA_SVNAPOT
+#include <linux/pgtable.h>
 
+#define arch_vmap_pte_range_map_size arch_vmap_pte_range_map_size
+static inline unsigned long arch_vmap_pte_range_map_size(unsigned long addr, unsigned long end,
+                                                        u64 pfn, unsigned int max_page_shift)
+{
+       unsigned long map_size = PAGE_SIZE;
+       unsigned long size, order;
+
+       if (!has_svnapot())
+               return map_size;
+
+       for_each_napot_order_rev(order) {
+               if (napot_cont_shift(order) > max_page_shift)
+                       continue;
+
+               size = napot_cont_size(order);
+               if (end - addr < size)
+                       continue;
+
+               if (!IS_ALIGNED(addr, size))
+                       continue;
+
+               if (!IS_ALIGNED(PFN_PHYS(pfn), size))
+                       continue;
+
+               map_size = size;
+               break;
+       }
+
+       return map_size;
+}
+
+#define arch_vmap_pte_supported_shift arch_vmap_pte_supported_shift
+static inline int arch_vmap_pte_supported_shift(unsigned long size)
+{
+       int shift = PAGE_SHIFT;
+       unsigned long order;
+
+       if (!has_svnapot())
+               return shift;
+
+       WARN_ON_ONCE(size >= PMD_SIZE);
+
+       for_each_napot_order_rev(order) {
+               if (napot_cont_size(order) > size)
+                       continue;
+
+               if (!IS_ALIGNED(size, napot_cont_size(order)))
+                       continue;
+
+               shift = napot_cont_shift(order);
+               break;
+       }
+
+       return shift;
+}
+
+#endif /* CONFIG_RISCV_ISA_SVNAPOT */
+#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */
 #endif /* _ASM_RISCV_VMALLOC_H */