* Don't map the IO-APIC within the bootloader. We don't need it to set up SMP
at all and, since there can be multiple IO-APICs, we need to do the enumeration again in the kernel anyway. Also only set ioapic_phys the first time we encounter an IO-APIC object as it looks cleaner when we arrive at the first IO-APIC default address. * Therefore we don't have to worry about already mapped IO-APICs when enumerating them in the kernel. * Also remove the mapping function that is now not used anymore. * We still use the ioapic_phys field of the kernel args to determine whether there is an IO-APIC at all to avoid needlessly doing the enumeration again. This fixes multi IO-APIC configurations, because before we would indeed map the last IO-APIC listed in the MADT, but then in the kernel assumed we mapped the first one. We'd end up with mapping the last listed IO-APIC twice and the first IO-APIC never, always programming the last one when we actually targetted the first one. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41476 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c75f313fbd
commit
8908aef9c2
@ -11,7 +11,6 @@ struct kernel_args;
|
||||
|
||||
bool ioapic_is_interrupt_available(int32 gsi);
|
||||
|
||||
void ioapic_map(kernel_args* args);
|
||||
void ioapic_init(kernel_args* args);
|
||||
|
||||
#endif // _KERNEL_ARCH_x86_IOAPIC_H
|
||||
|
@ -204,7 +204,8 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
|
||||
struct mp_base_ioapic *io = (struct mp_base_ioapic *)pointer;
|
||||
pointer += sizeof(struct mp_base_ioapic);
|
||||
|
||||
gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr;
|
||||
if (gKernelArgs.arch_args.ioapic_phys != 0)
|
||||
gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr;
|
||||
|
||||
TRACE(("smp: found io apic with apic id %d, version %d\n",
|
||||
io->ioapic_id, io->ioapic_version));
|
||||
@ -290,7 +291,8 @@ smp_do_acpi_config(void)
|
||||
acpi_io_apic *ioApic = (acpi_io_apic *)apic;
|
||||
TRACE(("smp: found io APIC with id %u and address 0x%lx\n",
|
||||
ioApic->io_apic_id, ioApic->io_apic_address));
|
||||
gKernelArgs.arch_args.ioapic_phys = ioApic->io_apic_address;
|
||||
if (gKernelArgs.arch_args.ioapic_phys == 0)
|
||||
gKernelArgs.arch_args.ioapic_phys = ioApic->io_apic_address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -410,16 +412,11 @@ smp_init_other_cpus(void)
|
||||
TRACE(("smp: ioapic_phys = %p\n",
|
||||
(void *)gKernelArgs.arch_args.ioapic_phys));
|
||||
|
||||
// map in the apic & ioapic (if available)
|
||||
// map in the apic
|
||||
gKernelArgs.arch_args.apic = (uint32 *)mmu_map_physical_memory(
|
||||
gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||
if (gKernelArgs.arch_args.ioapic_phys != 0) {
|
||||
gKernelArgs.arch_args.ioapic = (uint32 *)mmu_map_physical_memory(
|
||||
gKernelArgs.arch_args.ioapic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||
}
|
||||
|
||||
TRACE(("smp: apic = %p\n", gKernelArgs.arch_args.apic));
|
||||
TRACE(("smp: ioapic = %p\n", gKernelArgs.arch_args.ioapic));
|
||||
TRACE(("smp: apic (mapped) = %p\n", gKernelArgs.arch_args.apic));
|
||||
|
||||
// calculate how fast the apic timer is
|
||||
calculate_apic_timer_conversion_factor();
|
||||
|
@ -825,10 +825,6 @@ arch_int_init_post_vm(struct kernel_args *args)
|
||||
// don't end up using the io apic
|
||||
apic_init(args);
|
||||
|
||||
// We need to map in the I/O APIC here, since we would lose the already
|
||||
// wired mapping before arch_int_init_io() is called.
|
||||
ioapic_map(args);
|
||||
|
||||
// create IDT area for the boot CPU
|
||||
area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS,
|
||||
B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
|
@ -108,7 +108,7 @@ struct ioapic {
|
||||
};
|
||||
|
||||
|
||||
static ioapic sIOAPICs = { 0, 0, 0, 0, 0, 0, 0, -1, NULL, NULL };
|
||||
static ioapic* sIOAPICs = NULL;
|
||||
|
||||
|
||||
// #pragma mark - I/O APIC
|
||||
@ -130,7 +130,7 @@ find_ioapic(int32 gsi)
|
||||
if (gsi < 0)
|
||||
return NULL;
|
||||
|
||||
struct ioapic* current = &sIOAPICs;
|
||||
struct ioapic* current = sIOAPICs;
|
||||
while (current != NULL) {
|
||||
if (gsi >= current->global_interrupt_base
|
||||
&& gsi <= current->global_interrupt_last) {
|
||||
@ -371,7 +371,7 @@ acpi_enumerate_ioapics(acpi_module_info* acpi)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
struct ioapic* lastIOAPIC = &sIOAPICs;
|
||||
struct ioapic* lastIOAPIC = sIOAPICs;
|
||||
|
||||
acpi_subtable_header* apicEntry
|
||||
= (acpi_subtable_header*)((uint8*)madt + sizeof(acpi_table_madt));
|
||||
@ -385,20 +385,6 @@ acpi_enumerate_ioapics(acpi_module_info* acpi)
|
||||
"interrupt base %lu, apic-id %u\n", (uint32)info->Address,
|
||||
(uint32)info->GlobalIrqBase, info->Id);
|
||||
|
||||
struct ioapic* alreadyMapped
|
||||
= find_ioapic((int32)info->GlobalIrqBase);
|
||||
if (alreadyMapped != NULL) {
|
||||
// We've already mapped this IO-APIC (at boot), but we
|
||||
// need to fill in the APIC ID. TODO: We might not
|
||||
// actually get the IO-APIC with base 0 as first entry!
|
||||
alreadyMapped->apic_id = info->Id;
|
||||
alreadyMapped->global_interrupt_base = info->GlobalIrqBase;
|
||||
alreadyMapped->global_interrupt_last = info->GlobalIrqBase
|
||||
+ alreadyMapped->max_redirection_entry;
|
||||
print_ioapic(*alreadyMapped);
|
||||
break;
|
||||
}
|
||||
|
||||
struct ioapic* ioapic
|
||||
= (struct ioapic*)malloc(sizeof(struct ioapic));
|
||||
if (ioapic == NULL) {
|
||||
@ -407,7 +393,8 @@ acpi_enumerate_ioapics(acpi_module_info* acpi)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
ioapic->number = lastIOAPIC->number + 1;
|
||||
ioapic->number
|
||||
= lastIOAPIC != NULL ? lastIOAPIC->number + 1 : 0;
|
||||
ioapic->apic_id = info->Id;
|
||||
ioapic->global_interrupt_base = info->GlobalIrqBase;
|
||||
ioapic->registers = NULL;
|
||||
@ -422,7 +409,12 @@ acpi_enumerate_ioapics(acpi_module_info* acpi)
|
||||
}
|
||||
|
||||
print_ioapic(*ioapic);
|
||||
lastIOAPIC->next = ioapic;
|
||||
|
||||
if (lastIOAPIC == NULL)
|
||||
sIOAPICs = ioapic;
|
||||
else
|
||||
lastIOAPIC->next = ioapic;
|
||||
|
||||
lastIOAPIC = ioapic;
|
||||
break;
|
||||
}
|
||||
@ -524,26 +516,6 @@ ioapic_is_interrupt_available(int32 gsi)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ioapic_map(kernel_args* args)
|
||||
{
|
||||
if (args->arch_args.apic == NULL) {
|
||||
dprintf("no local apic available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args->arch_args.ioapic == NULL) {
|
||||
dprintf("no io-apic available, not using io-apics for interrupt "
|
||||
"routing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// map in the first IO-APIC
|
||||
sIOAPICs.registers = (ioapic_registers*)args->arch_args.ioapic;
|
||||
ioapic_map_ioapic(sIOAPICs, args->arch_args.ioapic_phys);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ioapic_init(kernel_args* args)
|
||||
{
|
||||
@ -557,9 +529,15 @@ ioapic_init(kernel_args* args)
|
||||
&ioapic_end_of_interrupt
|
||||
};
|
||||
|
||||
if (sIOAPICs.register_area < 0 || sIOAPICs.registers == NULL)
|
||||
if (args->arch_args.apic == NULL)
|
||||
return;
|
||||
|
||||
if (args->arch_args.ioapic_phys == 0) {
|
||||
dprintf("no io-apics available, not using io-apics for interrupt "
|
||||
"routing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (get_safemode_boolean(B_SAFEMODE_DISABLE_IOAPIC, false)) {
|
||||
dprintf("io-apics explicitly disabled, not using io-apics for "
|
||||
@ -618,7 +596,7 @@ ioapic_init(kernel_args* args)
|
||||
// use the boot CPU as the target for all interrupts
|
||||
uint8 targetAPIC = args->arch_args.cpu_apic_id[0];
|
||||
|
||||
struct ioapic* current = &sIOAPICs;
|
||||
struct ioapic* current = sIOAPICs;
|
||||
while (current != NULL) {
|
||||
status = ioapic_initialize_ioapic(*current, targetAPIC);
|
||||
if (status != B_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user