aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-07-29 00:15:42 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-29 00:46:01 -0400
commitf8d311939f9d2b2a5e935df8dceb98b7cbe08d43 (patch)
tree02da12ff661ee3da44e29e4ca89df28dea8a4593
parent37a47e65fa58d413a31f27ee88f6cb98583b6157 (diff)
[PATCH] x86_64: Support more than 8 cores on AMD systems
Use physical mode instead of logical mode to address more CPUs. This is also used in the CPU hotplug case to avoid a race. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/x86_64/kernel/genapic.c33
-rw-r--r--arch/x86_64/kernel/genapic_flat.c62
2 files changed, 85 insertions, 10 deletions
diff --git a/arch/x86_64/kernel/genapic.c b/arch/x86_64/kernel/genapic.c
index 69b9c25a8fc4..30c843a5efdd 100644
--- a/arch/x86_64/kernel/genapic.c
+++ b/arch/x86_64/kernel/genapic.c
@@ -31,6 +31,7 @@ u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
31 31
32extern struct genapic apic_cluster; 32extern struct genapic apic_cluster;
33extern struct genapic apic_flat; 33extern struct genapic apic_flat;
34extern struct genapic apic_physflat;
34 35
35struct genapic *genapic = &apic_flat; 36struct genapic *genapic = &apic_flat;
36 37
@@ -44,12 +45,7 @@ void __init clustered_apic_check(void)
44 u8 clusters, max_cluster; 45 u8 clusters, max_cluster;
45 u8 id; 46 u8 id;
46 u8 cluster_cnt[NUM_APIC_CLUSTERS]; 47 u8 cluster_cnt[NUM_APIC_CLUSTERS];
47 48 int num_cpus = 0;
48 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
49 /* AMD always uses flat mode right now */
50 genapic = &apic_flat;
51 goto print;
52 }
53 49
54#if defined(CONFIG_ACPI_BUS) 50#if defined(CONFIG_ACPI_BUS)
55 /* 51 /*
@@ -64,15 +60,34 @@ void __init clustered_apic_check(void)
64#endif 60#endif
65 61
66 memset(cluster_cnt, 0, sizeof(cluster_cnt)); 62 memset(cluster_cnt, 0, sizeof(cluster_cnt));
67
68 for (i = 0; i < NR_CPUS; i++) { 63 for (i = 0; i < NR_CPUS; i++) {
69 id = bios_cpu_apicid[i]; 64 id = bios_cpu_apicid[i];
70 if (id != BAD_APICID) 65 if (id == BAD_APICID)
71 cluster_cnt[APIC_CLUSTERID(id)]++; 66 continue;
67 num_cpus++;
68 cluster_cnt[APIC_CLUSTERID(id)]++;
72 } 69 }
73 70
71 /* Don't use clustered mode on AMD platforms. */
72 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
73 genapic = &apic_physflat;
74#ifndef CONFIG_CPU_HOTPLUG
75 /* In the CPU hotplug case we cannot use broadcast mode
76 because that opens a race when a CPU is removed.
77 Stay at physflat mode in this case.
78 It is bad to do this unconditionally though. Once
79 we have ACPI platform support for CPU hotplug
80 we should detect hotplug capablity from ACPI tables and
81 only do this when really needed. -AK */
82 if (num_cpus <= 8)
83 genapic = &apic_flat;
84#endif
85 goto print;
86 }
87
74 clusters = 0; 88 clusters = 0;
75 max_cluster = 0; 89 max_cluster = 0;
90
76 for (i = 0; i < NUM_APIC_CLUSTERS; i++) { 91 for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
77 if (cluster_cnt[i] > 0) { 92 if (cluster_cnt[i] > 0) {
78 ++clusters; 93 ++clusters;
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index fdfa15f5d2ed..adc96282a9e2 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -2,7 +2,7 @@
2 * Copyright 2004 James Cleverdon, IBM. 2 * Copyright 2004 James Cleverdon, IBM.
3 * Subject to the GNU Public License, v.2 3 * Subject to the GNU Public License, v.2
4 * 4 *
5 * Flat APIC subarch code. Maximum 8 CPUs, logical delivery. 5 * Flat APIC subarch code.
6 * 6 *
7 * Hacked for x86-64 by James Cleverdon from i386 architecture code by 7 * Hacked for x86-64 by James Cleverdon from i386 architecture code by
8 * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and 8 * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
@@ -119,3 +119,63 @@ struct genapic apic_flat = {
119 .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, 119 .cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
120 .phys_pkg_id = phys_pkg_id, 120 .phys_pkg_id = phys_pkg_id,
121}; 121};
122
123/*
124 * Physflat mode is used when there are more than 8 CPUs on a AMD system.
125 * We cannot use logical delivery in this case because the mask
126 * overflows, so use physical mode.
127 */
128
129static cpumask_t physflat_target_cpus(void)
130{
131 return cpumask_of_cpu(0);
132}
133
134static void physflat_send_IPI_mask(cpumask_t cpumask, int vector)
135{
136 send_IPI_mask_sequence(cpumask, vector);
137}
138
139static void physflat_send_IPI_allbutself(int vector)
140{
141 cpumask_t allbutme = cpu_online_map;
142 int me = get_cpu();
143 cpu_clear(me, allbutme);
144 physflat_send_IPI_mask(allbutme, vector);
145 put_cpu();
146}
147
148static void physflat_send_IPI_all(int vector)
149{
150 physflat_send_IPI_mask(cpu_online_map, vector);
151}
152
153static unsigned int physflat_cpu_mask_to_apicid(cpumask_t cpumask)
154{
155 int cpu;
156
157 /*
158 * We're using fixed IRQ delivery, can only return one phys APIC ID.
159 * May as well be the first.
160 */
161 cpu = first_cpu(cpumask);
162 if ((unsigned)cpu < NR_CPUS)
163 return x86_cpu_to_apicid[cpu];
164 else
165 return BAD_APICID;
166}
167
168struct genapic apic_physflat = {
169 .name = "physical flat",
170 .int_delivery_mode = dest_LowestPrio,
171 .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
172 .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_LOWEST,
173 .target_cpus = physflat_target_cpus,
174 .apic_id_registered = flat_apic_id_registered,
175 .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
176 .send_IPI_all = physflat_send_IPI_all,
177 .send_IPI_allbutself = physflat_send_IPI_allbutself,
178 .send_IPI_mask = physflat_send_IPI_mask,
179 .cpu_mask_to_apicid = physflat_cpu_mask_to_apicid,
180 .phys_pkg_id = phys_pkg_id,
181};