s390/kasan: avoid kasan crash with standby memory defined
authorVasily Gorbik <gor@linux.ibm.com>
Thu, 13 Sep 2018 08:59:25 +0000 (10:59 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:21:33 +0000 (11:21 +0200)
Kasan early memory allocator simply chops off memory blocks from the
end of the physical memory. Reuse mem_detect info to identify actual
online memory end rather than using max_physmem_end. This allows to run
the kernel with kasan enabled and standby memory defined.

Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/mm/kasan_init.c

index 5129847018bab6ca7364b6df3e4361395e8b1cc0..6b0574340f7fdad341d730ed7dfea0b872c92b6d 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/kasan.h>
+#include <asm/mem_detect.h>
 #include <asm/processor.h>
 #include <asm/sclp.h>
 #include <asm/facility.h>
@@ -233,6 +234,18 @@ static void __init kasan_early_detect_facilities(void)
        }
 }
 
+static unsigned long __init get_mem_detect_end(void)
+{
+       unsigned long start;
+       unsigned long end;
+
+       if (mem_detect.count) {
+               __get_mem_detect_block(mem_detect.count - 1, &start, &end);
+               return end;
+       }
+       return 0;
+}
+
 void __init kasan_early_init(void)
 {
        unsigned long untracked_mem_end;
@@ -252,6 +265,11 @@ void __init kasan_early_init(void)
                pgt_prot &= ~_PAGE_NOEXEC;
        pte_z = __pte(__pa(kasan_zero_page) | pgt_prot);
 
+       memsize = get_mem_detect_end();
+       if (!memsize)
+               kasan_early_panic("cannot detect physical memory size\n");
+       memsize = min(memsize, KASAN_SHADOW_START);
+
        if (IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING)) {
                /* 4 level paging */
                BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, P4D_SIZE));
@@ -276,7 +294,6 @@ void __init kasan_early_init(void)
        crst_table_init((unsigned long *)kasan_zero_pmd, pmd_val(pmd_z));
        memset64((u64 *)kasan_zero_pte, pte_val(pte_z), PTRS_PER_PTE);
 
-       memsize = min(max_physmem_end, KASAN_SHADOW_START);
        shadow_alloc_size = memsize >> KASAN_SHADOW_SCALE_SHIFT;
        pgalloc_low = round_up((unsigned long)_end, _SEGMENT_SIZE);
        if (IS_ENABLED(CONFIG_BLK_DEV_INITRD)) {