* 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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user