diff options
author | Andi Kleen <ak@suse.de> | 2005-07-29 00:15:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-29 00:46:01 -0400 |
commit | f8d311939f9d2b2a5e935df8dceb98b7cbe08d43 (patch) | |
tree | 02da12ff661ee3da44e29e4ca89df28dea8a4593 | |
parent | 37a47e65fa58d413a31f27ee88f6cb98583b6157 (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.c | 33 | ||||
-rw-r--r-- | arch/x86_64/kernel/genapic_flat.c | 62 |
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 | ||
32 | extern struct genapic apic_cluster; | 32 | extern struct genapic apic_cluster; |
33 | extern struct genapic apic_flat; | 33 | extern struct genapic apic_flat; |
34 | extern struct genapic apic_physflat; | ||
34 | 35 | ||
35 | struct genapic *genapic = &apic_flat; | 36 | struct 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 | |||
129 | static cpumask_t physflat_target_cpus(void) | ||
130 | { | ||
131 | return cpumask_of_cpu(0); | ||
132 | } | ||
133 | |||
134 | static void physflat_send_IPI_mask(cpumask_t cpumask, int vector) | ||
135 | { | ||
136 | send_IPI_mask_sequence(cpumask, vector); | ||
137 | } | ||
138 | |||
139 | static 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 | |||
148 | static void physflat_send_IPI_all(int vector) | ||
149 | { | ||
150 | physflat_send_IPI_mask(cpu_online_map, vector); | ||
151 | } | ||
152 | |||
153 | static 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 | |||
168 | struct 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 | }; | ||