* 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
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",
(floatingStruct->spec_revision == 1) ? "1.1" : "1.4",
(floatingStruct->mp_feature_2 & 0x80)
@@ -139,6 +145,18 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
mp_config_table *config = floatingStruct->config_table;
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.
TRACE(("smp: oem id: %.8s product id: %.12s\n", config->oem,
config->product));
@@ -146,6 +164,12 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
config->num_base_entries, config->ext_length));
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));
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;
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;
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",
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",
(void *)gKernelArgs.arch_args.apic_phys,
(void *)gKernelArgs.arch_args.ioapic_phys,
gKernelArgs.num_cpus);
return gKernelArgs.num_cpus > 0 ? B_OK : B_ERROR;
return B_OK;
}
@@ -637,6 +673,9 @@ smp_init(void)
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;
}