aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Schaefer <gerald.schaefer@de.ibm.com>2019-04-18 10:24:50 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2019-04-29 04:47:10 -0400
commit7a5da02de8d6eafba99556f8c98e5313edebb449 (patch)
treea65d2d59ec15717701fdb00a82dafeb418726593
parentb2d24b97b2a9691351920e700bfda4368c177232 (diff)
locking/lockdep: check for freed initmem in static_obj()
The following warning occurred on s390: WARNING: CPU: 0 PID: 804 at kernel/locking/lockdep.c:1025 lockdep_register_key+0x30/0x150 This is because the check in static_obj() assumes that all memory within [_stext, _end] belongs to static objects, which at least for s390 isn't true. The init section is also part of this range, and freeing it allows the buddy allocator to allocate memory from it. We have virt == phys for the kernel on s390, so that such allocations would then have addresses within the range [_stext, _end]. To fix this, introduce arch_is_kernel_initmem_freed(), similar to arch_is_kernel_text/data(), and add it to the checks in static_obj(). This will always return 0 on architectures that do not define arch_is_kernel_initmem_freed. On s390, it will return 1 if initmem has been freed and the address is in the range [__init_begin, __init_end]. Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/sections.h12
-rw-r--r--arch/s390/mm/init.c3
-rw-r--r--include/asm-generic/sections.h14
-rw-r--r--kernel/locking/lockdep.c3
4 files changed, 32 insertions, 0 deletions
diff --git a/arch/s390/include/asm/sections.h b/arch/s390/include/asm/sections.h
index af670fa4b12a..42de04ad9c07 100644
--- a/arch/s390/include/asm/sections.h
+++ b/arch/s390/include/asm/sections.h
@@ -2,8 +2,20 @@
2#ifndef _S390_SECTIONS_H 2#ifndef _S390_SECTIONS_H
3#define _S390_SECTIONS_H 3#define _S390_SECTIONS_H
4 4
5#define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed
6
5#include <asm-generic/sections.h> 7#include <asm-generic/sections.h>
6 8
9extern bool initmem_freed;
10
11static inline int arch_is_kernel_initmem_freed(unsigned long addr)
12{
13 if (!initmem_freed)
14 return 0;
15 return addr >= (unsigned long)__init_begin &&
16 addr < (unsigned long)__init_end;
17}
18
7/* 19/*
8 * .boot.data section contains variables "shared" between the decompressor and 20 * .boot.data section contains variables "shared" between the decompressor and
9 * the decompressed kernel. The decompressor will store values in them, and 21 * the decompressed kernel. The decompressor will store values in them, and
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 3e82f66d5c61..7cf48eefec8f 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -49,6 +49,8 @@ unsigned long empty_zero_page, zero_page_mask;
49EXPORT_SYMBOL(empty_zero_page); 49EXPORT_SYMBOL(empty_zero_page);
50EXPORT_SYMBOL(zero_page_mask); 50EXPORT_SYMBOL(zero_page_mask);
51 51
52bool initmem_freed;
53
52static void __init setup_zero_pages(void) 54static void __init setup_zero_pages(void)
53{ 55{
54 unsigned int order; 56 unsigned int order;
@@ -148,6 +150,7 @@ void __init mem_init(void)
148 150
149void free_initmem(void) 151void free_initmem(void)
150{ 152{
153 initmem_freed = true;
151 __set_memory((unsigned long)_sinittext, 154 __set_memory((unsigned long)_sinittext,
152 (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT, 155 (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT,
153 SET_MEMORY_RW | SET_MEMORY_NX); 156 SET_MEMORY_RW | SET_MEMORY_NX);
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index d79abca81a52..d1779d442aa5 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -77,6 +77,20 @@ static inline int arch_is_kernel_data(unsigned long addr)
77} 77}
78#endif 78#endif
79 79
80/*
81 * Check if an address is part of freed initmem. This is needed on architectures
82 * with virt == phys kernel mapping, for code that wants to check if an address
83 * is part of a static object within [_stext, _end]. After initmem is freed,
84 * memory can be allocated from it, and such allocations would then have
85 * addresses within the range [_stext, _end].
86 */
87#ifndef arch_is_kernel_initmem_freed
88static inline int arch_is_kernel_initmem_freed(unsigned long addr)
89{
90 return 0;
91}
92#endif
93
80/** 94/**
81 * memory_contains - checks if an object is contained within a memory region 95 * memory_contains - checks if an object is contained within a memory region
82 * @begin: virtual address of the beginning of the memory region 96 * @begin: virtual address of the beginning of the memory region
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 34cdcbedda49..22a99530983e 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -649,6 +649,9 @@ static int static_obj(const void *obj)
649 end = (unsigned long) &_end, 649 end = (unsigned long) &_end,
650 addr = (unsigned long) obj; 650 addr = (unsigned long) obj;
651 651
652 if (arch_is_kernel_initmem_freed(addr))
653 return 0;
654
652 /* 655 /*
653 * static variable? 656 * static variable?
654 */ 657 */