---
 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;