mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
locking/lockdep: Handle statically initialized PER_CPU locks properly
If a PER_CPU struct which contains a spin_lock is statically initialized
via:
DEFINE_PER_CPU(struct foo, bla) = {
.lock = __SPIN_LOCK_UNLOCKED(bla.lock)
};
then lockdep assigns a seperate key to each lock because the logic for
assigning a key to statically initialized locks is to use the address as
the key. With per CPU locks the address is obvioulsy different on each CPU.
That's wrong, because all locks should have the same key.
To solve this the following modifications are required:
1) Extend the is_kernel/module_percpu_addr() functions to hand back the
canonical address of the per CPU address, i.e. the per CPU address
minus the per CPU offset.
2) Check the lock address with these functions and if the per CPU check
matches use the returned canonical address as the lock key, so all per
CPU locks have the same key.
3) Move the static_obj(key) check into look_up_lock_class() so this check
can be avoided for statically initialized per CPU locks. That's
required because the canonical address fails the static_obj(key) check
for obvious reasons.
Reported-by: Mike Galbraith <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
[ Merged Dan's fixups for !MODULES and !SMP into this patch. ]
Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Dan Murphy <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Paul E. McKenney <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
This commit is contained in:
parent
6419c4af77
commit
383776fa75
5 changed files with 77 additions and 36 deletions
37
mm/percpu.c
37
mm/percpu.c
|
|
@ -1281,6 +1281,28 @@ void free_percpu(void __percpu *ptr)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(free_percpu);
|
||||
|
||||
bool __is_kernel_percpu_address(unsigned long addr, unsigned long *can_addr)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
const size_t static_size = __per_cpu_end - __per_cpu_start;
|
||||
void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
void *start = per_cpu_ptr(base, cpu);
|
||||
void *va = (void *)addr;
|
||||
|
||||
if (va >= start && va < start + static_size) {
|
||||
if (can_addr)
|
||||
*can_addr = (unsigned long) (va - start);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* on UP, can't distinguish from other static vars, always false */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_kernel_percpu_address - test whether address is from static percpu area
|
||||
* @addr: address to test
|
||||
|
|
@ -1294,20 +1316,7 @@ EXPORT_SYMBOL_GPL(free_percpu);
|
|||
*/
|
||||
bool is_kernel_percpu_address(unsigned long addr)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
const size_t static_size = __per_cpu_end - __per_cpu_start;
|
||||
void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
|
||||
unsigned int cpu;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
void *start = per_cpu_ptr(base, cpu);
|
||||
|
||||
if ((void *)addr >= start && (void *)addr < start + static_size)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
/* on UP, can't distinguish from other static vars, always false */
|
||||
return false;
|
||||
return __is_kernel_percpu_address(addr, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue