diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/apic.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 62 | ||||
-rw-r--r-- | arch/x86/kernel/apic/x2apic_uv_x.c | 89 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 2 |
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); | |||
204 | extern void disconnect_bsp_APIC(int virt_wire_setup); | 204 | extern void disconnect_bsp_APIC(int virt_wire_setup); |
205 | extern void disable_local_APIC(void); | 205 | extern void disable_local_APIC(void); |
206 | extern void lapic_shutdown(void); | 206 | extern void lapic_shutdown(void); |
207 | extern int verify_local_APIC(void); | ||
208 | extern void sync_Arb_IDs(void); | 207 | extern void sync_Arb_IDs(void); |
209 | extern void init_bsp_APIC(void); | 208 | extern void init_bsp_APIC(void); |
210 | extern void setup_local_APIC(void); | 209 | extern 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 | */ | ||
1092 | int __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 | ||
145 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 145 | static 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 | |||
197 | badbios: | ||
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 | ||
176 | enum uv_system_type get_uv_system_type(void) | 203 | enum 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 | */ |