* Verify the MP config table signature and add some more sanity checks.

* Also reset the local and IO APIC base physical addresses when configuration
  failed.

Should fix #8102, but is otherwise untested for lack of old enough hardware.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43217 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2011-11-07 19:23:33 +00:00
parent fae2ce1945
commit a5c94bedb6
+42 -3
View File
@@ -106,6 +106,12 @@ smp_mp_probe(uint32 base, uint32 limit)
static status_t static status_t
smp_do_mp_config(mp_floating_struct *floatingStruct) smp_do_mp_config(mp_floating_struct *floatingStruct)
{ {
if (floatingStruct->config_length != 1) {
TRACE(("smp: unsupported structure length of %" B_PRIu8 " units\n",
floatingStruct->config_length));
return B_UNSUPPORTED;
}
TRACE(("smp: intel mp version %s, %s", TRACE(("smp: intel mp version %s, %s",
(floatingStruct->spec_revision == 1) ? "1.1" : "1.4", (floatingStruct->spec_revision == 1) ? "1.1" : "1.4",
(floatingStruct->mp_feature_2 & 0x80) (floatingStruct->mp_feature_2 & 0x80)
@@ -139,6 +145,18 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
mp_config_table *config = floatingStruct->config_table; mp_config_table *config = floatingStruct->config_table;
gKernelArgs.num_cpus = 0; gKernelArgs.num_cpus = 0;
if (config->signature != MP_CONFIG_TABLE_SIGNATURE) {
TRACE(("smp: invalid config table signature, aborting\n"));
return B_ERROR;
}
if (config->base_table_length < sizeof(mp_config_table)) {
TRACE(("smp: config table length %" B_PRIu16
" too short for structure, aborting\n",
config->base_table_length));
return B_ERROR;
}
// print our new found configuration. // print our new found configuration.
TRACE(("smp: oem id: %.8s product id: %.12s\n", config->oem, TRACE(("smp: oem id: %.8s product id: %.12s\n", config->oem,
config->product)); config->product));
@@ -146,6 +164,12 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
config->num_base_entries, config->ext_length)); config->num_base_entries, config->ext_length));
gKernelArgs.arch_args.apic_phys = (uint32)config->apic; gKernelArgs.arch_args.apic_phys = (uint32)config->apic;
if ((gKernelArgs.arch_args.apic_phys % 4096) != 0) {
// MP specs mandate a 4K alignment for the local APIC(s)
TRACE(("smp: local apic %p has bad alignment, aborting\n",
(void *)gKernelArgs.arch_args.apic_phys));
return B_ERROR;
}
char *pointer = (char *)((uint32)config + sizeof(struct mp_config_table)); char *pointer = (char *)((uint32)config + sizeof(struct mp_config_table));
for (int32 i = 0; i < config->num_base_entries; i++) { for (int32 i = 0; i < config->num_base_entries; i++) {
@@ -203,8 +227,15 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
struct mp_base_ioapic *io = (struct mp_base_ioapic *)pointer; struct mp_base_ioapic *io = (struct mp_base_ioapic *)pointer;
pointer += sizeof(struct mp_base_ioapic); pointer += sizeof(struct mp_base_ioapic);
if (gKernelArgs.arch_args.ioapic_phys == 0) if (gKernelArgs.arch_args.ioapic_phys == 0) {
gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr; gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr;
if (gKernelArgs.arch_args.ioapic_phys % 1024) {
// MP specs mandate a 1K alignment for the IO-APICs
TRACE(("smp: io apic %p has bad alignment, aborting\n",
(void *)gKernelArgs.arch_args.ioapic_phys));
return B_ERROR;
}
}
TRACE(("smp: found io apic with apic id %d, version %d\n", TRACE(("smp: found io apic with apic id %d, version %d\n",
io->ioapic_id, io->ioapic_version)); io->ioapic_id, io->ioapic_version));
@@ -230,12 +261,17 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
} }
} }
if (gKernelArgs.num_cpus == 0) {
TRACE(("smp: didn't find any processors, aborting\n"));
return B_ERROR;
}
dprintf("smp: apic @ %p, i/o apic @ %p, total %ld processors detected\n", dprintf("smp: apic @ %p, i/o apic @ %p, total %ld processors detected\n",
(void *)gKernelArgs.arch_args.apic_phys, (void *)gKernelArgs.arch_args.apic_phys,
(void *)gKernelArgs.arch_args.ioapic_phys, (void *)gKernelArgs.arch_args.ioapic_phys,
gKernelArgs.num_cpus); gKernelArgs.num_cpus);
return gKernelArgs.num_cpus > 0 ? B_OK : B_ERROR; return B_OK;
} }
@@ -637,6 +673,9 @@ smp_init(void)
return; return;
} }
// everything failed or we are not running an SMP system // Everything failed or we are not running an SMP system, reset anything
// that might have been set through an incomplete configuration attempt.
gKernelArgs.arch_args.apic_phys = 0;
gKernelArgs.arch_args.ioapic_phys = 0;
gKernelArgs.num_cpus = 1; gKernelArgs.num_cpus = 1;
} }