blob: f3159a496e39ca2c6136b6bae47c72ecb11d1371 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright 2004 James Cleverdon, IBM.
3 * Subject to the GNU Public License, v.2
4 *
5 * Generic APIC sub-arch probe layer.
6 *
7 * Hacked for x86-64 by James Cleverdon from i386 architecture code by
8 * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
9 * James Cleverdon.
10 */
11#include <linux/config.h>
12#include <linux/threads.h>
13#include <linux/cpumask.h>
14#include <linux/string.h>
15#include <linux/kernel.h>
16#include <linux/ctype.h>
17#include <linux/init.h>
18#include <linux/module.h>
19
20#include <asm/smp.h>
21#include <asm/ipi.h>
22
Len Brown76f58582005-08-24 12:10:49 -040023#if defined(CONFIG_ACPI)
Jason Davis90660ec2005-04-16 15:24:53 -070024#include <acpi/acpi_bus.h>
25#endif
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027/* which logical CPU number maps to which CPU (physical APIC ID) */
Ravikiran G Thirumalai6c231b72005-09-06 15:17:45 -070028u8 x86_cpu_to_apicid[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
Linus Torvalds1da177e2005-04-16 15:20:36 -070029EXPORT_SYMBOL(x86_cpu_to_apicid);
30u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
31
32extern struct genapic apic_cluster;
33extern struct genapic apic_flat;
Andi Kleenf8d31192005-07-28 21:15:42 -070034extern struct genapic apic_physflat;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36struct genapic *genapic = &apic_flat;
37
38
39/*
40 * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
41 */
42void __init clustered_apic_check(void)
43{
44 long i;
45 u8 clusters, max_cluster;
46 u8 id;
47 u8 cluster_cnt[NUM_APIC_CLUSTERS];
Andi Kleen70556462005-09-12 18:49:24 +020048 int max_apic = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Len Brown76f58582005-08-24 12:10:49 -040050#if defined(CONFIG_ACPI)
Jason Davis90660ec2005-04-16 15:24:53 -070051 /*
52 * Some x86_64 machines use physical APIC mode regardless of how many
53 * procs/clusters are present (x86_64 ES7000 is an example).
54 */
55 if (acpi_fadt.revision > FADT2_REVISION_ID)
56 if (acpi_fadt.force_apic_physical_destination_mode) {
57 genapic = &apic_cluster;
58 goto print;
59 }
60#endif
61
Linus Torvalds1da177e2005-04-16 15:20:36 -070062 memset(cluster_cnt, 0, sizeof(cluster_cnt));
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 for (i = 0; i < NR_CPUS; i++) {
64 id = bios_cpu_apicid[i];
Andi Kleenf8d31192005-07-28 21:15:42 -070065 if (id == BAD_APICID)
66 continue;
Andi Kleen70556462005-09-12 18:49:24 +020067 if (id > max_apic)
68 max_apic = id;
Andi Kleenf8d31192005-07-28 21:15:42 -070069 cluster_cnt[APIC_CLUSTERID(id)]++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 }
71
Andi Kleenf8d31192005-07-28 21:15:42 -070072 /* Don't use clustered mode on AMD platforms. */
73 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
74 genapic = &apic_physflat;
75#ifndef CONFIG_CPU_HOTPLUG
76 /* In the CPU hotplug case we cannot use broadcast mode
77 because that opens a race when a CPU is removed.
78 Stay at physflat mode in this case.
79 It is bad to do this unconditionally though. Once
80 we have ACPI platform support for CPU hotplug
81 we should detect hotplug capablity from ACPI tables and
82 only do this when really needed. -AK */
Andi Kleen70556462005-09-12 18:49:24 +020083 if (max_apic <= 8)
Andi Kleenf8d31192005-07-28 21:15:42 -070084 genapic = &apic_flat;
85#endif
86 goto print;
87 }
88
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 clusters = 0;
90 max_cluster = 0;
Andi Kleenf8d31192005-07-28 21:15:42 -070091
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
93 if (cluster_cnt[i] > 0) {
94 ++clusters;
95 if (cluster_cnt[i] > max_cluster)
96 max_cluster = cluster_cnt[i];
97 }
98 }
99
100 /*
101 * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode,
102 * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical
103 * else physical mode.
104 * (We don't use lowest priority delivery + HW APIC IRQ steering, so
105 * can ignore the clustered logical case and go straight to physical.)
106 */
107 if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
108 genapic = &apic_flat;
109 else
110 genapic = &apic_cluster;
111
112print:
113 printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
114}
115
116/* Same for both flat and clustered. */
117
118void send_IPI_self(int vector)
119{
120 __send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
121}