From 8908aef9c2c62225bce2d8216e81397c872316e8 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Fri, 13 May 2011 16:31:31 +0000 Subject: [PATCH] * 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 --- headers/private/kernel/arch/x86/ioapic.h | 1 - src/system/boot/platform/bios_ia32/smp.cpp | 15 +++--- src/system/kernel/arch/x86/arch_int.cpp | 4 -- src/system/kernel/arch/x86/ioapic.cpp | 60 +++++++--------------- 4 files changed, 25 insertions(+), 55 deletions(-) diff --git a/headers/private/kernel/arch/x86/ioapic.h b/headers/private/kernel/arch/x86/ioapic.h index a9ada3e262..a48e215ea7 100644 --- a/headers/private/kernel/arch/x86/ioapic.h +++ b/headers/private/kernel/arch/x86/ioapic.h @@ -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 diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 0f635d37ac..b187197852 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -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(); diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 000cdcb327..69aa5da153 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -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); diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index 20976ae721..6b65b006c2 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -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) {