linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-10-16  8:18 ` [PATCH 0/1] " Andrew Morton
@ 2007-08-04  1:15   ` Mike Travis
  2007-10-16 15:02   ` Christoph Lameter
  1 sibling, 0 replies; 9+ messages in thread
From: Mike Travis @ 2007-08-04  1:15 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Andi Kleen, Christoph Lameter, Jack Steiner, linux-mm,
	linux-kernel

Andrew Morton wrote:
...
>> ...  This patch deals with the cpu_data array of
>> cpuinfo_x86 structs.  The model that was used in sparc64
>> architecture was adopted for x86.
>>
> 
> This has mysteriously started to oops on me, only on x86_64.
> 
> http://userweb.kernel.org/~akpm/config-x.txt
> http://userweb.kernel.org/~akpm/dsc00001.jpg
> 
> which is a bit strange since this patch doesn't touch sched.c.  Maybe
> there's something somewhere else in the -mm lineup which when combined with
> this prevents it from oopsing, dunno.  I'll hold it back for now and will
> see what happens.
> 

I'll take a look at this right away.

Thanks,
Mike

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
@ 2007-09-24 21:08 travis
  2007-09-24 21:08 ` [PATCH 1/1] " travis
  2007-10-16  8:18 ` [PATCH 0/1] " Andrew Morton
  0 siblings, 2 replies; 9+ messages in thread
From: travis @ 2007-09-24 21:08 UTC (permalink / raw)
  To: Andrew Morton, Andi Kleen
  Cc: Christoph Lameter, Jack Steiner, linux-mm, linux-kernel

v3: fix compile errors in arch-i386-allmodconfig build

v2: rebasing on 2.6.23-rc6-mm1

Analyzing various data structures when NR_CPU count is raised
to 4096 shows the following arrays over 128k.  If the maximum
number of cpus are not installed (about 99.99% of the time),
then a large percentage of this memory is wasted.
--
	151289856  CALNDATA  irq_desc
	135530496  RMDATATA  irq_cfg
	  3145728  CALNDATA  cpu_data
	  2101248  BSS       irq_lists
	  2097152  RMDATATA  cpu_sibling_map
	  2097152  RMDATATA  cpu_core_map
	  1575936  BSS       irq_2_pin
	  1050624  BSS       irq_timer_state
	   614400  INITDATA  early_node_map
	   525376  PERCPU    per_cpu__kstat
	   524608  DATA      unix_proto
	   524608  DATA      udpv6_prot
	   524608  DATA      udplitev6_prot
	   524608  DATA      udplite_prot
	   524608  DATA      udp_prot
	   524608  DATA      tcpv6_prot
	   524608  DATA      tcp_prot
	   524608  DATA      rawv6_prot
	   524608  DATA      raw_prot
	   524608  DATA      packet_proto
	   524608  DATA      netlink_proto
	   524288  BSS       cpu_devices
	   524288  BSS       boot_pageset
	   524288  CALNDATA  boot_cpu_pda
	   262144  RMDATATA  node_to_cpumask
	   262144  BSS       __log_buf
	   131072  BSS       entries

cpu_sibling_map and cpu_core_map have been taken care of in
a prior patch.  This patch deals with the cpu_data array of
cpuinfo_x86 structs.  The model that was used in sparc64
architecture was adopted for x86.

-- 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-24 21:08 [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3 travis
@ 2007-09-24 21:08 ` travis
  2007-09-24 22:01   ` roel
  2007-10-16  8:18 ` [PATCH 0/1] " Andrew Morton
  1 sibling, 1 reply; 9+ messages in thread
From: travis @ 2007-09-24 21:08 UTC (permalink / raw)
  To: Andrew Morton, Andi Kleen
  Cc: Christoph Lameter, Jack Steiner, linux-mm, linux-kernel

[-- Attachment #1: convert-cpu_data --]
[-- Type: text/plain, Size: 39030 bytes --]

v2: rebasing on 2.6.23-rc6-mm1

cpu_data is currently an array defined using NR_CPUS. This means that
we overallocate since we will rarely really use maximum configured cpus.
When NR_CPU count is raised to 4096 the size of cpu_data becomes
3,145,728 bytes.

These changes were adopted from the sparc64 (and ia64) code.  An
additional field was added to cpuinfo_x86 to be a non-ambiguous
cpu index.  This corresponds to the index into a cpumask_t as
well as the per_cpu index.  It's used in various places like
show_cpuinfo().

cpu_data is defined to be the boot_cpu_data structure for the
NON-SMP case.

Signed-off-by: Mike Travis <travis@sgi.com>
Acked-by: Christoph Lameter <clameter@sgi.com>
---
 arch/i386/kernel/acpi/cstate.c                    |    4 -
 arch/i386/kernel/acpi/processor.c                 |    2 
 arch/i386/kernel/alternative.c                    |    6 +-
 arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c       |    4 -
 arch/i386/kernel/cpu/cpufreq/e_powersaver.c       |    2 
 arch/i386/kernel/cpu/cpufreq/elanfreq.c           |    4 -
 arch/i386/kernel/cpu/cpufreq/longhaul.c           |    4 -
 arch/i386/kernel/cpu/cpufreq/longrun.c            |    4 -
 arch/i386/kernel/cpu/cpufreq/p4-clockmod.c        |    4 -
 arch/i386/kernel/cpu/cpufreq/powernow-k6.c        |    2 
 arch/i386/kernel/cpu/cpufreq/powernow-k7.c        |    2 
 arch/i386/kernel/cpu/cpufreq/sc520_freq.c         |    4 -
 arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c |    6 +-
 arch/i386/kernel/cpu/cpufreq/speedstep-lib.c      |    2 
 arch/i386/kernel/cpu/intel_cacheinfo.c            |    8 +--
 arch/i386/kernel/cpu/proc.c                       |   11 +++-
 arch/i386/kernel/cpuid.c                          |    2 
 arch/i386/kernel/microcode.c                      |    6 +-
 arch/i386/kernel/msr.c                            |    2 
 arch/i386/kernel/sched-clock.c                    |    2 
 arch/i386/kernel/smp.c                            |    2 
 arch/i386/kernel/smpboot.c                        |   51 +++++++++++-----------
 arch/i386/kernel/tsc.c                            |    8 +--
 arch/i386/lib/delay.c                             |    2 
 arch/i386/mach-voyager/voyager_smp.c              |   12 ++---
 arch/x86_64/kernel/mce.c                          |    2 
 arch/x86_64/kernel/mce_amd.c                      |    4 -
 arch/x86_64/kernel/setup.c                        |   20 +++++---
 arch/x86_64/kernel/smpboot.c                      |   45 +++++++++----------
 arch/x86_64/kernel/tsc.c                          |    4 -
 arch/x86_64/kernel/vsyscall.c                     |    2 
 arch/x86_64/lib/delay.c                           |    3 -
 drivers/hwmon/coretemp.c                          |    6 +-
 drivers/hwmon/hwmon-vid.c                         |    2 
 drivers/input/gameport/gameport.c                 |    3 -
 drivers/video/geode/video_gx.c                    |    2 
 include/asm-i386/processor.h                      |   10 ++--
 include/asm-i386/topology.h                       |    4 -
 include/asm-x86_64/processor.h                    |   10 ++--
 include/asm-x86_64/topology.h                     |    4 -
 40 files changed, 148 insertions(+), 129 deletions(-)

--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -84,8 +84,8 @@ cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 
 /* Per CPU bogomips and other parameters */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 /* Set when the idlers are all forked */
 int smp_threads_ready;
@@ -138,9 +138,10 @@ static unsigned long __cpuinit setup_tra
 
 static void __cpuinit smp_store_cpu_info(int id)
 {
-	struct cpuinfo_x86 *c = cpu_data + id;
+	struct cpuinfo_x86 *c = &cpu_data(id);
 
 	*c = boot_cpu_data;
+	c->cpu_index = id;
 	identify_cpu(c);
 	print_cpu_info(c);
 }
@@ -238,7 +239,7 @@ void __cpuinit smp_callin(void)
 /* maps the cpu to the sched domain representing multi-core */
 cpumask_t cpu_coregroup_map(int cpu)
 {
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	/*
 	 * For perf, we return last level cache shared map.
 	 * And for power savings, we return cpu_core_map
@@ -255,41 +256,41 @@ static cpumask_t cpu_sibling_setup_map;
 static inline void set_cpu_sibling_map(int cpu)
 {
 	int i;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	cpu_set(cpu, cpu_sibling_setup_map);
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
-			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
+			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
 				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
 				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
 				cpu_set(i, per_cpu(cpu_core_map, cpu));
 				cpu_set(cpu, per_cpu(cpu_core_map, i));
-				cpu_set(i, c[cpu].llc_shared_map);
-				cpu_set(cpu, c[i].llc_shared_map);
+				cpu_set(i, c->llc_shared_map);
+				cpu_set(cpu, cpu_data(i).llc_shared_map);
 			}
 		}
 	} else {
 		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
 	}
 
-	cpu_set(cpu, c[cpu].llc_shared_map);
+	cpu_set(cpu, c->llc_shared_map);
 
 	if (current_cpu_data.x86_max_cores == 1) {
 		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
-		c[cpu].booted_cores = 1;
+		c->booted_cores = 1;
 		return;
 	}
 
 	for_each_cpu_mask(i, cpu_sibling_setup_map) {
 		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
 		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
-			cpu_set(i, c[cpu].llc_shared_map);
-			cpu_set(cpu, c[i].llc_shared_map);
+			cpu_set(i, c->llc_shared_map);
+			cpu_set(cpu, cpu_data(i).llc_shared_map);
 		}
-		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
+		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
 			cpu_set(i, per_cpu(cpu_core_map, cpu));
 			cpu_set(cpu, per_cpu(cpu_core_map, i));
 			/*
@@ -301,15 +302,15 @@ static inline void set_cpu_sibling_map(i
 				 * the booted_cores for this new cpu
 				 */
 				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
-					c[cpu].booted_cores++;
+					c->booted_cores++;
 				/*
 				 * increment the core count for all
 				 * the other cpus in this package
 				 */
 				if (i != cpu)
-					c[i].booted_cores++;
-			} else if (i != cpu && !c[cpu].booted_cores)
-				c[cpu].booted_cores = c[i].booted_cores;
+					cpu_data(i).booted_cores++;
+			} else if (i != cpu && !c->booted_cores)
+				c->booted_cores = cpu_data(i).booted_cores;
 		}
 	}
 }
@@ -1000,7 +1001,7 @@ void __init smp_cpus_done(unsigned int m
 static void remove_siblinginfo(int cpu)
 {
 	int sibling;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
 		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
@@ -1008,15 +1009,15 @@ static void remove_siblinginfo(int cpu)
 		 * last thread sibling in this cpu core going down
 		 */
 		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
-			c[sibling].booted_cores--;
+			cpu_data(sibling).booted_cores--;
 	}
 			
 	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
 		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
 	cpus_clear(per_cpu(cpu_sibling_map, cpu));
 	cpus_clear(per_cpu(cpu_core_map, cpu));
-	c[cpu].phys_proc_id = 0;
-	c[cpu].cpu_core_id = 0;
+	c->phys_proc_id = 0;
+	c->cpu_core_id = 0;
 	cpu_clear(cpu, cpu_sibling_setup_map);
 }
 
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -75,6 +75,7 @@ struct cpuinfo_x86 {
 	__u8	booted_cores;	/* number of cores as seen by OS */
 	__u8	phys_proc_id;	/* Physical Processor id. */
 	__u8	cpu_core_id;	/* Core id. */
+	__u8	cpu_index;	/* index into per_cpu list */
 #endif
 } ____cacheline_aligned;
 
@@ -89,11 +90,12 @@ struct cpuinfo_x86 {
 #define X86_VENDOR_UNKNOWN 0xff
 
 #ifdef CONFIG_SMP
-extern struct cpuinfo_x86 cpu_data[];
-#define current_cpu_data cpu_data[smp_processor_id()]
+DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+#define current_cpu_data	cpu_data(smp_processor_id())
 #else
-#define cpu_data (&boot_cpu_data)
-#define current_cpu_data boot_cpu_data
+#define cpu_data(cpu)		boot_cpu_data
+#define current_cpu_data	boot_cpu_data
 #endif
 
 extern char ignore_irq13;
--- a/arch/i386/kernel/acpi/cstate.c
+++ b/arch/i386/kernel/acpi/cstate.c
@@ -29,7 +29,7 @@
 void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 					unsigned int cpu)
 {
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	flags->bm_check = 0;
 	if (num_online_cpus() == 1)
@@ -72,7 +72,7 @@ int acpi_processor_ffh_cstate_probe(unsi
 		struct acpi_processor_cx *cx, struct acpi_power_register *reg)
 {
 	struct cstate_entry *percpu_entry;
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	cpumask_t saved_mask;
 	int retval;
--- a/arch/i386/kernel/acpi/processor.c
+++ b/arch/i386/kernel/acpi/processor.c
@@ -63,7 +63,7 @@ static void init_intel_pdc(struct acpi_p
 void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
 {
 	unsigned int cpu = pr->id;
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	pr->pdc = NULL;
 	if (c->x86_vendor == X86_VENDOR_INTEL)
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -353,14 +353,14 @@ void alternatives_smp_switch(int smp)
 	if (smp) {
 		printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
 		clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
-		clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+		clear_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
 		list_for_each_entry(mod, &smp_alt_modules, next)
 			alternatives_smp_lock(mod->locks, mod->locks_end,
 					      mod->text, mod->text_end);
 	} else {
 		printk(KERN_INFO "SMP alternatives: switching to UP code\n");
 		set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
-		set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+		set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
 		list_for_each_entry(mod, &smp_alt_modules, next)
 			alternatives_smp_unlock(mod->locks, mod->locks_end,
 						mod->text, mod->text_end);
@@ -428,7 +428,7 @@ void __init alternative_instructions(voi
 		if (1 == num_possible_cpus()) {
 			printk(KERN_INFO "SMP alternatives: switching to UP code\n");
 			set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
-			set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
+			set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
 			alternatives_smp_unlock(__smp_locks, __smp_locks_end,
 						_text, _etext);
 		}
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -77,7 +77,7 @@ static unsigned int acpi_pstate_strict;
 
 static int check_est_cpu(unsigned int cpuid)
 {
-	struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
+	struct cpuinfo_x86 *cpu = &cpu_data(cpuid);
 
 	if (cpu->x86_vendor != X86_VENDOR_INTEL ||
 	    !cpu_has(cpu, X86_FEATURE_EST))
@@ -560,7 +560,7 @@ static int acpi_cpufreq_cpu_init(struct 
 	unsigned int cpu = policy->cpu;
 	struct acpi_cpufreq_data *data;
 	unsigned int result = 0;
-	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+	struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
 	struct acpi_processor_performance *perf;
 
 	dprintk("acpi_cpufreq_cpu_init\n");
--- a/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
+++ b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
@@ -305,7 +305,7 @@ static struct cpufreq_driver eps_driver 
 
 static int __init eps_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	/* This driver will work only on Centaur C7 processors with
 	 * Enhanced SpeedStep/PowerSaver registers */
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
@@ -199,7 +199,7 @@ static int elanfreq_target (struct cpufr
 
 static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	unsigned int i;
 	int result;
 
@@ -280,7 +280,7 @@ static struct cpufreq_driver elanfreq_dr
 
 static int __init elanfreq_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	/* Test if we have the right hardware */
 	if ((c->x86_vendor != X86_VENDOR_AMD) ||
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -731,7 +731,7 @@ static int longhaul_setup_southbridge(vo
 
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	char *cpuname=NULL;
 	int ret;
 	u32 lo, hi;
@@ -910,7 +910,7 @@ static struct cpufreq_driver longhaul_dr
 
 static int __init longhaul_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
 		return -ENODEV;
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c
@@ -172,7 +172,7 @@ static unsigned int __init longrun_deter
 	u32 save_lo, save_hi;
 	u32 eax, ebx, ecx, edx;
 	u32 try_hi;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	if (!low_freq || !high_freq)
 		return -EINVAL;
@@ -298,7 +298,7 @@ static struct cpufreq_driver longrun_dri
  */
 static int __init longrun_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
 	    !cpu_has(c, X86_FEATURE_LONGRUN))
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequ
 
 static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+	struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
 	int cpuid = 0;
 	unsigned int i;
 
@@ -279,7 +279,7 @@ static struct cpufreq_driver p4clockmod_
 
 static int __init cpufreq_p4_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	int ret;
 
 	/*
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
@@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6
  */
 static int __init powernow_k6_init(void)
 {
-	struct cpuinfo_x86      *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 
 	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
 		((c->x86_model != 12) && (c->x86_model != 13)))
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -114,7 +114,7 @@ static int check_fsb(unsigned int fsbspe
 
 static int check_powernow(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	unsigned int maxei, eax, ebx, ecx, edx;
 
 	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
--- a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
+++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
@@ -102,7 +102,7 @@ static int sc520_freq_target (struct cpu
 
 static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	int result;
 
 	/* capability check */
@@ -151,7 +151,7 @@ static struct cpufreq_driver sc520_freq_
 
 static int __init sc520_freq_init(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	int err;
 
 	/* Test if we have the right hardware */
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -230,7 +230,7 @@ static struct cpu_model models[] =
 
 static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
+	struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
 	struct cpu_model *model;
 
 	for(model = models; model->cpu_id != NULL; model++)
@@ -340,7 +340,7 @@ static unsigned int get_cur_freq(unsigne
 
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
-	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
+	struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
 	unsigned freq;
 	unsigned l, h;
 	int ret;
@@ -612,7 +612,7 @@ static struct cpufreq_driver centrino_dr
  */
 static int __init centrino_init(void)
 {
-	struct cpuinfo_x86 *cpu = cpu_data;
+	struct cpuinfo_x86 *cpu = &cpu_data(0);
 
 	if (!cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -228,7 +228,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_processo
 
 unsigned int speedstep_detect_processor (void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	u32 ebx, msr_lo, msr_hi;
 
 	dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -295,7 +295,7 @@ unsigned int __cpuinit init_intel_cachei
 	unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
 	unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
 #ifdef CONFIG_X86_HT
-	unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
+	unsigned int cpu = c->cpu_index;
 #endif
 
 	if (c->cpuid_level > 3) {
@@ -459,7 +459,7 @@ static void __cpuinit cache_shared_cpu_m
 	struct _cpuid4_info	*this_leaf, *sibling_leaf;
 	unsigned long num_threads_sharing;
 	int index_msb, i;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	this_leaf = CPUID4_INFO_IDX(cpu, index);
 	num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
@@ -470,8 +470,8 @@ static void __cpuinit cache_shared_cpu_m
 		index_msb = get_count_order(num_threads_sharing);
 
 		for_each_online_cpu(i) {
-			if (c[i].apicid >> index_msb ==
-			    c[cpu].apicid >> index_msb) {
+			if (cpu_data(i).apicid >> index_msb ==
+			    c->apicid >> index_msb) {
 				cpu_set(i, this_leaf->shared_cpu_map);
 				if (i != cpu && cpuid4_info[i])  {
 					sibling_leaf = CPUID4_INFO_IDX(i, index);
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -116,7 +116,7 @@ static ssize_t cpuid_read(struct file *f
 static int cpuid_open(struct inode *inode, struct file *file)
 {
 	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
-	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	if (cpu >= NR_CPUS || !cpu_online(cpu))
 		return -ENXIO;	/* No such CPU */
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -132,7 +132,7 @@ static struct ucode_cpu_info {
 
 static void collect_cpu_info(int cpu_num)
 {
-	struct cpuinfo_x86 *c = cpu_data + cpu_num;
+	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 	unsigned int val[2];
 
@@ -522,7 +522,7 @@ static struct platform_device *microcode
 static int cpu_request_microcode(int cpu)
 {
 	char name[30];
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	const struct firmware *firmware;
 	void *buf;
 	unsigned long size;
@@ -570,7 +570,7 @@ static int cpu_request_microcode(int cpu
 
 static int apply_microcode_check_cpu(int cpu)
 {
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	cpumask_t old;
 	unsigned int val[2];
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -114,7 +114,7 @@ static ssize_t msr_write(struct file *fi
 static int msr_open(struct inode *inode, struct file *file)
 {
 	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
-	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	if (cpu >= NR_CPUS || !cpu_online(cpu))
 		return -ENXIO;	/* No such CPU */
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -610,7 +610,7 @@ static void stop_this_cpu (void * dummy)
 	 */
 	cpu_clear(smp_processor_id(), cpu_online_map);
 	disable_local_APIC();
-	if (cpu_data[smp_processor_id()].hlt_works_ok)
+	if (cpu_data(smp_processor_id()).hlt_works_ok)
 		for(;;) halt();
 	for (;;);
 }
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -89,8 +89,8 @@ EXPORT_SYMBOL(cpu_possible_map);
 static cpumask_t smp_commenced_mask;
 
 /* Per CPU bogomips and other parameters */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
+EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 /*
  * The following static array is used during kernel startup
@@ -158,9 +158,10 @@ void __init smp_alloc_memory(void)
 
 void __cpuinit smp_store_cpu_info(int id)
 {
-	struct cpuinfo_x86 *c = cpu_data + id;
+	struct cpuinfo_x86 *c = &cpu_data(id);
 
 	*c = boot_cpu_data;
+	c->cpu_index = id;
 	if (id!=0)
 		identify_secondary_cpu(c);
 	/*
@@ -302,7 +303,7 @@ static int cpucount;
 /* maps the cpu to the sched domain representing multi-core */
 cpumask_t cpu_coregroup_map(int cpu)
 {
-	struct cpuinfo_x86 *c = cpu_data + cpu;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	/*
 	 * For perf, we return last level cache shared map.
 	 * And for power savings, we return cpu_core_map
@@ -319,41 +320,41 @@ static cpumask_t cpu_sibling_setup_map;
 void __cpuinit set_cpu_sibling_map(int cpu)
 {
 	int i;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	cpu_set(cpu, cpu_sibling_setup_map);
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
-			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
+			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
+			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
 				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
 				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
 				cpu_set(i, per_cpu(cpu_core_map, cpu));
 				cpu_set(cpu, per_cpu(cpu_core_map, i));
-				cpu_set(i, c[cpu].llc_shared_map);
-				cpu_set(cpu, c[i].llc_shared_map);
+				cpu_set(i, c->llc_shared_map);
+				cpu_set(cpu, cpu_data(i).llc_shared_map);
 			}
 		}
 	} else {
 		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
 	}
 
-	cpu_set(cpu, c[cpu].llc_shared_map);
+	cpu_set(cpu, c->llc_shared_map);
 
 	if (current_cpu_data.x86_max_cores == 1) {
 		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
-		c[cpu].booted_cores = 1;
+		c->booted_cores = 1;
 		return;
 	}
 
 	for_each_cpu_mask(i, cpu_sibling_setup_map) {
 		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
 		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
-			cpu_set(i, c[cpu].llc_shared_map);
-			cpu_set(cpu, c[i].llc_shared_map);
+			cpu_set(i, c->llc_shared_map);
+			cpu_set(cpu, cpu_data(i).llc_shared_map);
 		}
-		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
+		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
 			cpu_set(i, per_cpu(cpu_core_map, cpu));
 			cpu_set(cpu, per_cpu(cpu_core_map, i));
 			/*
@@ -365,15 +366,15 @@ void __cpuinit set_cpu_sibling_map(int c
 				 * the booted_cores for this new cpu
 				 */
 				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
-					c[cpu].booted_cores++;
+					c->booted_cores++;
 				/*
 				 * increment the core count for all
 				 * the other cpus in this package
 				 */
 				if (i != cpu)
-					c[i].booted_cores++;
-			} else if (i != cpu && !c[cpu].booted_cores)
-				c[cpu].booted_cores = c[i].booted_cores;
+					cpu_data(i).booted_cores++;
+			} else if (i != cpu && !c->booted_cores)
+				c->booted_cores = cpu_data(i).booted_cores;
 		}
 	}
 }
@@ -852,7 +853,7 @@ static int __cpuinit do_boot_cpu(int api
 			/* number CPUs logically, starting from 1 (BSP is 0) */
 			Dprintk("OK.\n");
 			printk("CPU%d: ", cpu);
-			print_cpu_info(&cpu_data[cpu]);
+			print_cpu_info(&cpu_data(cpu));
 			Dprintk("CPU has booted.\n");
 		} else {
 			boot_error= 1;
@@ -969,7 +970,7 @@ static void __init smp_boot_cpus(unsigne
 	 */
 	smp_store_cpu_info(0); /* Final full version of the data */
 	printk("CPU%d: ", 0);
-	print_cpu_info(&cpu_data[0]);
+	print_cpu_info(&cpu_data(0));
 
 	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
@@ -1084,7 +1085,7 @@ static void __init smp_boot_cpus(unsigne
 	Dprintk("Before bogomips.\n");
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
 		if (cpu_isset(cpu, cpu_callout_map))
-			bogosum += cpu_data[cpu].loops_per_jiffy;
+			bogosum += cpu_data(cpu).loops_per_jiffy;
 	printk(KERN_INFO
 		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 		cpucount+1,
@@ -1154,7 +1155,7 @@ void __init native_smp_prepare_boot_cpu(
 void remove_siblinginfo(int cpu)
 {
 	int sibling;
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
 		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
@@ -1162,15 +1163,15 @@ void remove_siblinginfo(int cpu)
 		 * last thread sibling in this cpu core going down
 		 */
 		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
-			c[sibling].booted_cores--;
+			cpu_data(sibling).booted_cores--;
 	}
 			
 	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
 		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
 	cpus_clear(per_cpu(cpu_sibling_map, cpu));
 	cpus_clear(per_cpu(cpu_core_map, cpu));
-	c[cpu].phys_proc_id = 0;
-	c[cpu].cpu_core_id = 0;
+	c->phys_proc_id = 0;
+	c->cpu_core_id = 0;
 	cpu_clear(cpu, cpu_sibling_setup_map);
 }
 
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -119,8 +119,8 @@ int recalibrate_cpu_khz(void)
 	if (cpu_has_tsc) {
 		cpu_khz = calculate_cpu_khz();
 		tsc_khz = cpu_khz;
-		cpu_data[0].loops_per_jiffy =
-			cpufreq_scale(cpu_data[0].loops_per_jiffy,
+		cpu_data(0).loops_per_jiffy =
+			cpufreq_scale(cpu_data(0).loops_per_jiffy,
 					cpu_khz_old, cpu_khz);
 		return 0;
 	} else
@@ -153,7 +153,7 @@ time_cpufreq_notifier(struct notifier_bl
 			return 0;
 		}
 		ref_freq = freq->old;
-		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+		loops_per_jiffy_ref = cpu_data(freq->cpu).loops_per_jiffy;
 		cpu_khz_ref = cpu_khz;
 	}
 
@@ -161,7 +161,7 @@ time_cpufreq_notifier(struct notifier_bl
 	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
 	    (val == CPUFREQ_RESUMECHANGE)) {
 		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-			cpu_data[freq->cpu].loops_per_jiffy =
+			cpu_data(freq->cpu).loops_per_jiffy =
 				cpufreq_scale(loops_per_jiffy_ref,
 						ref_freq, freq->new);
 
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -82,7 +82,7 @@ inline void __const_udelay(unsigned long
 	__asm__("mull %0"
 		:"=d" (xloops), "=&a" (d0)
 		:"1" (xloops), "0"
-		(cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+		(cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4)));
 
 	__delay(++xloops);
 }
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -36,8 +36,8 @@ static unsigned long cpu_irq_affinity[NR
 
 /* per CPU data structure (for /proc/cpuinfo et al), visible externally
  * indexed physically */
-struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_data);
+DEFINE_PER_CPU(cpuinfo_x86, cpu_info) __cacheline_aligned;
+EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 /* physical ID of the CPU used to boot the system */
 unsigned char boot_cpu_id;
@@ -430,7 +430,7 @@ find_smp_config(void)
 void __init
 smp_store_cpu_info(int id)
 {
-	struct cpuinfo_x86 *c=&cpu_data[id];
+	struct cpuinfo_x86 *c = &cpu_data(id);
 
 	*c = boot_cpu_data;
 
@@ -634,7 +634,7 @@ do_boot_cpu(__u8 cpu)
 			cpu, smp_processor_id()));
 	
 		printk("CPU%d: ", cpu);
-		print_cpu_info(&cpu_data[cpu]);
+		print_cpu_info(&cpu_data(cpu));
 		wmb();
 		cpu_set(cpu, cpu_callout_map);
 		cpu_set(cpu, cpu_present_map);
@@ -683,7 +683,7 @@ smp_boot_cpus(void)
 	 */
 	smp_store_cpu_info(boot_cpu_id);
 	printk("CPU%d: ", boot_cpu_id);
-	print_cpu_info(&cpu_data[boot_cpu_id]);
+	print_cpu_info(&cpu_data(boot_cpu_id));
 
 	if(is_cpu_quad()) {
 		/* booting on a Quad CPU */
@@ -714,7 +714,7 @@ smp_boot_cpus(void)
 		unsigned long bogosum = 0;
 		for (i = 0; i < NR_CPUS; i++)
 			if (cpu_isset(i, cpu_online_map))
-				bogosum += cpu_data[i].loops_per_jiffy;
+				bogosum += cpu_data(i).loops_per_jiffy;
 		printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 			cpucount+1,
 			bogosum/(500000/HZ),
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -815,7 +815,7 @@ static __cpuinit int mce_create_device(u
 {
 	int err;
 	int i;
-	if (!mce_available(&cpu_data[cpu]))
+	if (!mce_available(&cpu_data(cpu)))
 		return -EIO;
 
 	memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -472,11 +472,11 @@ static __cpuinit int threshold_create_ba
 	sprintf(name, "threshold_bank%i", bank);
 
 #ifdef CONFIG_SMP
-	if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) {	/* symlink */
+	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
 		i = first_cpu(per_cpu(cpu_core_map, cpu));
 
 		/* first core not up yet */
-		if (cpu_data[i].cpu_core_id)
+		if (cpu_data(i).cpu_core_id)
 			goto out;
 
 		/* already linked */
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -554,7 +554,7 @@ static void __init amd_detect_cmp(struct
  		   but in the same order as the HT nodeids.
  		   If that doesn't result in a usable node fall back to the
  		   path for the previous case.  */
- 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
+		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
  		if (ht_nodeid >= 0 &&
  		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
  			node = apicid_to_node[ht_nodeid];
@@ -910,6 +910,7 @@ void __cpuinit early_identify_cpu(struct
 
 #ifdef CONFIG_SMP
 	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
+	c->cpu_index = 0;
 #endif
 	/* AMD-defined flags: level 0x80000001 */
 	xlvl = cpuid_eax(0x80000000);
@@ -1022,6 +1023,7 @@ void __cpuinit print_cpu_info(struct cpu
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	struct cpuinfo_x86 *c = v;
+	int cpu = 0;
 
 	/* 
 	 * These flag bits must match the definitions in <asm/cpufeature.h>.
@@ -1100,8 +1102,9 @@ static int show_cpuinfo(struct seq_file 
 
 
 #ifdef CONFIG_SMP
-	if (!cpu_online(c-cpu_data))
+	if (!cpu_online(c->cpu_index))
 		return 0;
+	cpu = c->cpu_index;
 #endif
 
 	seq_printf(m,"processor\t: %u\n"
@@ -1109,7 +1112,7 @@ static int show_cpuinfo(struct seq_file 
 		     "cpu family\t: %d\n"
 		     "model\t\t: %d\n"
 		     "model name\t: %s\n",
-		     (unsigned)(c-cpu_data),
+		     (unsigned)cpu,
 		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
 		     c->x86,
 		     (int)c->x86_model,
@@ -1121,7 +1124,7 @@ static int show_cpuinfo(struct seq_file 
 		seq_printf(m, "stepping\t: unknown\n");
 	
 	if (cpu_has(c,X86_FEATURE_TSC)) {
-		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
+		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
 		if (!freq)
 			freq = cpu_khz;
 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
@@ -1134,7 +1137,6 @@ static int show_cpuinfo(struct seq_file 
 	
 #ifdef CONFIG_SMP
 	if (smp_num_siblings * c->x86_max_cores > 1) {
-		int cpu = c - cpu_data;
 		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
 		seq_printf(m, "siblings\t: %d\n",
 			       cpus_weight(per_cpu(cpu_core_map, cpu)));
@@ -1192,12 +1194,16 @@ static int show_cpuinfo(struct seq_file 
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+	if (*pos == 0)	/* just in case, cpu 0 is not the first */
+		*pos = first_cpu(cpu_possible_map);
+	if ((*pos) < NR_CPUS && cpu_possible(*pos))
+		return &cpu_data(*pos);
+	return NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	++*pos;
+	*pos = next_cpu(*pos, cpu_possible_map);
 	return c_start(m, pos);
 }
 
--- a/arch/x86_64/kernel/tsc.c
+++ b/arch/x86_64/kernel/tsc.c
@@ -48,13 +48,13 @@ static int time_cpufreq_notifier(struct 
 	struct cpufreq_freqs *freq = data;
 	unsigned long *lpj, dummy;
 
-	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
 		return 0;
 
 	lpj = &dummy;
 	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
 #ifdef CONFIG_SMP
-		lpj = &cpu_data[freq->cpu].loops_per_jiffy;
+		lpj = &cpu_data(freq->cpu).loops_per_jiffy;
 #else
 		lpj = &boot_cpu_data.loops_per_jiffy;
 #endif
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -293,7 +293,7 @@ static void __cpuinit vsyscall_set_cpu(i
 #ifdef CONFIG_NUMA
 	node = cpu_to_node(cpu);
 #endif
-	if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP))
+	if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
 		write_rdtscp_aux((node << 12) | cpu);
 
 	/* Store cpu number in limit so that it can be loaded quickly
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -150,7 +150,7 @@ static struct coretemp_data *coretemp_up
 static int __devinit coretemp_probe(struct platform_device *pdev)
 {
 	struct coretemp_data *data;
-	struct cpuinfo_x86 *c = &(cpu_data)[pdev->id];
+	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
 	int err;
 	u32 eax, edx;
 
@@ -359,7 +359,7 @@ static int __init coretemp_init(void)
 	struct pdev_entry *p, *n;
 
 	/* quick check if we run Intel */
-	if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
+	if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
 		goto exit;
 
 	err = platform_driver_register(&coretemp_driver);
@@ -367,7 +367,7 @@ static int __init coretemp_init(void)
 		goto exit;
 
 	for_each_online_cpu(i) {
-		struct cpuinfo_x86 *c = &(cpu_data)[i];
+		struct cpuinfo_x86 *c = &cpu_data(i);
 
 		/* check if family 6, models e, f */
 		if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -200,7 +200,7 @@ static u8 find_vrm(u8 eff_family, u8 eff
 
 u8 vid_which_vrm(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	u32 eax;
 	u8 eff_family, eff_model, eff_stepping, vrm_ret;
 
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -136,7 +136,8 @@ static int gameport_measure_speed(struct
 	}
 
 	gameport_close(gameport);
-	return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+	return (cpu_data(raw_smp_processor_id()).loops_per_jiffy *
+		(unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
 
 #else
 
--- a/drivers/video/geode/video_gx.c
+++ b/drivers/video/geode/video_gx.c
@@ -127,7 +127,7 @@ static void gx_set_dclk_frequency(struct
 	int timeout = 1000;
 
 	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
-	if (cpu_data->x86_mask == 1) {
+	if (cpu_data(0).x86_mask == 1) {
 		pll_table = gx_pll_table_14MHz;
 		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
 	} else {
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -79,6 +79,7 @@ struct cpuinfo_x86 {
 	unsigned char booted_cores;	/* number of cores as seen by OS */
 	__u8 phys_proc_id; 		/* Physical processor id. */
 	__u8 cpu_core_id;  		/* Core id */
+	__u8 cpu_index;			/* index into per_cpu list */
 #endif
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
@@ -103,11 +104,12 @@ extern struct tss_struct doublefault_tss
 DECLARE_PER_CPU(struct tss_struct, init_tss);
 
 #ifdef CONFIG_SMP
-extern struct cpuinfo_x86 cpu_data[];
-#define current_cpu_data cpu_data[smp_processor_id()]
+DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
+#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
+#define current_cpu_data	cpu_data(smp_processor_id())
 #else
-#define cpu_data (&boot_cpu_data)
-#define current_cpu_data boot_cpu_data
+#define cpu_data(cpu)		boot_cpu_data
+#define current_cpu_data	boot_cpu_data
 #endif
 
 /*
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -28,8 +28,8 @@
 #define _ASM_I386_TOPOLOGY_H
 
 #ifdef CONFIG_X86_HT
-#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
-#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
+#define topology_physical_package_id(cpu)	(cpu_data(cpu).phys_proc_id)
+#define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
 #define topology_core_siblings(cpu)		(per_cpu(cpu_core_map, cpu))
 #define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
 #endif
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -56,8 +56,8 @@ extern int __node_distance(int, int);
 #endif
 
 #ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
-#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
+#define topology_physical_package_id(cpu)	(cpu_data(cpu).phys_proc_id)
+#define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
 #define topology_core_siblings(cpu)		(per_cpu(cpu_core_map, cpu))
 #define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
 #define mc_capable()			(boot_cpu_data.x86_max_cores > 1)
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -40,7 +40,8 @@ EXPORT_SYMBOL(__delay);
 
 inline void __const_udelay(unsigned long xloops)
 {
-	__delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1);
+	__delay(((xloops * HZ *
+		cpu_data(raw_smp_processor_id()).loops_per_jiffy) >> 32) + 1);
 }
 EXPORT_SYMBOL(__const_udelay);
 
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -85,12 +85,13 @@ static int show_cpuinfo(struct seq_file 
 		/* nothing */
 	};
 	struct cpuinfo_x86 *c = v;
-	int i, n = c - cpu_data;
+	int i, n = 0;
 	int fpu_exception;
 
 #ifdef CONFIG_SMP
 	if (!cpu_online(n))
 		return 0;
+	n = c->cpu_index;
 #endif
 	seq_printf(m, "processor\t: %d\n"
 		"vendor_id\t: %s\n"
@@ -175,11 +176,15 @@ static int show_cpuinfo(struct seq_file 
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+	if (*pos == 0)	/* just in case, cpu 0 is not the first */
+		*pos = first_cpu(cpu_possible_map);
+	if ((*pos) < NR_CPUS && cpu_possible(*pos))
+		return &cpu_data(*pos);
+	return NULL;
 }
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	++*pos;
+	*pos = next_cpu(*pos, cpu_possible_map);
 	return c_start(m, pos);
 }
 static void c_stop(struct seq_file *m, void *v)
--- a/arch/i386/kernel/sched-clock.c
+++ b/arch/i386/kernel/sched-clock.c
@@ -205,7 +205,7 @@ static int sc_freq_event(struct notifier
 {
 	struct cpufreq_freqs *freq = data;
 
-	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
 		return NOTIFY_DONE;
 	if (freq->old == freq->new)
 		return NOTIFY_DONE;

-- 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-24 21:08 ` [PATCH 1/1] " travis
@ 2007-09-24 22:01   ` roel
  2007-09-24 23:24     ` Dave Jones
  0 siblings, 1 reply; 9+ messages in thread
From: roel @ 2007-09-24 22:01 UTC (permalink / raw)
  To: travis
  Cc: Andrew Morton, Andi Kleen, Christoph Lameter, Jack Steiner,
	linux-mm, linux-kernel

travis@sgi.com wrote:
> v3: fix compile errors in arch-i386-allmodconfig build
> 
> v2: rebasing on 2.6.23-rc6-mm1
> 
> cpu_data is currently an array defined using NR_CPUS. This means that
> we overallocate since we will rarely really use maximum configured cpus.
> When NR_CPU count is raised to 4096 the size of cpu_data becomes
> 3,145,728 bytes.
> 
> These changes were adopted from the sparc64 (and ia64) code.  An
> additional field was added to cpuinfo_x86 to be a non-ambiguous
> cpu index.  This corresponds to the index into a cpumask_t as
> well as the per_cpu index.  It's used in various places like
> show_cpuinfo().
> 
> cpu_data is defined to be the boot_cpu_data structure for the
> NON-SMP case.
> 
> Signed-off-by: Mike Travis <travis@sgi.com>
> Acked-by: Christoph Lameter <clameter@sgi.com>
> ---
>  arch/i386/kernel/acpi/cstate.c                    |    4 -
>  arch/i386/kernel/acpi/processor.c                 |    2 
>  arch/i386/kernel/alternative.c                    |    6 +-
>  arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c       |    4 -
>  arch/i386/kernel/cpu/cpufreq/e_powersaver.c       |    2 
>  arch/i386/kernel/cpu/cpufreq/elanfreq.c           |    4 -
>  arch/i386/kernel/cpu/cpufreq/longhaul.c           |    4 -
>  arch/i386/kernel/cpu/cpufreq/longrun.c            |    4 -
>  arch/i386/kernel/cpu/cpufreq/p4-clockmod.c        |    4 -
>  arch/i386/kernel/cpu/cpufreq/powernow-k6.c        |    2 
>  arch/i386/kernel/cpu/cpufreq/powernow-k7.c        |    2 
>  arch/i386/kernel/cpu/cpufreq/sc520_freq.c         |    4 -
>  arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c |    6 +-
>  arch/i386/kernel/cpu/cpufreq/speedstep-lib.c      |    2 
>  arch/i386/kernel/cpu/intel_cacheinfo.c            |    8 +--
>  arch/i386/kernel/cpu/proc.c                       |   11 +++-
>  arch/i386/kernel/cpuid.c                          |    2 
>  arch/i386/kernel/microcode.c                      |    6 +-
>  arch/i386/kernel/msr.c                            |    2 
>  arch/i386/kernel/sched-clock.c                    |    2 
>  arch/i386/kernel/smp.c                            |    2 
>  arch/i386/kernel/smpboot.c                        |   51 +++++++++++-----------
>  arch/i386/kernel/tsc.c                            |    8 +--
>  arch/i386/lib/delay.c                             |    2 
>  arch/i386/mach-voyager/voyager_smp.c              |   12 ++---
>  arch/x86_64/kernel/mce.c                          |    2 
>  arch/x86_64/kernel/mce_amd.c                      |    4 -
>  arch/x86_64/kernel/setup.c                        |   20 +++++---
>  arch/x86_64/kernel/smpboot.c                      |   45 +++++++++----------
>  arch/x86_64/kernel/tsc.c                          |    4 -
>  arch/x86_64/kernel/vsyscall.c                     |    2 
>  arch/x86_64/lib/delay.c                           |    3 -
>  drivers/hwmon/coretemp.c                          |    6 +-
>  drivers/hwmon/hwmon-vid.c                         |    2 
>  drivers/input/gameport/gameport.c                 |    3 -
>  drivers/video/geode/video_gx.c                    |    2 
>  include/asm-i386/processor.h                      |   10 ++--
>  include/asm-i386/topology.h                       |    4 -
>  include/asm-x86_64/processor.h                    |   10 ++--
>  include/asm-x86_64/topology.h                     |    4 -
>  40 files changed, 148 insertions(+), 129 deletions(-)
> 
> --- a/arch/x86_64/kernel/smpboot.c
> +++ b/arch/x86_64/kernel/smpboot.c
> @@ -84,8 +84,8 @@ cpumask_t cpu_possible_map;
>  EXPORT_SYMBOL(cpu_possible_map);
>  
>  /* Per CPU bogomips and other parameters */
> -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
> -EXPORT_SYMBOL(cpu_data);
> +DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
> +EXPORT_PER_CPU_SYMBOL(cpu_info);
>  
>  /* Set when the idlers are all forked */
>  int smp_threads_ready;
> @@ -138,9 +138,10 @@ static unsigned long __cpuinit setup_tra
>  
>  static void __cpuinit smp_store_cpu_info(int id)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + id;
> +	struct cpuinfo_x86 *c = &cpu_data(id);
>  
>  	*c = boot_cpu_data;
> +	c->cpu_index = id;
>  	identify_cpu(c);
>  	print_cpu_info(c);
>  }
> @@ -238,7 +239,7 @@ void __cpuinit smp_callin(void)
>  /* maps the cpu to the sched domain representing multi-core */
>  cpumask_t cpu_coregroup_map(int cpu)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  	/*
>  	 * For perf, we return last level cache shared map.
>  	 * And for power savings, we return cpu_core_map
> @@ -255,41 +256,41 @@ static cpumask_t cpu_sibling_setup_map;
>  static inline void set_cpu_sibling_map(int cpu)
>  {
>  	int i;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	cpu_set(cpu, cpu_sibling_setup_map);
>  
>  	if (smp_num_siblings > 1) {
>  		for_each_cpu_mask(i, cpu_sibling_setup_map) {
> -			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
> -			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
> +			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
> +			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
>  				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
>  				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
>  				cpu_set(i, per_cpu(cpu_core_map, cpu));
>  				cpu_set(cpu, per_cpu(cpu_core_map, i));
> -				cpu_set(i, c[cpu].llc_shared_map);
> -				cpu_set(cpu, c[i].llc_shared_map);
> +				cpu_set(i, c->llc_shared_map);
> +				cpu_set(cpu, cpu_data(i).llc_shared_map);
>  			}
>  		}
>  	} else {
>  		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
>  	}
>  
> -	cpu_set(cpu, c[cpu].llc_shared_map);
> +	cpu_set(cpu, c->llc_shared_map);
>  
>  	if (current_cpu_data.x86_max_cores == 1) {
>  		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
> -		c[cpu].booted_cores = 1;
> +		c->booted_cores = 1;
>  		return;
>  	}
>  
>  	for_each_cpu_mask(i, cpu_sibling_setup_map) {
>  		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
>  		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
> -			cpu_set(i, c[cpu].llc_shared_map);
> -			cpu_set(cpu, c[i].llc_shared_map);
> +			cpu_set(i, c->llc_shared_map);
> +			cpu_set(cpu, cpu_data(i).llc_shared_map);
>  		}
> -		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
> +		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
>  			cpu_set(i, per_cpu(cpu_core_map, cpu));
>  			cpu_set(cpu, per_cpu(cpu_core_map, i));
>  			/*
> @@ -301,15 +302,15 @@ static inline void set_cpu_sibling_map(i
>  				 * the booted_cores for this new cpu
>  				 */
>  				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
> -					c[cpu].booted_cores++;
> +					c->booted_cores++;
>  				/*
>  				 * increment the core count for all
>  				 * the other cpus in this package
>  				 */
>  				if (i != cpu)
> -					c[i].booted_cores++;
> -			} else if (i != cpu && !c[cpu].booted_cores)
> -				c[cpu].booted_cores = c[i].booted_cores;
> +					cpu_data(i).booted_cores++;
> +			} else if (i != cpu && !c->booted_cores)
> +				c->booted_cores = cpu_data(i).booted_cores;
>  		}
>  	}
>  }
> @@ -1000,7 +1001,7 @@ void __init smp_cpus_done(unsigned int m
>  static void remove_siblinginfo(int cpu)
>  {
>  	int sibling;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
>  		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
> @@ -1008,15 +1009,15 @@ static void remove_siblinginfo(int cpu)
>  		 * last thread sibling in this cpu core going down
>  		 */
>  		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
> -			c[sibling].booted_cores--;
> +			cpu_data(sibling).booted_cores--;
>  	}
>  			
>  	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
>  		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
>  	cpus_clear(per_cpu(cpu_sibling_map, cpu));
>  	cpus_clear(per_cpu(cpu_core_map, cpu));
> -	c[cpu].phys_proc_id = 0;
> -	c[cpu].cpu_core_id = 0;
> +	c->phys_proc_id = 0;
> +	c->cpu_core_id = 0;
>  	cpu_clear(cpu, cpu_sibling_setup_map);
>  }
>  
> --- a/include/asm-x86_64/processor.h
> +++ b/include/asm-x86_64/processor.h
> @@ -75,6 +75,7 @@ struct cpuinfo_x86 {
>  	__u8	booted_cores;	/* number of cores as seen by OS */
>  	__u8	phys_proc_id;	/* Physical Processor id. */
>  	__u8	cpu_core_id;	/* Core id. */
> +	__u8	cpu_index;	/* index into per_cpu list */
>  #endif
>  } ____cacheline_aligned;
>  
> @@ -89,11 +90,12 @@ struct cpuinfo_x86 {
>  #define X86_VENDOR_UNKNOWN 0xff
>  
>  #ifdef CONFIG_SMP
> -extern struct cpuinfo_x86 cpu_data[];
> -#define current_cpu_data cpu_data[smp_processor_id()]
> +DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
> +#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
> +#define current_cpu_data	cpu_data(smp_processor_id())
>  #else
> -#define cpu_data (&boot_cpu_data)
> -#define current_cpu_data boot_cpu_data
> +#define cpu_data(cpu)		boot_cpu_data
> +#define current_cpu_data	boot_cpu_data
>  #endif
>  
>  extern char ignore_irq13;
> --- a/arch/i386/kernel/acpi/cstate.c
> +++ b/arch/i386/kernel/acpi/cstate.c
> @@ -29,7 +29,7 @@
>  void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
>  					unsigned int cpu)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	flags->bm_check = 0;
>  	if (num_online_cpus() == 1)
> @@ -72,7 +72,7 @@ int acpi_processor_ffh_cstate_probe(unsi
>  		struct acpi_processor_cx *cx, struct acpi_power_register *reg)
>  {
>  	struct cstate_entry *percpu_entry;
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	cpumask_t saved_mask;
>  	int retval;
> --- a/arch/i386/kernel/acpi/processor.c
> +++ b/arch/i386/kernel/acpi/processor.c
> @@ -63,7 +63,7 @@ static void init_intel_pdc(struct acpi_p
>  void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
>  {
>  	unsigned int cpu = pr->id;
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	pr->pdc = NULL;
>  	if (c->x86_vendor == X86_VENDOR_INTEL)
> --- a/arch/i386/kernel/alternative.c
> +++ b/arch/i386/kernel/alternative.c
> @@ -353,14 +353,14 @@ void alternatives_smp_switch(int smp)
>  	if (smp) {
>  		printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
>  		clear_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
> -		clear_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
> +		clear_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
>  		list_for_each_entry(mod, &smp_alt_modules, next)
>  			alternatives_smp_lock(mod->locks, mod->locks_end,
>  					      mod->text, mod->text_end);
>  	} else {
>  		printk(KERN_INFO "SMP alternatives: switching to UP code\n");
>  		set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
> -		set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
> +		set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
>  		list_for_each_entry(mod, &smp_alt_modules, next)
>  			alternatives_smp_unlock(mod->locks, mod->locks_end,
>  						mod->text, mod->text_end);
> @@ -428,7 +428,7 @@ void __init alternative_instructions(voi
>  		if (1 == num_possible_cpus()) {
>  			printk(KERN_INFO "SMP alternatives: switching to UP code\n");
>  			set_bit(X86_FEATURE_UP, boot_cpu_data.x86_capability);
> -			set_bit(X86_FEATURE_UP, cpu_data[0].x86_capability);
> +			set_bit(X86_FEATURE_UP, cpu_data(0).x86_capability);
>  			alternatives_smp_unlock(__smp_locks, __smp_locks_end,
>  						_text, _etext);
>  		}
> --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
> +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
> @@ -77,7 +77,7 @@ static unsigned int acpi_pstate_strict;
>  
>  static int check_est_cpu(unsigned int cpuid)
>  {
> -	struct cpuinfo_x86 *cpu = &cpu_data[cpuid];
> +	struct cpuinfo_x86 *cpu = &cpu_data(cpuid);
>  
>  	if (cpu->x86_vendor != X86_VENDOR_INTEL ||
>  	    !cpu_has(cpu, X86_FEATURE_EST))
> @@ -560,7 +560,7 @@ static int acpi_cpufreq_cpu_init(struct 
>  	unsigned int cpu = policy->cpu;
>  	struct acpi_cpufreq_data *data;
>  	unsigned int result = 0;
> -	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
> +	struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
>  	struct acpi_processor_performance *perf;
>  
>  	dprintk("acpi_cpufreq_cpu_init\n");
> --- a/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
> +++ b/arch/i386/kernel/cpu/cpufreq/e_powersaver.c
> @@ -305,7 +305,7 @@ static struct cpufreq_driver eps_driver 
>  
>  static int __init eps_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	/* This driver will work only on Centaur C7 processors with
>  	 * Enhanced SpeedStep/PowerSaver registers */
> --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c
> +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
> @@ -199,7 +199,7 @@ static int elanfreq_target (struct cpufr
>  
>  static int elanfreq_cpu_init(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	unsigned int i;
>  	int result;
>  
> @@ -280,7 +280,7 @@ static struct cpufreq_driver elanfreq_dr
>  
>  static int __init elanfreq_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	/* Test if we have the right hardware */
>  	if ((c->x86_vendor != X86_VENDOR_AMD) ||
> --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
> +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
> @@ -731,7 +731,7 @@ static int longhaul_setup_southbridge(vo
>  
>  static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	char *cpuname=NULL;
>  	int ret;
>  	u32 lo, hi;
> @@ -910,7 +910,7 @@ static struct cpufreq_driver longhaul_dr
>  
>  static int __init longhaul_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
>  		return -ENODEV;
> --- a/arch/i386/kernel/cpu/cpufreq/longrun.c
> +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c
> @@ -172,7 +172,7 @@ static unsigned int __init longrun_deter
>  	u32 save_lo, save_hi;
>  	u32 eax, ebx, ecx, edx;
>  	u32 try_hi;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	if (!low_freq || !high_freq)
>  		return -EINVAL;
> @@ -298,7 +298,7 @@ static struct cpufreq_driver longrun_dri
>   */
>  static int __init longrun_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
>  	    !cpu_has(c, X86_FEATURE_LONGRUN))
> --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
> +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
> @@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequ
>  
>  static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
> +	struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
>  	int cpuid = 0;
>  	unsigned int i;
>  
> @@ -279,7 +279,7 @@ static struct cpufreq_driver p4clockmod_
>  
>  static int __init cpufreq_p4_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	int ret;
>  
>  	/*
> --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
> +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
> @@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6
>   */
>  static int __init powernow_k6_init(void)
>  {
> -	struct cpuinfo_x86      *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  
>  	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
>  		((c->x86_model != 12) && (c->x86_model != 13)))

while we're at it, we could change this to

  	if (!(c->x86_vendor == X86_VENDOR_AMD && c->x86 == 5 &&
  		(c->x86_model == 12 || c->x86_model == 13)))

> --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
> +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
> @@ -114,7 +114,7 @@ static int check_fsb(unsigned int fsbspe
>  
>  static int check_powernow(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	unsigned int maxei, eax, ebx, ecx, edx;
>  
>  	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
> --- a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
> +++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
> @@ -102,7 +102,7 @@ static int sc520_freq_target (struct cpu
>  
>  static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	int result;
>  
>  	/* capability check */
> @@ -151,7 +151,7 @@ static struct cpufreq_driver sc520_freq_
>  
>  static int __init sc520_freq_init(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	int err;
>  
>  	/* Test if we have the right hardware */
> --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
> +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
> @@ -230,7 +230,7 @@ static struct cpu_model models[] =
>  
>  static int centrino_cpu_init_table(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
> +	struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
>  	struct cpu_model *model;
>  
>  	for(model = models; model->cpu_id != NULL; model++)
> @@ -340,7 +340,7 @@ static unsigned int get_cur_freq(unsigne
>  
>  static int centrino_cpu_init(struct cpufreq_policy *policy)
>  {
> -	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
> +	struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
>  	unsigned freq;
>  	unsigned l, h;
>  	int ret;
> @@ -612,7 +612,7 @@ static struct cpufreq_driver centrino_dr
>   */
>  static int __init centrino_init(void)
>  {
> -	struct cpuinfo_x86 *cpu = cpu_data;
> +	struct cpuinfo_x86 *cpu = &cpu_data(0);
>  
>  	if (!cpu_has(cpu, X86_FEATURE_EST))
>  		return -ENODEV;
> --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
> +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
> @@ -228,7 +228,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_processo
>  
>  unsigned int speedstep_detect_processor (void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	u32 ebx, msr_lo, msr_hi;
>  
>  	dprintk("x86: %x, model: %x\n", c->x86, c->x86_model);
> --- a/arch/i386/kernel/cpu/intel_cacheinfo.c
> +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
> @@ -295,7 +295,7 @@ unsigned int __cpuinit init_intel_cachei
>  	unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
>  	unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
>  #ifdef CONFIG_X86_HT
> -	unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
> +	unsigned int cpu = c->cpu_index;
>  #endif
>  
>  	if (c->cpuid_level > 3) {
> @@ -459,7 +459,7 @@ static void __cpuinit cache_shared_cpu_m
>  	struct _cpuid4_info	*this_leaf, *sibling_leaf;
>  	unsigned long num_threads_sharing;
>  	int index_msb, i;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	this_leaf = CPUID4_INFO_IDX(cpu, index);
>  	num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
> @@ -470,8 +470,8 @@ static void __cpuinit cache_shared_cpu_m
>  		index_msb = get_count_order(num_threads_sharing);
>  
>  		for_each_online_cpu(i) {
> -			if (c[i].apicid >> index_msb ==
> -			    c[cpu].apicid >> index_msb) {
> +			if (cpu_data(i).apicid >> index_msb ==
> +			    c->apicid >> index_msb) {
>  				cpu_set(i, this_leaf->shared_cpu_map);
>  				if (i != cpu && cpuid4_info[i])  {
>  					sibling_leaf = CPUID4_INFO_IDX(i, index);
> --- a/arch/i386/kernel/cpuid.c
> +++ b/arch/i386/kernel/cpuid.c
> @@ -116,7 +116,7 @@ static ssize_t cpuid_read(struct file *f
>  static int cpuid_open(struct inode *inode, struct file *file)
>  {
>  	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
> -	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	if (cpu >= NR_CPUS || !cpu_online(cpu))
>  		return -ENXIO;	/* No such CPU */
> --- a/arch/i386/kernel/microcode.c
> +++ b/arch/i386/kernel/microcode.c
> @@ -132,7 +132,7 @@ static struct ucode_cpu_info {
>  
>  static void collect_cpu_info(int cpu_num)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + cpu_num;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
>  	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
>  	unsigned int val[2];
>  
> @@ -522,7 +522,7 @@ static struct platform_device *microcode
>  static int cpu_request_microcode(int cpu)
>  {
>  	char name[30];
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  	const struct firmware *firmware;
>  	void *buf;
>  	unsigned long size;
> @@ -570,7 +570,7 @@ static int cpu_request_microcode(int cpu
>  
>  static int apply_microcode_check_cpu(int cpu)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
>  	cpumask_t old;
>  	unsigned int val[2];
> --- a/arch/i386/kernel/msr.c
> +++ b/arch/i386/kernel/msr.c
> @@ -114,7 +114,7 @@ static ssize_t msr_write(struct file *fi
>  static int msr_open(struct inode *inode, struct file *file)
>  {
>  	unsigned int cpu = iminor(file->f_path.dentry->d_inode);
> -	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	if (cpu >= NR_CPUS || !cpu_online(cpu))
>  		return -ENXIO;	/* No such CPU */
> --- a/arch/i386/kernel/smp.c
> +++ b/arch/i386/kernel/smp.c
> @@ -610,7 +610,7 @@ static void stop_this_cpu (void * dummy)
>  	 */
>  	cpu_clear(smp_processor_id(), cpu_online_map);
>  	disable_local_APIC();
> -	if (cpu_data[smp_processor_id()].hlt_works_ok)
> +	if (cpu_data(smp_processor_id()).hlt_works_ok)
>  		for(;;) halt();
>  	for (;;);
>  }
> --- a/arch/i386/kernel/smpboot.c
> +++ b/arch/i386/kernel/smpboot.c
> @@ -89,8 +89,8 @@ EXPORT_SYMBOL(cpu_possible_map);
>  static cpumask_t smp_commenced_mask;
>  
>  /* Per CPU bogomips and other parameters */
> -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
> -EXPORT_SYMBOL(cpu_data);
> +DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
> +EXPORT_PER_CPU_SYMBOL(cpu_info);
>  
>  /*
>   * The following static array is used during kernel startup
> @@ -158,9 +158,10 @@ void __init smp_alloc_memory(void)
>  
>  void __cpuinit smp_store_cpu_info(int id)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + id;
> +	struct cpuinfo_x86 *c = &cpu_data(id);
>  
>  	*c = boot_cpu_data;
> +	c->cpu_index = id;
>  	if (id!=0)
>  		identify_secondary_cpu(c);
>  	/*
> @@ -302,7 +303,7 @@ static int cpucount;
>  /* maps the cpu to the sched domain representing multi-core */
>  cpumask_t cpu_coregroup_map(int cpu)
>  {
> -	struct cpuinfo_x86 *c = cpu_data + cpu;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  	/*
>  	 * For perf, we return last level cache shared map.
>  	 * And for power savings, we return cpu_core_map
> @@ -319,41 +320,41 @@ static cpumask_t cpu_sibling_setup_map;
>  void __cpuinit set_cpu_sibling_map(int cpu)
>  {
>  	int i;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	cpu_set(cpu, cpu_sibling_setup_map);
>  
>  	if (smp_num_siblings > 1) {
>  		for_each_cpu_mask(i, cpu_sibling_setup_map) {
> -			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
> -			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
> +			if (c->phys_proc_id == cpu_data(i).phys_proc_id &&
> +			    c->cpu_core_id == cpu_data(i).cpu_core_id) {
>  				cpu_set(i, per_cpu(cpu_sibling_map, cpu));
>  				cpu_set(cpu, per_cpu(cpu_sibling_map, i));
>  				cpu_set(i, per_cpu(cpu_core_map, cpu));
>  				cpu_set(cpu, per_cpu(cpu_core_map, i));
> -				cpu_set(i, c[cpu].llc_shared_map);
> -				cpu_set(cpu, c[i].llc_shared_map);
> +				cpu_set(i, c->llc_shared_map);
> +				cpu_set(cpu, cpu_data(i).llc_shared_map);
>  			}
>  		}
>  	} else {
>  		cpu_set(cpu, per_cpu(cpu_sibling_map, cpu));
>  	}
>  
> -	cpu_set(cpu, c[cpu].llc_shared_map);
> +	cpu_set(cpu, c->llc_shared_map);
>  
>  	if (current_cpu_data.x86_max_cores == 1) {
>  		per_cpu(cpu_core_map, cpu) = per_cpu(cpu_sibling_map, cpu);
> -		c[cpu].booted_cores = 1;
> +		c->booted_cores = 1;
>  		return;
>  	}
>  
>  	for_each_cpu_mask(i, cpu_sibling_setup_map) {
>  		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
>  		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
> -			cpu_set(i, c[cpu].llc_shared_map);
> -			cpu_set(cpu, c[i].llc_shared_map);
> +			cpu_set(i, c->llc_shared_map);
> +			cpu_set(cpu, cpu_data(i).llc_shared_map);
>  		}
> -		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
> +		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
>  			cpu_set(i, per_cpu(cpu_core_map, cpu));
>  			cpu_set(cpu, per_cpu(cpu_core_map, i));
>  			/*
> @@ -365,15 +366,15 @@ void __cpuinit set_cpu_sibling_map(int c
>  				 * the booted_cores for this new cpu
>  				 */
>  				if (first_cpu(per_cpu(cpu_sibling_map, i)) == i)
> -					c[cpu].booted_cores++;
> +					c->booted_cores++;
>  				/*
>  				 * increment the core count for all
>  				 * the other cpus in this package
>  				 */
>  				if (i != cpu)
> -					c[i].booted_cores++;
> -			} else if (i != cpu && !c[cpu].booted_cores)
> -				c[cpu].booted_cores = c[i].booted_cores;
> +					cpu_data(i).booted_cores++;
> +			} else if (i != cpu && !c->booted_cores)
> +				c->booted_cores = cpu_data(i).booted_cores;
>  		}
>  	}
>  }
> @@ -852,7 +853,7 @@ static int __cpuinit do_boot_cpu(int api
>  			/* number CPUs logically, starting from 1 (BSP is 0) */
>  			Dprintk("OK.\n");
>  			printk("CPU%d: ", cpu);
> -			print_cpu_info(&cpu_data[cpu]);
> +			print_cpu_info(&cpu_data(cpu));
>  			Dprintk("CPU has booted.\n");
>  		} else {
>  			boot_error= 1;
> @@ -969,7 +970,7 @@ static void __init smp_boot_cpus(unsigne
>  	 */
>  	smp_store_cpu_info(0); /* Final full version of the data */
>  	printk("CPU%d: ", 0);
> -	print_cpu_info(&cpu_data[0]);
> +	print_cpu_info(&cpu_data(0));
>  
>  	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
>  	boot_cpu_logical_apicid = logical_smp_processor_id();
> @@ -1084,7 +1085,7 @@ static void __init smp_boot_cpus(unsigne
>  	Dprintk("Before bogomips.\n");
>  	for (cpu = 0; cpu < NR_CPUS; cpu++)
>  		if (cpu_isset(cpu, cpu_callout_map))
> -			bogosum += cpu_data[cpu].loops_per_jiffy;
> +			bogosum += cpu_data(cpu).loops_per_jiffy;
>  	printk(KERN_INFO
>  		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
>  		cpucount+1,
> @@ -1154,7 +1155,7 @@ void __init native_smp_prepare_boot_cpu(
>  void remove_siblinginfo(int cpu)
>  {
>  	int sibling;
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(cpu);
>  
>  	for_each_cpu_mask(sibling, per_cpu(cpu_core_map, cpu)) {
>  		cpu_clear(cpu, per_cpu(cpu_core_map, sibling));
> @@ -1162,15 +1163,15 @@ void remove_siblinginfo(int cpu)
>  		 * last thread sibling in this cpu core going down
>  		 */
>  		if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1)
> -			c[sibling].booted_cores--;
> +			cpu_data(sibling).booted_cores--;
>  	}
>  			
>  	for_each_cpu_mask(sibling, per_cpu(cpu_sibling_map, cpu))
>  		cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling));
>  	cpus_clear(per_cpu(cpu_sibling_map, cpu));
>  	cpus_clear(per_cpu(cpu_core_map, cpu));
> -	c[cpu].phys_proc_id = 0;
> -	c[cpu].cpu_core_id = 0;
> +	c->phys_proc_id = 0;
> +	c->cpu_core_id = 0;
>  	cpu_clear(cpu, cpu_sibling_setup_map);
>  }
>  
> --- a/arch/i386/kernel/tsc.c
> +++ b/arch/i386/kernel/tsc.c
> @@ -119,8 +119,8 @@ int recalibrate_cpu_khz(void)
>  	if (cpu_has_tsc) {
>  		cpu_khz = calculate_cpu_khz();
>  		tsc_khz = cpu_khz;
> -		cpu_data[0].loops_per_jiffy =
> -			cpufreq_scale(cpu_data[0].loops_per_jiffy,
> +		cpu_data(0).loops_per_jiffy =
> +			cpufreq_scale(cpu_data(0).loops_per_jiffy,
>  					cpu_khz_old, cpu_khz);
>  		return 0;
>  	} else
> @@ -153,7 +153,7 @@ time_cpufreq_notifier(struct notifier_bl
>  			return 0;
>  		}
>  		ref_freq = freq->old;
> -		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
> +		loops_per_jiffy_ref = cpu_data(freq->cpu).loops_per_jiffy;
>  		cpu_khz_ref = cpu_khz;
>  	}
>  
> @@ -161,7 +161,7 @@ time_cpufreq_notifier(struct notifier_bl
>  	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
>  	    (val == CPUFREQ_RESUMECHANGE)) {
>  		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
> -			cpu_data[freq->cpu].loops_per_jiffy =
> +			cpu_data(freq->cpu).loops_per_jiffy =
>  				cpufreq_scale(loops_per_jiffy_ref,
>  						ref_freq, freq->new);
>  
> --- a/arch/i386/lib/delay.c
> +++ b/arch/i386/lib/delay.c
> @@ -82,7 +82,7 @@ inline void __const_udelay(unsigned long
>  	__asm__("mull %0"
>  		:"=d" (xloops), "=&a" (d0)
>  		:"1" (xloops), "0"
> -		(cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
> +		(cpu_data(raw_smp_processor_id()).loops_per_jiffy * (HZ/4)));
>  
>  	__delay(++xloops);
>  }
> --- a/arch/i386/mach-voyager/voyager_smp.c
> +++ b/arch/i386/mach-voyager/voyager_smp.c
> @@ -36,8 +36,8 @@ static unsigned long cpu_irq_affinity[NR
>  
>  /* per CPU data structure (for /proc/cpuinfo et al), visible externally
>   * indexed physically */
> -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
> -EXPORT_SYMBOL(cpu_data);
> +DEFINE_PER_CPU(cpuinfo_x86, cpu_info) __cacheline_aligned;
> +EXPORT_PER_CPU_SYMBOL(cpu_info);
>  
>  /* physical ID of the CPU used to boot the system */
>  unsigned char boot_cpu_id;
> @@ -430,7 +430,7 @@ find_smp_config(void)
>  void __init
>  smp_store_cpu_info(int id)
>  {
> -	struct cpuinfo_x86 *c=&cpu_data[id];
> +	struct cpuinfo_x86 *c = &cpu_data(id);
>  
>  	*c = boot_cpu_data;
>  
> @@ -634,7 +634,7 @@ do_boot_cpu(__u8 cpu)
>  			cpu, smp_processor_id()));
>  	
>  		printk("CPU%d: ", cpu);
> -		print_cpu_info(&cpu_data[cpu]);
> +		print_cpu_info(&cpu_data(cpu));
>  		wmb();
>  		cpu_set(cpu, cpu_callout_map);
>  		cpu_set(cpu, cpu_present_map);
> @@ -683,7 +683,7 @@ smp_boot_cpus(void)
>  	 */
>  	smp_store_cpu_info(boot_cpu_id);
>  	printk("CPU%d: ", boot_cpu_id);
> -	print_cpu_info(&cpu_data[boot_cpu_id]);
> +	print_cpu_info(&cpu_data(boot_cpu_id));
>  
>  	if(is_cpu_quad()) {
>  		/* booting on a Quad CPU */
> @@ -714,7 +714,7 @@ smp_boot_cpus(void)
>  		unsigned long bogosum = 0;
>  		for (i = 0; i < NR_CPUS; i++)
>  			if (cpu_isset(i, cpu_online_map))
> -				bogosum += cpu_data[i].loops_per_jiffy;
> +				bogosum += cpu_data(i).loops_per_jiffy;
>  		printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
>  			cpucount+1,
>  			bogosum/(500000/HZ),
> --- a/arch/x86_64/kernel/mce.c
> +++ b/arch/x86_64/kernel/mce.c
> @@ -815,7 +815,7 @@ static __cpuinit int mce_create_device(u
>  {
>  	int err;
>  	int i;
> -	if (!mce_available(&cpu_data[cpu]))
> +	if (!mce_available(&cpu_data(cpu)))
>  		return -EIO;
>  
>  	memset(&per_cpu(device_mce, cpu).kobj, 0, sizeof(struct kobject));
> --- a/arch/x86_64/kernel/mce_amd.c
> +++ b/arch/x86_64/kernel/mce_amd.c
> @@ -472,11 +472,11 @@ static __cpuinit int threshold_create_ba
>  	sprintf(name, "threshold_bank%i", bank);
>  
>  #ifdef CONFIG_SMP
> -	if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) {	/* symlink */
> +	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
>  		i = first_cpu(per_cpu(cpu_core_map, cpu));
>  
>  		/* first core not up yet */
> -		if (cpu_data[i].cpu_core_id)
> +		if (cpu_data(i).cpu_core_id)
>  			goto out;
>  
>  		/* already linked */
> --- a/arch/x86_64/kernel/setup.c
> +++ b/arch/x86_64/kernel/setup.c
> @@ -554,7 +554,7 @@ static void __init amd_detect_cmp(struct
>   		   but in the same order as the HT nodeids.
>   		   If that doesn't result in a usable node fall back to the
>   		   path for the previous case.  */
> - 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
> +		int ht_nodeid = apicid - (cpu_data(0).phys_proc_id << bits);
>   		if (ht_nodeid >= 0 &&
>   		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
>   			node = apicid_to_node[ht_nodeid];
> @@ -910,6 +910,7 @@ void __cpuinit early_identify_cpu(struct
>  
>  #ifdef CONFIG_SMP
>  	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
> +	c->cpu_index = 0;
>  #endif
>  	/* AMD-defined flags: level 0x80000001 */
>  	xlvl = cpuid_eax(0x80000000);
> @@ -1022,6 +1023,7 @@ void __cpuinit print_cpu_info(struct cpu
>  static int show_cpuinfo(struct seq_file *m, void *v)
>  {
>  	struct cpuinfo_x86 *c = v;
> +	int cpu = 0;
>  
>  	/* 
>  	 * These flag bits must match the definitions in <asm/cpufeature.h>.
> @@ -1100,8 +1102,9 @@ static int show_cpuinfo(struct seq_file 
>  
>  
>  #ifdef CONFIG_SMP
> -	if (!cpu_online(c-cpu_data))
> +	if (!cpu_online(c->cpu_index))
>  		return 0;
> +	cpu = c->cpu_index;
>  #endif
>  
>  	seq_printf(m,"processor\t: %u\n"
> @@ -1109,7 +1112,7 @@ static int show_cpuinfo(struct seq_file 
>  		     "cpu family\t: %d\n"
>  		     "model\t\t: %d\n"
>  		     "model name\t: %s\n",
> -		     (unsigned)(c-cpu_data),
> +		     (unsigned)cpu,
>  		     c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
>  		     c->x86,
>  		     (int)c->x86_model,
> @@ -1121,7 +1124,7 @@ static int show_cpuinfo(struct seq_file 
>  		seq_printf(m, "stepping\t: unknown\n");
>  	
>  	if (cpu_has(c,X86_FEATURE_TSC)) {
> -		unsigned int freq = cpufreq_quick_get((unsigned)(c-cpu_data));
> +		unsigned int freq = cpufreq_quick_get((unsigned)cpu);
>  		if (!freq)
>  			freq = cpu_khz;
>  		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
> @@ -1134,7 +1137,6 @@ static int show_cpuinfo(struct seq_file 
>  	
>  #ifdef CONFIG_SMP
>  	if (smp_num_siblings * c->x86_max_cores > 1) {
> -		int cpu = c - cpu_data;
>  		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
>  		seq_printf(m, "siblings\t: %d\n",
>  			       cpus_weight(per_cpu(cpu_core_map, cpu)));
> @@ -1192,12 +1194,16 @@ static int show_cpuinfo(struct seq_file 
>  
>  static void *c_start(struct seq_file *m, loff_t *pos)
>  {
> -	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
> +	if (*pos == 0)	/* just in case, cpu 0 is not the first */
> +		*pos = first_cpu(cpu_possible_map);
> +	if ((*pos) < NR_CPUS && cpu_possible(*pos))
> +		return &cpu_data(*pos);
> +	return NULL;
>  }
>  
>  static void *c_next(struct seq_file *m, void *v, loff_t *pos)
>  {
> -	++*pos;
> +	*pos = next_cpu(*pos, cpu_possible_map);
>  	return c_start(m, pos);
>  }
>  
> --- a/arch/x86_64/kernel/tsc.c
> +++ b/arch/x86_64/kernel/tsc.c
> @@ -48,13 +48,13 @@ static int time_cpufreq_notifier(struct 
>  	struct cpufreq_freqs *freq = data;
>  	unsigned long *lpj, dummy;
>  
> -	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
> +	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
>  		return 0;
>  
>  	lpj = &dummy;
>  	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
>  #ifdef CONFIG_SMP
> -		lpj = &cpu_data[freq->cpu].loops_per_jiffy;
> +		lpj = &cpu_data(freq->cpu).loops_per_jiffy;
>  #else
>  		lpj = &boot_cpu_data.loops_per_jiffy;
>  #endif
> --- a/arch/x86_64/kernel/vsyscall.c
> +++ b/arch/x86_64/kernel/vsyscall.c
> @@ -293,7 +293,7 @@ static void __cpuinit vsyscall_set_cpu(i
>  #ifdef CONFIG_NUMA
>  	node = cpu_to_node(cpu);
>  #endif
> -	if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP))
> +	if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP))
>  		write_rdtscp_aux((node << 12) | cpu);
>  
>  	/* Store cpu number in limit so that it can be loaded quickly
> --- a/drivers/hwmon/coretemp.c
> +++ b/drivers/hwmon/coretemp.c
> @@ -150,7 +150,7 @@ static struct coretemp_data *coretemp_up
>  static int __devinit coretemp_probe(struct platform_device *pdev)
>  {
>  	struct coretemp_data *data;
> -	struct cpuinfo_x86 *c = &(cpu_data)[pdev->id];
> +	struct cpuinfo_x86 *c = &cpu_data(pdev->id);
>  	int err;
>  	u32 eax, edx;
>  
> @@ -359,7 +359,7 @@ static int __init coretemp_init(void)
>  	struct pdev_entry *p, *n;
>  
>  	/* quick check if we run Intel */
> -	if (cpu_data[0].x86_vendor != X86_VENDOR_INTEL)
> +	if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
>  		goto exit;
>  
>  	err = platform_driver_register(&coretemp_driver);
> @@ -367,7 +367,7 @@ static int __init coretemp_init(void)
>  		goto exit;
>  
>  	for_each_online_cpu(i) {
> -		struct cpuinfo_x86 *c = &(cpu_data)[i];
> +		struct cpuinfo_x86 *c = &cpu_data(i);
>  
>  		/* check if family 6, models e, f */
>  		if ((c->cpuid_level < 0) || (c->x86 != 0x6) ||
> --- a/drivers/hwmon/hwmon-vid.c
> +++ b/drivers/hwmon/hwmon-vid.c
> @@ -200,7 +200,7 @@ static u8 find_vrm(u8 eff_family, u8 eff
>  
>  u8 vid_which_vrm(void)
>  {
> -	struct cpuinfo_x86 *c = cpu_data;
> +	struct cpuinfo_x86 *c = &cpu_data(0);
>  	u32 eax;
>  	u8 eff_family, eff_model, eff_stepping, vrm_ret;
>  
> --- a/drivers/input/gameport/gameport.c
> +++ b/drivers/input/gameport/gameport.c
> @@ -136,7 +136,8 @@ static int gameport_measure_speed(struct
>  	}
>  
>  	gameport_close(gameport);
> -	return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
> +	return (cpu_data(raw_smp_processor_id()).loops_per_jiffy *
> +		(unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);

You could also use the max macro here:
	max(tx, 1) 
instead of (tx < 1 ? 1 : tx)

>  #else
>  
> --- a/drivers/video/geode/video_gx.c
> +++ b/drivers/video/geode/video_gx.c
> @@ -127,7 +127,7 @@ static void gx_set_dclk_frequency(struct
>  	int timeout = 1000;
>  
>  	/* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */
> -	if (cpu_data->x86_mask == 1) {
> +	if (cpu_data(0).x86_mask == 1) {
>  		pll_table = gx_pll_table_14MHz;
>  		pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
>  	} else {
> --- a/include/asm-i386/processor.h
> +++ b/include/asm-i386/processor.h
> @@ -79,6 +79,7 @@ struct cpuinfo_x86 {
>  	unsigned char booted_cores;	/* number of cores as seen by OS */
>  	__u8 phys_proc_id; 		/* Physical processor id. */
>  	__u8 cpu_core_id;  		/* Core id */
> +	__u8 cpu_index;			/* index into per_cpu list */
>  #endif
>  } __attribute__((__aligned__(SMP_CACHE_BYTES)));
>  
> @@ -103,11 +104,12 @@ extern struct tss_struct doublefault_tss
>  DECLARE_PER_CPU(struct tss_struct, init_tss);
>  
>  #ifdef CONFIG_SMP
> -extern struct cpuinfo_x86 cpu_data[];
> -#define current_cpu_data cpu_data[smp_processor_id()]
> +DECLARE_PER_CPU(struct cpuinfo_x86, cpu_info);
> +#define cpu_data(cpu)		per_cpu(cpu_info, cpu)
> +#define current_cpu_data	cpu_data(smp_processor_id())
>  #else
> -#define cpu_data (&boot_cpu_data)
> -#define current_cpu_data boot_cpu_data
> +#define cpu_data(cpu)		boot_cpu_data
> +#define current_cpu_data	boot_cpu_data
>  #endif
>  
>  /*
> --- a/include/asm-i386/topology.h
> +++ b/include/asm-i386/topology.h
> @@ -28,8 +28,8 @@
>  #define _ASM_I386_TOPOLOGY_H
>  
>  #ifdef CONFIG_X86_HT
> -#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
> -#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
> +#define topology_physical_package_id(cpu)	(cpu_data(cpu).phys_proc_id)
> +#define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
>  #define topology_core_siblings(cpu)		(per_cpu(cpu_core_map, cpu))
>  #define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
>  #endif
> --- a/include/asm-x86_64/topology.h
> +++ b/include/asm-x86_64/topology.h
> @@ -56,8 +56,8 @@ extern int __node_distance(int, int);
>  #endif
>  
>  #ifdef CONFIG_SMP
> -#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
> -#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
> +#define topology_physical_package_id(cpu)	(cpu_data(cpu).phys_proc_id)
> +#define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
>  #define topology_core_siblings(cpu)		(per_cpu(cpu_core_map, cpu))
>  #define topology_thread_siblings(cpu)		(per_cpu(cpu_sibling_map, cpu))
>  #define mc_capable()			(boot_cpu_data.x86_max_cores > 1)
> --- a/arch/x86_64/lib/delay.c
> +++ b/arch/x86_64/lib/delay.c
> @@ -40,7 +40,8 @@ EXPORT_SYMBOL(__delay);
>  
>  inline void __const_udelay(unsigned long xloops)
>  {
> -	__delay(((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) + 1);
> +	__delay(((xloops * HZ *
> +		cpu_data(raw_smp_processor_id()).loops_per_jiffy) >> 32) + 1);
>  }
>  EXPORT_SYMBOL(__const_udelay);
>  
> --- a/arch/i386/kernel/cpu/proc.c
> +++ b/arch/i386/kernel/cpu/proc.c
> @@ -85,12 +85,13 @@ static int show_cpuinfo(struct seq_file 
>  		/* nothing */
>  	};
>  	struct cpuinfo_x86 *c = v;
> -	int i, n = c - cpu_data;
> +	int i, n = 0;
>  	int fpu_exception;
>  
>  #ifdef CONFIG_SMP
>  	if (!cpu_online(n))
>  		return 0;
> +	n = c->cpu_index;
>  #endif
>  	seq_printf(m, "processor\t: %d\n"
>  		"vendor_id\t: %s\n"
> @@ -175,11 +176,15 @@ static int show_cpuinfo(struct seq_file 
>  
>  static void *c_start(struct seq_file *m, loff_t *pos)
>  {
> -	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
> +	if (*pos == 0)	/* just in case, cpu 0 is not the first */
> +		*pos = first_cpu(cpu_possible_map);
> +	if ((*pos) < NR_CPUS && cpu_possible(*pos))
> +		return &cpu_data(*pos);
> +	return NULL;
>  }
>  static void *c_next(struct seq_file *m, void *v, loff_t *pos)
>  {
> -	++*pos;
> +	*pos = next_cpu(*pos, cpu_possible_map);
>  	return c_start(m, pos);
>  }
>  static void c_stop(struct seq_file *m, void *v)
> --- a/arch/i386/kernel/sched-clock.c
> +++ b/arch/i386/kernel/sched-clock.c
> @@ -205,7 +205,7 @@ static int sc_freq_event(struct notifier
>  {
>  	struct cpufreq_freqs *freq = data;
>  
> -	if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
> +	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
>  		return NOTIFY_DONE;
>  	if (freq->old == freq->new)
>  		return NOTIFY_DONE;
> 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-24 22:01   ` roel
@ 2007-09-24 23:24     ` Dave Jones
  2007-09-25  0:20       ` roel
  0 siblings, 1 reply; 9+ messages in thread
From: Dave Jones @ 2007-09-24 23:24 UTC (permalink / raw)
  To: roel
  Cc: travis, Andrew Morton, Andi Kleen, Christoph Lameter,
	Jack Steiner, linux-mm, linux-kernel

<excessive quoting trimmed, please don't quote 40K of text
 to add a single line reply>

On Tue, Sep 25, 2007 at 12:01:56AM +0200, roel wrote:

 > > --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
 > > +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
 > > @@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6
 > >   */
 > >  static int __init powernow_k6_init(void)
 > >  {
 > > -	struct cpuinfo_x86      *c = cpu_data;
 > > +	struct cpuinfo_x86 *c = &cpu_data(0);
 > >  
 > >  	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
 > >  		((c->x86_model != 12) && (c->x86_model != 13)))
 > 
 > while we're at it, we could change this to
 > 
 >   	if (!(c->x86_vendor == X86_VENDOR_AMD && c->x86 == 5 &&
 >   		(c->x86_model == 12 || c->x86_model == 13)))

For what purpose?  There's nothing wrong with the code as it stands,
and inverting the tests means we'd have to move a bunch of
code inside the if arm instead of just returning -ENODEV.

	Dave

-- 
http://www.codemonkey.org.uk

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-24 23:24     ` Dave Jones
@ 2007-09-25  0:20       ` roel
  2007-09-25  0:31         ` Dave Jones
  0 siblings, 1 reply; 9+ messages in thread
From: roel @ 2007-09-25  0:20 UTC (permalink / raw)
  To: Dave Jones, roel, travis, Andrew Morton, Andi Kleen,
	Christoph Lameter, Jack Steiner, linux-mm, linux-kernel

Dave Jones wrote:
> <excessive quoting trimmed, please don't quote 40K of text
>  to add a single line reply>

Ok, sorry, I don't know these rules

> On Tue, Sep 25, 2007 at 12:01:56AM +0200, roel wrote:
> 
>  > > --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
>  > > +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
>  > > @@ -215,7 +215,7 @@ static struct cpufreq_driver powernow_k6
>  > >   */
>  > >  static int __init powernow_k6_init(void)
>  > >  {
>  > > -	struct cpuinfo_x86      *c = cpu_data;
>  > > +	struct cpuinfo_x86 *c = &cpu_data(0);
>  > >  
>  > >  	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
>  > >  		((c->x86_model != 12) && (c->x86_model != 13)))
>  > 
>  > while we're at it, we could change this to
>  > 
>  >   	if (!(c->x86_vendor == X86_VENDOR_AMD && c->x86 == 5 &&
>  >   		(c->x86_model == 12 || c->x86_model == 13)))
> 
> For what purpose?  There's nothing wrong with the code as it stands,
> and inverting the tests means we'd have to move a bunch of
> code inside the if arm instead of just returning -ENODEV.

It's not inverting the test, so you don't need to move code. It evaluates 
the same, only the combined negation is moved to the front. I suggested it
to increase clarity, it results in the same assembly language.

Roel

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-25  0:20       ` roel
@ 2007-09-25  0:31         ` Dave Jones
  0 siblings, 0 replies; 9+ messages in thread
From: Dave Jones @ 2007-09-25  0:31 UTC (permalink / raw)
  To: roel
  Cc: travis, Andrew Morton, Andi Kleen, Christoph Lameter,
	Jack Steiner, linux-mm, linux-kernel

On Tue, Sep 25, 2007 at 02:20:01AM +0200, roel wrote:
 
 > >  > >  	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
 > >  > >  		((c->x86_model != 12) && (c->x86_model != 13)))
 > >  > 
 > >  > while we're at it, we could change this to
 > >  > 
 > >  >   	if (!(c->x86_vendor == X86_VENDOR_AMD && c->x86 == 5 &&
 > >  >   		(c->x86_model == 12 || c->x86_model == 13)))
 > > 
 > > For what purpose?  There's nothing wrong with the code as it stands,
 > > and inverting the tests means we'd have to move a bunch of
 > > code inside the if arm instead of just returning -ENODEV.
 > 
 > It's not inverting the test, so you don't need to move code. It evaluates 
 > the same, only the combined negation is moved to the front. I suggested it
 > to increase clarity, it results in the same assembly language.

I don't see it as being particularly more readable after this change.
In fact, the reverse, as my previous comment implied, I missed the
initial !
Given this code works fine, and there's no discernable gain from
changing it, I'm not particularly enthusiastic about this modification.

	Dave

-- 
http://www.codemonkey.org.uk

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-09-24 21:08 [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3 travis
  2007-09-24 21:08 ` [PATCH 1/1] " travis
@ 2007-10-16  8:18 ` Andrew Morton
  2007-08-04  1:15   ` Mike Travis
  2007-10-16 15:02   ` Christoph Lameter
  1 sibling, 2 replies; 9+ messages in thread
From: Andrew Morton @ 2007-10-16  8:18 UTC (permalink / raw)
  To: travis; +Cc: Andi Kleen, Christoph Lameter, Jack Steiner, linux-mm,
	linux-kernel

On Mon, 24 Sep 2007 14:08:53 -0700 travis@sgi.com wrote:

> 
> v3: fix compile errors in arch-i386-allmodconfig build
> 
> v2: rebasing on 2.6.23-rc6-mm1
> 
> Analyzing various data structures when NR_CPU count is raised
> to 4096 shows the following arrays over 128k.  If the maximum
> number of cpus are not installed (about 99.99% of the time),
> then a large percentage of this memory is wasted.
> --
> 	151289856  CALNDATA  irq_desc
> 	135530496  RMDATATA  irq_cfg
> 	  3145728  CALNDATA  cpu_data
> 	  2101248  BSS       irq_lists
> 	  2097152  RMDATATA  cpu_sibling_map
> 	  2097152  RMDATATA  cpu_core_map
> 	  1575936  BSS       irq_2_pin
> 	  1050624  BSS       irq_timer_state
> 	   614400  INITDATA  early_node_map
> 	   525376  PERCPU    per_cpu__kstat
> 	   524608  DATA      unix_proto
> 	   524608  DATA      udpv6_prot
> 	   524608  DATA      udplitev6_prot
> 	   524608  DATA      udplite_prot
> 	   524608  DATA      udp_prot
> 	   524608  DATA      tcpv6_prot
> 	   524608  DATA      tcp_prot
> 	   524608  DATA      rawv6_prot
> 	   524608  DATA      raw_prot
> 	   524608  DATA      packet_proto
> 	   524608  DATA      netlink_proto
> 	   524288  BSS       cpu_devices
> 	   524288  BSS       boot_pageset
> 	   524288  CALNDATA  boot_cpu_pda
> 	   262144  RMDATATA  node_to_cpumask
> 	   262144  BSS       __log_buf
> 	   131072  BSS       entries
> 
> cpu_sibling_map and cpu_core_map have been taken care of in
> a prior patch.  This patch deals with the cpu_data array of
> cpuinfo_x86 structs.  The model that was used in sparc64
> architecture was adopted for x86.
> 

This has mysteriously started to oops on me, only on x86_64.

http://userweb.kernel.org/~akpm/config-x.txt
http://userweb.kernel.org/~akpm/dsc00001.jpg

which is a bit strange since this patch doesn't touch sched.c.  Maybe
there's something somewhere else in the -mm lineup which when combined with
this prevents it from oopsing, dunno.  I'll hold it back for now and will
see what happens.


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3
  2007-10-16  8:18 ` [PATCH 0/1] " Andrew Morton
  2007-08-04  1:15   ` Mike Travis
@ 2007-10-16 15:02   ` Christoph Lameter
  1 sibling, 0 replies; 9+ messages in thread
From: Christoph Lameter @ 2007-10-16 15:02 UTC (permalink / raw)
  To: pj
  Cc: travis, Andrew Morton, Andi Kleen, Jack Steiner, linux-mm,
	Siddha, Suresh B, linux-kernel

On Tue, 16 Oct 2007, Andrew Morton wrote:

> On Mon, 24 Sep 2007 14:08:53 -0700 travis@sgi.com wrote:

> > cpu_sibling_map and cpu_core_map have been taken care of in
> > a prior patch.  This patch deals with the cpu_data array of
> > cpuinfo_x86 structs.  The model that was used in sparc64
> > architecture was adopted for x86.
> 
> This has mysteriously started to oops on me, only on x86_64.
> 
> http://userweb.kernel.org/~akpm/config-x.txt
> http://userweb.kernel.org/~akpm/dsc00001.jpg
> 
> which is a bit strange since this patch doesn't touch sched.c.  Maybe
> there's something somewhere else in the -mm lineup which when combined with
> this prevents it from oopsing, dunno.  I'll hold it back for now and will
> see what happens.

The config that you are using has

	CONFIG_SCHED_MC

and 

	CONFIG_SCHED_MT

set.

So we use cpu_corecroup_map() from arch/x86_64/kernel/smpboot.c in
cpu_to_phys_group that has these nice convoluted ifdefs:

static int cpu_to_phys_group(int cpu, const cpumask_t *cpu_map,
                             struct sched_group **sg)
{
        int group;
#ifdef CONFIG_SCHED_MC
        cpumask_t mask = cpu_coregroup_map(cpu);
        cpus_and(mask, mask, *cpu_map);
        group = first_cpu(mask);
#elif defined(CONFIG_SCHED_SMT)
        cpumask_t mask = per_cpu(cpu_sibling_map, cpu);
        cpus_and(mask, mask, *cpu_map);
        group = first_cpu(mask);
#else
        group = cpu;
#endif
        if (sg)
                *sg = &per_cpu(sched_group_phys, group);
        return group;
}

and I guess that some sched domain patches resulted in an empty
nodemask so that we end up with an invalid group number for the sched 
group?


/* maps the cpu to the sched domain representing multi-core */
cpumask_t cpu_coregroup_map(int cpu)
{
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        /*
         * For perf, we return last level cache shared map.
         * And for power savings, we return cpu_core_map
         */
        if (sched_mc_power_savings || sched_smt_power_savings)
                return per_cpu(cpu_core_map, cpu);
        else
                return c->llc_shared_map;
}

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-10-16 15:02 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-24 21:08 [PATCH 0/1] x86: Convert cpuinfo_x86 array to a per_cpu array v3 travis
2007-09-24 21:08 ` [PATCH 1/1] " travis
2007-09-24 22:01   ` roel
2007-09-24 23:24     ` Dave Jones
2007-09-25  0:20       ` roel
2007-09-25  0:31         ` Dave Jones
2007-10-16  8:18 ` [PATCH 0/1] " Andrew Morton
2007-08-04  1:15   ` Mike Travis
2007-10-16 15:02   ` Christoph Lameter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).