s390/kasan: move memory needs estimation into a function
authorVasily Gorbik <gor@linux.ibm.com>
Mon, 5 Oct 2020 11:53:36 +0000 (13:53 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 9 Nov 2020 10:20:59 +0000 (11:20 +0100)
Also correct rounding downs in estimation calculations.

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/boot/kaslr.c
arch/s390/include/asm/kasan.h

index d844a5ef9089fd2513e43f99c12ddfd9718611a2..987a9eaf228a7cb440483b30287ba2611e826076 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/cpacf.h>
 #include <asm/timex.h>
 #include <asm/sclp.h>
+#include <asm/kasan.h>
 #include "compressed/decompressor.h"
 #include "boot.h"
 
@@ -179,34 +180,19 @@ unsigned long get_random_base(unsigned long safe_addr)
        if (memory_end_set)
                memory_limit = min(memory_limit, memory_end);
 
+       /*
+        * Avoid putting kernel in the end of physical memory
+        * which kasan will use for shadow memory and early pgtable
+        * mapping allocations.
+        */
+       memory_limit -= kasan_estimate_memory_needs(memory_limit);
+
        if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && INITRD_START && INITRD_SIZE) {
                if (safe_addr < INITRD_START + INITRD_SIZE)
                        safe_addr = INITRD_START + INITRD_SIZE;
        }
        safe_addr = ALIGN(safe_addr, THREAD_SIZE);
 
-       if ((IS_ENABLED(CONFIG_KASAN))) {
-               /*
-                * Estimate kasan memory requirements, which it will reserve
-                * at the very end of available physical memory. To estimate
-                * that, we take into account that kasan would require
-                * 1/8 of available physical memory (for shadow memory) +
-                * creating page tables for the whole memory + shadow memory
-                * region (1 + 1/8). To keep page tables estimates simple take
-                * the double of combined ptes size.
-                */
-               memory_limit = get_mem_detect_end();
-               if (memory_end_set && memory_limit > memory_end)
-                       memory_limit = memory_end;
-
-               /* for shadow memory */
-               kasan_needs = memory_limit / 8;
-               /* for paging structures */
-               kasan_needs += (memory_limit + kasan_needs) / PAGE_SIZE /
-                              _PAGE_ENTRIES * _PAGE_TABLE_SIZE * 2;
-               memory_limit -= kasan_needs;
-       }
-
        kernel_size = vmlinux.image_size + vmlinux.bss_size;
        if (safe_addr + kernel_size > memory_limit)
                return 0;
index eea62586e71965a6faf2e9d5478a685afcbde8fa..76f351bd66459f6742c15fc957082b3af308950e 100644 (file)
@@ -17,10 +17,36 @@ extern void kasan_early_init(void);
 extern void kasan_copy_shadow_mapping(void);
 extern void kasan_free_early_identity(void);
 extern unsigned long kasan_vmax;
+
+/*
+ * Estimate kasan memory requirements, which it will reserve
+ * at the very end of available physical memory. To estimate
+ * that, we take into account that kasan would require
+ * 1/8 of available physical memory (for shadow memory) +
+ * creating page tables for the whole memory + shadow memory
+ * region (1 + 1/8). To keep page tables estimates simple take
+ * the double of combined ptes size.
+ *
+ * physmem parameter has to be already adjusted if not entire physical memory
+ * would be used (e.g. due to effect of "mem=" option).
+ */
+static inline unsigned long kasan_estimate_memory_needs(unsigned long physmem)
+{
+       unsigned long kasan_needs;
+       unsigned long pages;
+       /* for shadow memory */
+       kasan_needs = round_up(physmem / 8, PAGE_SIZE);
+       /* for paging structures */
+       pages = DIV_ROUND_UP(physmem + kasan_needs, PAGE_SIZE);
+       kasan_needs += DIV_ROUND_UP(pages, _PAGE_ENTRIES) * _PAGE_TABLE_SIZE * 2;
+
+       return kasan_needs;
+}
 #else
 static inline void kasan_early_init(void) { }
 static inline void kasan_copy_shadow_mapping(void) { }
 static inline void kasan_free_early_identity(void) { }
+static inline unsigned long kasan_estimate_memory_needs(unsigned long physmem) { return 0; }
 #endif
 
 #endif