diff options
author | Tejun Heo <tj@kernel.org> | 2010-03-10 04:57:54 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-03-29 10:07:12 -0400 |
commit | 10fad5e46f6c7bdfb01b1a012380a38e3c6ab346 (patch) | |
tree | 9ec6e3955e7f879f64ea79812cf5ecd41baa6939 /kernel | |
parent | 259354deaaf03d49a02dbb9975d6ec2a54675672 (diff) |
percpu, module: implement and use is_kernel/module_percpu_address()
lockdep has custom code to check whether a pointer belongs to static
percpu area which is somewhat broken. Implement proper
is_kernel/module_percpu_address() and replace the custom code.
On UP, percpu variables are regular static variables and can't be
distinguished from them. Always return %false on UP.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Ingo Molnar <mingo@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/lockdep.c | 21 | ||||
-rw-r--r-- | kernel/module.c | 38 |
2 files changed, 43 insertions, 16 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index c927a549db2c..9bbb9c841e48 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -582,9 +582,6 @@ static int static_obj(void *obj) | |||
582 | unsigned long start = (unsigned long) &_stext, | 582 | unsigned long start = (unsigned long) &_stext, |
583 | end = (unsigned long) &_end, | 583 | end = (unsigned long) &_end, |
584 | addr = (unsigned long) obj; | 584 | addr = (unsigned long) obj; |
585 | #ifdef CONFIG_SMP | ||
586 | int i; | ||
587 | #endif | ||
588 | 585 | ||
589 | /* | 586 | /* |
590 | * static variable? | 587 | * static variable? |
@@ -595,24 +592,16 @@ static int static_obj(void *obj) | |||
595 | if (arch_is_kernel_data(addr)) | 592 | if (arch_is_kernel_data(addr)) |
596 | return 1; | 593 | return 1; |
597 | 594 | ||
598 | #ifdef CONFIG_SMP | ||
599 | /* | 595 | /* |
600 | * percpu var? | 596 | * in-kernel percpu var? |
601 | */ | 597 | */ |
602 | for_each_possible_cpu(i) { | 598 | if (is_kernel_percpu_address(addr)) |
603 | start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); | 599 | return 1; |
604 | end = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM | ||
605 | + per_cpu_offset(i); | ||
606 | |||
607 | if ((addr >= start) && (addr < end)) | ||
608 | return 1; | ||
609 | } | ||
610 | #endif | ||
611 | 600 | ||
612 | /* | 601 | /* |
613 | * module var? | 602 | * module static or percpu var? |
614 | */ | 603 | */ |
615 | return is_module_address(addr); | 604 | return is_module_address(addr) || is_module_percpu_address(addr); |
616 | } | 605 | } |
617 | 606 | ||
618 | /* | 607 | /* |
diff --git a/kernel/module.c b/kernel/module.c index e7a6e53fc73e..9f8d23d8b3a8 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -415,6 +415,40 @@ static void percpu_modcopy(struct module *mod, | |||
415 | memcpy(per_cpu_ptr(mod->percpu, cpu), from, size); | 415 | memcpy(per_cpu_ptr(mod->percpu, cpu), from, size); |
416 | } | 416 | } |
417 | 417 | ||
418 | /** | ||
419 | * is_module_percpu_address - test whether address is from module static percpu | ||
420 | * @addr: address to test | ||
421 | * | ||
422 | * Test whether @addr belongs to module static percpu area. | ||
423 | * | ||
424 | * RETURNS: | ||
425 | * %true if @addr is from module static percpu area | ||
426 | */ | ||
427 | bool is_module_percpu_address(unsigned long addr) | ||
428 | { | ||
429 | struct module *mod; | ||
430 | unsigned int cpu; | ||
431 | |||
432 | preempt_disable(); | ||
433 | |||
434 | list_for_each_entry_rcu(mod, &modules, list) { | ||
435 | if (!mod->percpu_size) | ||
436 | continue; | ||
437 | for_each_possible_cpu(cpu) { | ||
438 | void *start = per_cpu_ptr(mod->percpu, cpu); | ||
439 | |||
440 | if ((void *)addr >= start && | ||
441 | (void *)addr < start + mod->percpu_size) { | ||
442 | preempt_enable(); | ||
443 | return true; | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | |||
448 | preempt_enable(); | ||
449 | return false; | ||
450 | } | ||
451 | |||
418 | #else /* ... !CONFIG_SMP */ | 452 | #else /* ... !CONFIG_SMP */ |
419 | 453 | ||
420 | static inline void __percpu *mod_percpu(struct module *mod) | 454 | static inline void __percpu *mod_percpu(struct module *mod) |
@@ -441,6 +475,10 @@ static inline void percpu_modcopy(struct module *mod, | |||
441 | /* pcpusec should be 0, and size of that section should be 0. */ | 475 | /* pcpusec should be 0, and size of that section should be 0. */ |
442 | BUG_ON(size != 0); | 476 | BUG_ON(size != 0); |
443 | } | 477 | } |
478 | bool is_module_percpu_address(unsigned long addr) | ||
479 | { | ||
480 | return false; | ||
481 | } | ||
444 | 482 | ||
445 | #endif /* CONFIG_SMP */ | 483 | #endif /* CONFIG_SMP */ |
446 | 484 | ||