powerpc/64s/radix: Enable huge vmalloc mappings
authorNicholas Piggin <npiggin@gmail.com>
Mon, 3 May 2021 09:17:55 +0000 (19:17 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 4 May 2021 01:06:45 +0000 (11:06 +1000)
This reduces TLB misses by nearly 30x on a `git diff` workload on a
2-node POWER9 (59,800 -> 2,100) and reduces CPU cycles by 0.54%, due
to vfs hashes being allocated with 2MB pages.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210503091755.613393-1-npiggin@gmail.com
Documentation/admin-guide/kernel-parameters.txt
arch/powerpc/Kconfig
arch/powerpc/kernel/module.c

index 02470ba1fe6a4b365a71a32d6e3fd1582ec8d046..1fcec80b099ee70ff717c0e0059d61d55bbb6316 100644 (file)
 
        nohugeiomap     [KNL,X86,PPC,ARM64] Disable kernel huge I/O mappings.
 
+       nohugevmalloc   [PPC] Disable kernel huge vmalloc mappings.
+
        nosmt           [KNL,S390] Disable symmetric multithreading (SMT).
                        Equivalent to smt=1.
 
index 1e6230bea09d41dc9da550ee91d9c4258a610104..c547a9d6a2dd235b52f6f649514cfabb624aa2a4 100644 (file)
@@ -185,6 +185,7 @@ config PPC
        select GENERIC_VDSO_TIME_NS
        select HAVE_ARCH_AUDITSYSCALL
        select HAVE_ARCH_HUGE_VMAP              if PPC_BOOK3S_64 && PPC_RADIX_MMU
+       select HAVE_ARCH_HUGE_VMALLOC           if HAVE_ARCH_HUGE_VMAP
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_JUMP_LABEL_RELATIVE
        select HAVE_ARCH_KASAN                  if PPC32 && PPC_PAGE_SHIFT <= 14
index fab84024650c8d526453970b4aef0c8b6d7aea29..3f35c8d20be75ffeea1bda50b20f72c0f29034ca 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/moduleloader.h>
 #include <linux/err.h>
 #include <linux/vmalloc.h>
+#include <linux/mm.h>
 #include <linux/bug.h>
 #include <asm/module.h>
 #include <linux/uaccess.h>
@@ -88,17 +89,22 @@ int module_finalize(const Elf_Ehdr *hdr,
        return 0;
 }
 
-#ifdef MODULES_VADDR
 static __always_inline void *
 __module_alloc(unsigned long size, unsigned long start, unsigned long end)
 {
-       return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL,
-                                   PAGE_KERNEL_EXEC, VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
-                                   __builtin_return_address(0));
+       /*
+        * Don't do huge page allocations for modules yet until more testing
+        * is done. STRICT_MODULE_RWX may require extra work to support this
+        * too.
+        */
+       return __vmalloc_node_range(size, 1, start, end, GFP_KERNEL, PAGE_KERNEL_EXEC,
+                                   VM_FLUSH_RESET_PERMS | VM_NO_HUGE_VMAP,
+                                   NUMA_NO_NODE, __builtin_return_address(0));
 }
 
 void *module_alloc(unsigned long size)
 {
+#ifdef MODULES_VADDR
        unsigned long limit = (unsigned long)_etext - SZ_32M;
        void *ptr = NULL;
 
@@ -112,5 +118,7 @@ void *module_alloc(unsigned long size)
                ptr = __module_alloc(size, MODULES_VADDR, MODULES_END);
 
        return ptr;
-}
+#else
+       return __module_alloc(size, VMALLOC_START, VMALLOC_END);
 #endif
+}