Support an option CONFIG_PERCPU_ZERO_BASED that makes offsets for per cpu variables start at zero. If a percpu area starts at zero then 1. We do not need RELOC_HIDE anymore 2. Indexes off the per cpu area for each processor are small 3. The percpu area "addresses" are offsets and we can then have allocpercpu/cpu_alloc in the future also use these offsets so that percpu functions can take any type of percpu address if it is provided by a percpu variable or a pointer obtained via allocpercpu/cpu_alloc. The linker area boundaries variables are different for zero based percpu segments: __per_cpu_load -> The address at which the percpu area was loaded __per_cpu_size -> The length of the per cpu area Removes the &__per_cpu_x in lockdep. AFAICT The __per_cpu_x are already pointers. Signed-off-by: Christoph Lameter --- include/asm-generic/percpu.h | 7 ++++++- include/asm-generic/sections.h | 10 ++++++++++ include/asm-generic/vmlinux.lds.h | 15 +++++++++++++++ init/main.c | 17 +++++++++-------- kernel/lockdep.c | 4 ++-- 5 files changed, 42 insertions(+), 11 deletions(-) Index: linux-2.6.24-rc3-mm2/include/asm-generic/percpu.h =================================================================== --- linux-2.6.24-rc3-mm2.orig/include/asm-generic/percpu.h 2007-11-29 22:05:58.359576450 -0800 +++ linux-2.6.24-rc3-mm2/include/asm-generic/percpu.h 2007-11-29 22:06:22.750825804 -0800 @@ -42,8 +42,13 @@ extern unsigned long __per_cpu_offset[NR * Only S390 provides its own means of moving the pointer. */ #ifndef SHIFT_PTR +#ifdef CONFIG_PERCPU_ZERO_BASED +#define SHIFT_PTR(__p, __offset) \ + ((__typeof(__p))(((void *)(__p)) + (__offset))) +#else #define SHIFT_PTR(__p, __offset) RELOC_HIDE((__p), (__offset)) -#endif +#endif /* CONFIG_PER_CPU_ZERO_BASED */ +#endif /* SHIFT_PTR */ /* * A percpu variable may point to a discarded reghions. The following are Index: linux-2.6.24-rc3-mm2/include/asm-generic/sections.h =================================================================== --- linux-2.6.24-rc3-mm2.orig/include/asm-generic/sections.h 2007-11-29 22:05:58.367576240 -0800 +++ linux-2.6.24-rc3-mm2/include/asm-generic/sections.h 2007-11-29 22:06:22.754826440 -0800 @@ -9,7 +9,17 @@ extern char __bss_start[], __bss_stop[]; extern char __init_begin[], __init_end[]; extern char _sinittext[], _einittext[]; extern char _end[]; +#ifdef CONFIG_PERCPU_ZERO_BASED +extern char __per_cpu_load[]; +extern char ____per_cpu_size[]; +#define __per_cpu_size ((unsigned long)&____per_cpu_size) +#define __per_cpu_start ((char *)0) +#define __per_cpu_end ((char *)__per_cpu_size) +#else extern char __per_cpu_start[], __per_cpu_end[]; +#define __per_cpu_load __per_cpu_start +#define __per_cpu_size (__per_cpu_end - __per_cpu_start) +#endif extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __initdata_begin[], __initdata_end[]; extern char __start_rodata[], __end_rodata[]; Index: linux-2.6.24-rc3-mm2/include/asm-generic/vmlinux.lds.h =================================================================== --- linux-2.6.24-rc3-mm2.orig/include/asm-generic/vmlinux.lds.h 2007-11-29 22:06:03.486826118 -0800 +++ linux-2.6.24-rc3-mm2/include/asm-generic/vmlinux.lds.h 2007-11-29 22:06:22.754826440 -0800 @@ -255,6 +255,20 @@ *(.initcall7.init) \ *(.initcall7s.init) +#ifdef CONFIG_PERCPU_ZERO_BASED +#define PERCPU(align) \ + . = ALIGN(align); \ + percpu : { } :percpu \ + __per_cpu_load = .; \ + .data.percpu 0 : AT(__per_cpu_load - LOAD_OFFSET) { \ + *(.data.percpu.first) \ + *(.data.percpu) \ + *(.data.percpu.shared_aligned) \ + ____per_cpu_size = .; \ + } \ + . = __per_cpu_load + ____per_cpu_size; \ + data : { } :data +#else #define PERCPU(align) \ . = ALIGN(align); \ __per_cpu_start = .; \ @@ -263,3 +277,4 @@ *(.data.percpu.shared_aligned) \ } \ __per_cpu_end = .; +#endif Index: linux-2.6.24-rc3-mm2/init/main.c =================================================================== --- linux-2.6.24-rc3-mm2.orig/init/main.c 2007-11-29 22:06:01.607326159 -0800 +++ linux-2.6.24-rc3-mm2/init/main.c 2007-11-29 22:06:22.754826440 -0800 @@ -370,18 +370,19 @@ EXPORT_SYMBOL(__per_cpu_offset); static void __init setup_per_cpu_areas(void) { - unsigned long size, i; - char *ptr; - unsigned long nr_possible_cpus = num_possible_cpus(); + unsigned long size; + int cpu; /* Copy section for each CPU (we discard the original) */ size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE); - ptr = alloc_bootmem_pages(size * nr_possible_cpus); - for_each_possible_cpu(i) { - __per_cpu_offset[i] = ptr - __per_cpu_start; - memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); - ptr += size; + for_each_possible_cpu(cpu) { + char *ptr; + + ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(cpu)), + size); + __per_cpu_offset[cpu] = ptr - __per_cpu_start; + memcpy(ptr, __per_cpu_load, __per_cpu_size); } } #endif /* CONFIG_ARCH_SETS_UP_CPU_AREA */ Index: linux-2.6.24-rc3-mm2/kernel/lockdep.c =================================================================== --- linux-2.6.24-rc3-mm2.orig/kernel/lockdep.c 2007-11-29 22:05:58.391576218 -0800 +++ linux-2.6.24-rc3-mm2/kernel/lockdep.c 2007-11-29 22:06:22.754826440 -0800 @@ -613,8 +613,8 @@ static int static_obj(void *obj) * percpu var? */ for_each_possible_cpu(i) { - start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); - end = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM + start = (unsigned long) __per_cpu_start + per_cpu_offset(i); + end = (unsigned long) __per_cpu_start + PERCPU_ENOUGH_ROOM + per_cpu_offset(i); if ((addr >= start) && (addr < end)) -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/