aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Travis <travis@sgi.com>2015-04-09 14:26:30 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-10 04:16:07 -0400
commit379b97e280971ef7673db5166c7e0f7ab49b81de (patch)
treefc7f887b1c32ed9e9e2eebc25d1972b55dfc95e2
parent7a4e017041136de05527722b97e0c1f8702a5cbe (diff)
x86/apic/uv: Update the UV APIC driver check
Fix a bug in the OEM check function that determines if the system is a UV system and the BIOS is compatible with the kernel's UV apic driver. This prevents some possibly obscure panics and guards the system against being started on SGI hardware that does not have the required kernel support. Signed-off-by: Mike Travis <travis@sgi.com> Acked-by: Hedi Berriche <hedi@sgi.com> Acked-by: Dimitri Sivanich <sivanich@sgi.com> Link: http://lkml.kernel.org/r/20150409182629.112998930@asylum.americas.sgi.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c74
1 files changed, 49 insertions, 25 deletions
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 2a739a90010e..e18962c8b007 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -144,36 +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 int uv_apic;
148 149
149 if (strncmp(oem_id, "SGI", 3) != 0) 150 if (strncmp(oem_id, "SGI", 3) != 0)
150 return 0; 151 return 0;
151 152
152 is_uv1 = !strcmp(oem_id, "SGI"); 153 /*
153 is_uv2 = !strcmp(oem_id, "SGI2"); 154 * Determine UV arch type.
154 is_uv3 = !strncmp(oem_id, "SGI3", 4); /* there are varieties of UV3 */ 155 * SGI: UV100/1000
155 if (is_uv1 || is_uv2 || is_uv3) { 156 * SGI2: UV2000/3000
156 uv_hub_info->hub_revision = 157 * SGI3: UV300 (truncated to 4 chars because of different varieties)
157 (is_uv1 ? UV1_HUB_REVISION_BASE : 158 */
158 (is_uv2 ? UV2_HUB_REVISION_BASE : 159 uv_hub_info->hub_revision =
159 UV3_HUB_REVISION_BASE)); 160 !strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
160 pnodeid = early_get_pnodeid(); 161 !strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
161 early_get_apic_pnode_shift(); 162 !strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
162 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; 163
163 x86_platform.nmi_init = uv_nmi_init; 164 if (uv_hub_info->hub_revision == 0)
164 if (!strcmp(oem_table_id, "UVL")) 165 goto badbios;
165 uv_system_type = UV_LEGACY_APIC; 166
166 else if (!strcmp(oem_table_id, "UVX")) 167 pnodeid = early_get_pnodeid();
167 uv_system_type = UV_X2APIC; 168 early_get_apic_pnode_shift();
168 else if (!strcmp(oem_table_id, "UVH")) { 169 x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range;
169 __this_cpu_write(x2apic_extra_bits, 170 x86_platform.nmi_init = uv_nmi_init;
170 pnodeid << uvh_apicid.s.pnode_shift); 171
171 uv_system_type = UV_NON_UNIQUE_APIC; 172 if (!strcmp(oem_table_id, "UVX")) { /* most common */
172 uv_set_apicid_hibit(); 173 uv_system_type = UV_X2APIC;
173 return 1; 174 uv_apic = 0;
174 } 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;
175 } 189 }
176 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();
177} 201}
178 202
179enum uv_system_type get_uv_system_type(void) 203enum uv_system_type get_uv_system_type(void)