--- include/linux/percpu.h | 8 +++----- mm/allocpercpu.c | 11 +++++++---- 2 files changed, 10 insertions(+), 9 deletions(-) Index: linux-2.6/include/linux/percpu.h =================================================================== --- linux-2.6.orig/include/linux/percpu.h 2007-10-30 22:53:24.000000000 -0700 +++ linux-2.6/include/linux/percpu.h 2007-10-31 08:28:45.000000000 -0700 @@ -33,8 +33,6 @@ #ifdef CONFIG_SMP -DECLARE_PER_CPU(int, cpu_area)[]; - #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) /* * Use this to get to a cpu's version of the per-cpu object dynamically @@ -43,9 +41,9 @@ DECLARE_PER_CPU(int, cpu_area)[]; */ #define percpu_ptr(ptr, cpu) \ ({ \ - void *p = __percpu_disguise(ptr); \ - void *q = per_cpu(cpu_area, cpu) + (unsigned long)p; \ - (__typeof__(ptr))(q); \ + void *p = __percpu_disguise(ptr); \ + unsigned long q = per_cpu_offset(cpu); \ + (__typeof__(ptr))(p + q); \ }) extern void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu); Index: linux-2.6/mm/allocpercpu.c =================================================================== --- linux-2.6.orig/mm/allocpercpu.c 2007-10-30 22:53:49.000000000 -0700 +++ linux-2.6/mm/allocpercpu.c 2007-10-31 08:31:00.000000000 -0700 @@ -16,8 +16,9 @@ enum unit_type { FREE, END, USED }; static DEFINE_SPINLOCK(cpu_area_lock); static u8 cpu_alloc_map[UNITS_PER_CPU] = { 1, }; -DEFINE_PER_CPU(int, cpu_area)[UNITS_PER_CPU]; -EXPORT_PER_CPU_SYMBOL(cpu_area); +static DEFINE_PER_CPU(int, cpu_area)[UNITS_PER_CPU]; + +#define CPU_DATA_OFFSET ((unsigned long)&per_cpu__cpu_area) static inline int size_to_units(unsigned long size) { @@ -70,7 +71,7 @@ static inline void *cpu_alloc(unsigned l set_map(start, units); __count_vm_events(ALLOC_PERCPU, units * sizeof(int)); spin_unlock(&cpu_area_lock); - return (void *)start; + return (void *)(start * sizeof(int) + CPU_DATA_OFFSET); } static inline void cpu_free(void *pcpu) @@ -78,6 +79,8 @@ static inline void cpu_free(void *pcpu) unsigned long start = (unsigned long)pcpu; int units; + BUG_ON(start < CPU_DATA_OFFSET); + start = (start - CPU_DATA_OFFSET) / sizeof(int); BUG_ON(cpu_alloc_map[start] == FREE || start >= UNITS_PER_CPU); @@ -131,7 +134,7 @@ EXPORT_SYMBOL_GPL(__percpu_depopulate_ma void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu) { int pdata = (unsigned long)__percpu_disguise(__pdata); - void *p = per_cpu(cpu_area, cpu) + pdata; + void *p = (void *)per_cpu_offset(cpu) + pdata; memset(p, 0, size); return p;