It's useful to check that no one is accessing > nr_cpumask_bits for cpumasks. This also allows you to turn on CONFIG_CPUMASKS_OFFSTACK even for smaller CONFIG_NR_CPUS. From: Rusty Russell Signed-off-by: Rusty Russell Signed-off-by: Mike Travis --- include/linux/cpumask.h | 23 +++++++++++++++++------ lib/Kconfig.debug | 6 ++++++ lib/cpumask.c | 3 +++ 3 files changed, 26 insertions(+), 6 deletions(-) --- test-compile.orig/include/linux/cpumask.h +++ test-compile/include/linux/cpumask.h @@ -217,23 +217,34 @@ extern cpumask_t _unused_cpumask_arg_; } #endif /* CONFIG_NR_CPUS > BITS_PER_LONG */ +/* verify cpu argument to cpumask_* operators */ +static inline unsigned int cpumask_check(unsigned int cpu) +{ +#ifdef CONFIG_DEBUG_PER_CPU_MAPS + /* This breaks at runtime. */ + BUG_ON(cpu >= nr_cpumask_bits); +#endif /* CONFIG_DEBUG_PER_CPU_MAPS */ + return cpu; +} + /* cpumask_* operators */ static inline void cpumask_set_cpu(int cpu, volatile struct cpumask *dstp) { - set_bit(cpu, cpumask_bits(dstp)); + set_bit(cpumask_check(cpu), cpumask_bits(dstp)); } static inline void cpumask_clear_cpu(int cpu, volatile struct cpumask *dstp) { - clear_bit(cpu, cpumask_bits(dstp)); + clear_bit(cpumask_check(cpu), cpumask_bits(dstp)); } /* No static inline type checking - see Subtlety (1) above. */ -#define cpumask_test_cpu(cpu, cpumask) test_bit((cpu), (cpumask)->bits) +#define cpumask_test_cpu(cpu, cpumask) \ + test_bit(cpumask_check(cpu), (cpumask)->bits) static inline int cpumask_test_and_set_cpu(int cpu, struct cpumask *addr) { - return test_and_set_bit(cpu, cpumask_bits(addr)); + return test_and_set_bit(cpumask_check(cpu), cpumask_bits(addr)); } static inline void cpumask_setall(struct cpumask *dstp) @@ -367,8 +378,8 @@ static inline int cpumask_cpuremap(int o const struct cpumask *oldp, const struct cpumask *newp) { - return bitmap_bitremap(oldbit, cpumask_bits(oldp), cpumask_bits(newp), - nr_cpumask_bits); + return bitmap_bitremap(cpumask_check(oldbit), cpumask_bits(oldp), + cpumask_bits(newp), nr_cpumask_bits); } static inline void cpumask_remap(struct cpumask *dstp, --- test-compile.orig/lib/Kconfig.debug +++ test-compile/lib/Kconfig.debug @@ -766,6 +766,12 @@ config SYSCTL_SYSCALL_CHECK to properly maintain and use. This enables checks that help you to keep things correct. +config DEBUG_PER_CPU_MAPS + bool "Cpumask debug checks" + ---help--- + Extra debugging for cpumasks. + eg. to make sure accesses to cpumasks are < nr_cpu_ids. + source kernel/trace/Kconfig config PROVIDE_OHCI1394_DMA_INIT --- test-compile.orig/lib/cpumask.c +++ test-compile/lib/cpumask.c @@ -11,6 +11,9 @@ EXPORT_SYMBOL(cpumask_first); int cpumask_next(int n, const cpumask_t *srcp) { + /* -1 is a legal arg here. */ + if (n != -1) + cpumask_check(n); return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1); } EXPORT_SYMBOL(cpumask_next); --