aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/apic.h1
-rw-r--r--arch/x86/kernel/apic/apic.c62
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c89
-rw-r--r--arch/x86/kernel/smpboot.c2
4 files changed, 60 insertions, 94 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index efc3b22d896e..08f217354442 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -204,7 +204,6 @@ extern void clear_local_APIC(void);
204extern void disconnect_bsp_APIC(int virt_wire_setup); 204extern void disconnect_bsp_APIC(int virt_wire_setup);
205extern void disable_local_APIC(void); 205extern void disable_local_APIC(void);
206extern void lapic_shutdown(void); 206extern void lapic_shutdown(void);
207extern int verify_local_APIC(void);
208extern void sync_Arb_IDs(void); 207extern void sync_Arb_IDs(void);
209extern void init_bsp_APIC(void); 208extern void init_bsp_APIC(void);
210extern void setup_local_APIC(void); 209extern void setup_local_APIC(void);
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ad3639ae1b9b..dcb52850a28f 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1084,67 +1084,6 @@ void lapic_shutdown(void)
1084 local_irq_restore(flags); 1084 local_irq_restore(flags);
1085} 1085}
1086 1086
1087/*
1088 * This is to verify that we're looking at a real local APIC.
1089 * Check these against your board if the CPUs aren't getting
1090 * started for no apparent reason.
1091 */
1092int __init verify_local_APIC(void)
1093{
1094 unsigned int reg0, reg1;
1095
1096 /*
1097 * The version register is read-only in a real APIC.
1098 */
1099 reg0 = apic_read(APIC_LVR);
1100 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
1101 apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
1102 reg1 = apic_read(APIC_LVR);
1103 apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
1104
1105 /*
1106 * The two version reads above should print the same
1107 * numbers. If the second one is different, then we
1108 * poke at a non-APIC.
1109 */
1110 if (reg1 != reg0)
1111 return 0;
1112
1113 /*
1114 * Check if the version looks reasonably.
1115 */
1116 reg1 = GET_APIC_VERSION(reg0);
1117 if (reg1 == 0x00 || reg1 == 0xff)
1118 return 0;
1119 reg1 = lapic_get_maxlvt();
1120 if (reg1 < 0x02 || reg1 == 0xff)
1121 return 0;
1122
1123 /*
1124 * The ID register is read/write in a real APIC.
1125 */
1126 reg0 = apic_read(APIC_ID);
1127 apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
1128 apic_write(APIC_ID, reg0 ^ apic->apic_id_mask);
1129 reg1 = apic_read(APIC_ID);
1130 apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
1131 apic_write(APIC_ID, reg0);
1132 if (reg1 != (reg0 ^ apic->apic_id_mask))
1133 return 0;
1134
1135 /*
1136 * The next two are just to see if we have sane values.
1137 * They're only really relevant if we're in Virtual Wire
1138 * compatibility mode, but most boxes are anymore.
1139 */
1140 reg0 = apic_read(APIC_LVT0);
1141 apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
1142 reg1 = apic_read(APIC_LVT1);
1143 apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
1144
1145 return 1;
1146}
1147
1148/** 1087/**
1149 * sync_Arb_IDs - synchronize APIC bus arbitration IDs 1088 * sync_Arb_IDs - synchronize APIC bus arbitration IDs
1150 */ 1089 */
@@ -2283,7 +2222,6 @@ int __init APIC_init_uniprocessor(void)
2283 disable_ioapic_support(); 2222 disable_ioapic_support();
2284 2223
2285 default_setup_apic_routing(); 2224 default_setup_apic_routing();
2286 verify_local_APIC();
2287 apic_bsp_setup(true); 2225 apic_bsp_setup(true);
2288 return 0; 2226 return 0;
2289} 2227}
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 8e9dcfd630e4..c8d92950bc04 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -144,33 +144,60 @@ static void __init uv_set_apicid_hibit(void)
144 144
145static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) 145static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
146{ 146{
147 int pnodeid, is_uv1, is_uv2, is_uv3; 147 int pnodeid;
148 148 int uv_apic;
149 is_uv1 = !strcmp(oem_id, "SGI"); 149
150 is_uv2 = !strcmp(oem_id, "SGI2"); 150 if (strncmp(oem_id, "SGI", 3) != 0)
151 is_uv3 = !strncmp(oem_id, "SGI3", 4); /* there are varieties of UV3 */ 151 return 0;
152 if (is_uv1 || is_uv2 || is_uv3) { 152
153 uv_hub_info->hub_revision = 153 /*
154 (is_uv1 ? UV1_HUB_REVISION_BASE : 154 * Determine UV arch type.
155 (is_uv2 ? UV2_HUB_REVISION_BASE : 155 * SGI: UV100/1000
156 UV3_HUB_REVISION_BASE)); 156 * SGI2: UV2000/3000
157 pnodeid = early_get_pnodeid(); 157 * SGI3: UV300 (truncated to 4 chars because of different varieties)
158 early_get_apic_pnode_shift(); 158 */
159 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; 159 uv_hub_info->hub_revision =
160 x86_platform.nmi_init = uv_nmi_init; 160 !strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
161 if (!strcmp(oem_table_id, "UVL")) 161 !strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
162 uv_system_type = UV_LEGACY_APIC; 162 !strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
163 else if (!strcmp(oem_table_id, "UVX")) 163
164 uv_system_type = UV_X2APIC; 164 if (uv_hub_info->hub_revision == 0)
165 else if (!strcmp(oem_table_id, "UVH")) { 165 goto badbios;
166 __this_cpu_write(x2apic_extra_bits, 166
167 pnodeid << uvh_apicid.s.pnode_shift); 167 pnodeid = early_get_pnodeid();
168 uv_system_type = UV_NON_UNIQUE_APIC; 168 early_get_apic_pnode_shift();
169 uv_set_apicid_hibit(); 169 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
170 return 1; 170 x86_platform.nmi_init = uv_nmi_init;
171 } 171
172 if (!strcmp(oem_table_id, "UVX")) { /* most common */
173 uv_system_type = UV_X2APIC;
174 uv_apic = 0;
175
176 } else if (!strcmp(oem_table_id, "UVH")) { /* only UV1 systems */
177 uv_system_type = UV_NON_UNIQUE_APIC;
178 __this_cpu_write(x2apic_extra_bits,
179 pnodeid << uvh_apicid.s.pnode_shift);
180 uv_set_apicid_hibit();
181 uv_apic = 1;
182
183 } else if (!strcmp(oem_table_id, "UVL")) { /* only used for */
184 uv_system_type = UV_LEGACY_APIC; /* very small systems */
185 uv_apic = 0;
186
187 } else {
188 goto badbios;
172 } 189 }
173 return 0; 190
191 pr_info("UV: OEM IDs %s/%s, System/HUB Types %d/%d, uv_apic %d\n",
192 oem_id, oem_table_id, uv_system_type,
193 uv_min_hub_revision_id, uv_apic);
194
195 return uv_apic;
196
197badbios:
198 pr_err("UV: OEM_ID:%s OEM_TABLE_ID:%s\n", oem_id, oem_table_id);
199 pr_err("Current BIOS not supported, update kernel and/or BIOS\n");
200 BUG();
174} 201}
175 202
176enum uv_system_type get_uv_system_type(void) 203enum uv_system_type get_uv_system_type(void)
@@ -854,10 +881,14 @@ void __init uv_system_init(void)
854 unsigned long mmr_base, present, paddr; 881 unsigned long mmr_base, present, paddr;
855 unsigned short pnode_mask; 882 unsigned short pnode_mask;
856 unsigned char n_lshift; 883 unsigned char n_lshift;
857 char *hub = (is_uv1_hub() ? "UV1" : 884 char *hub = (is_uv1_hub() ? "UV100/1000" :
858 (is_uv2_hub() ? "UV2" : 885 (is_uv2_hub() ? "UV2000/3000" :
859 "UV3")); 886 (is_uv3_hub() ? "UV300" : NULL)));
860 887
888 if (!hub) {
889 pr_err("UV: Unknown/unsupported UV hub\n");
890 return;
891 }
861 pr_info("UV: Found %s hub\n", hub); 892 pr_info("UV: Found %s hub\n", hub);
862 map_low_mmrs(); 893 map_low_mmrs();
863 894
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index febc6aabc72e..ddd2c0674cda 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1086,8 +1086,6 @@ static int __init smp_sanity_check(unsigned max_cpus)
1086 return SMP_NO_APIC; 1086 return SMP_NO_APIC;
1087 } 1087 }
1088 1088
1089 verify_local_APIC();
1090
1091 /* 1089 /*
1092 * If SMP should be disabled, then really disable it! 1090 * If SMP should be disabled, then really disable it!
1093 */ 1091 */