[PATCH] powerpc/lockdep: fix a false positive warning
From: Qian Cai <hidden>
Date: 2019-09-06 20:01:19
Also in:
linux-arch, lkml
Subsystem:
generic include/asm header files, kernel virtual machine for powerpc (kvm/powerpc), linux for powerpc (32-bit and 64-bit), locking primitives, the rest · Maintainers:
Arnd Bergmann, Madhavan Srinivasan, Peter Zijlstra, Ingo Molnar, Will Deacon, Boqun Feng, Linus Torvalds
The commit 108c14858b9e ("locking/lockdep: Add support for dynamic
keys") introduced a boot warning on powerpc below, because since the
commit 2d4f567103ff ("KVM: PPC: Introduce kvm_tmp framework") adds
kvm_tmp[] into the .bss section and then free the rest of unused spaces
back to the page allocator.
kernel_init
kvm_guest_init
kvm_free_tmp
free_reserved_area
free_unref_page
free_unref_page_prepare
Later, alloc_workqueue() happens to allocate some pages from there and
trigger the warning at,
if (WARN_ON_ONCE(static_obj(key)))
Fix it by adding a generic helper arch_is_bss_hole() to skip those areas
in static_obj(). Since kvm_free_tmp() is only done early during the
boot, just go lockless to make the implementation simple for now.
WARNING: CPU: 0 PID: 13 at kernel/locking/lockdep.c:1120
Workqueue: events work_for_cpu_fn
Call Trace:
lockdep_register_key+0x68/0x200
wq_init_lockdep+0x40/0xc0
trunc_msg+0x385f9/0x4c30f (unreliable)
wq_init_lockdep+0x40/0xc0
alloc_workqueue+0x1e0/0x620
scsi_host_alloc+0x3d8/0x490
ata_scsi_add_hosts+0xd0/0x220 [libata]
ata_host_register+0x178/0x400 [libata]
ata_host_activate+0x17c/0x210 [libata]
ahci_host_activate+0x84/0x250 [libahci]
ahci_init_one+0xc74/0xdc0 [ahci]
local_pci_probe+0x78/0x100
work_for_cpu_fn+0x40/0x70
process_one_work+0x388/0x750
process_scheduled_works+0x50/0x90
worker_thread+0x3d0/0x570
kthread+0x1b8/0x1e0
ret_from_kernel_thread+0x5c/0x7c
Fixes: 108c14858b9e ("locking/lockdep: Add support for dynamic keys")
Signed-off-by: Qian Cai <redacted>
---
arch/powerpc/include/asm/sections.h | 10 ++++++++++
arch/powerpc/kernel/kvm.c | 5 +++++
include/asm-generic/sections.h | 7 +++++++
kernel/locking/lockdep.c | 3 +++
4 files changed, 25 insertions(+)
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index 4a1664a8658d..abd08b3cb3f3 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h@@ -5,8 +5,12 @@ #include <linux/elf.h> #include <linux/uaccess.h> + +#define arch_is_bss_hole arch_is_bss_hole + #include <asm-generic/sections.h> +extern void *bss_hole_start, *bss_hole_end; extern char __head_end[]; #ifdef __powerpc64__
@@ -24,6 +28,12 @@ extern char end_virt_trampolines[]; #endif +static inline int arch_is_bss_hole(unsigned long addr) +{ + return addr >= (unsigned long)bss_hole_start && + addr < (unsigned long)bss_hole_end; +} + static inline int in_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index b7b3a5e4e224..89e0e522e125 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c@@ -66,6 +66,7 @@ static bool kvm_patching_worked = true; char kvm_tmp[1024 * 1024]; static int kvm_tmp_index; +void *bss_hole_start, *bss_hole_end; static inline void kvm_patch_ins(u32 *inst, u32 new_inst) {
@@ -707,6 +708,10 @@ static __init void kvm_free_tmp(void) */ kmemleak_free_part(&kvm_tmp[kvm_tmp_index], ARRAY_SIZE(kvm_tmp) - kvm_tmp_index); + + bss_hole_start = &kvm_tmp[kvm_tmp_index]; + bss_hole_end = &kvm_tmp[ARRAY_SIZE(kvm_tmp)]; + free_reserved_area(&kvm_tmp[kvm_tmp_index], &kvm_tmp[ARRAY_SIZE(kvm_tmp)], -1, NULL); }
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index d1779d442aa5..4d8b1f2c5fd9 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h@@ -91,6 +91,13 @@ static inline int arch_is_kernel_initmem_freed(unsigned long addr) } #endif +#ifndef arch_is_bss_hole +static inline int arch_is_bss_hole(unsigned long addr) +{ + return 0; +} +#endif + /** * memory_contains - checks if an object is contained within a memory region * @begin: virtual address of the beginning of the memory region
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 4861cf8e274b..cd75b51f15ce 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c@@ -675,6 +675,9 @@ static int static_obj(const void *obj) if (arch_is_kernel_initmem_freed(addr)) return 0; + if (arch_is_bss_hole(addr)) + return 0; + /* * static variable? */
--
1.8.3.1