Author: mmlr Date: 2011-05-11 20:05:05 +0200 (Wed, 11 May 2011) New Revision: 41445 Changeset: https://dev.haiku-os.org/changeset/41445 Modified: haiku/trunk/headers/private/kernel/arch/x86/apic.h haiku/trunk/headers/private/kernel/arch/x86/ioapic.h haiku/trunk/src/system/kernel/arch/x86/apic.cpp haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp haiku/trunk/src/system/kernel/arch/x86/ioapic.cpp haiku/trunk/src/system/kernel/arch/x86/msi.cpp Log: * When initializing MSI support, don't assume a single 24 entry IO-APIC. Instead mark the ISA interrupts as unusable and then use ioapic_is_interrupt_available to determine if that vector is possibly taken by an IO-APIC. If IO-APICs are not used, this will simply always return false, leaving all vectors free for MSI use. * The msi_init() now has to be done after a potential IO-APIC init, so it is now done after ioapic_init() instead of inside apic_init(). * Add apic_disable_local_ints() to clear the local ints on the local APIC once we are in APIC mode (i.e. the IO-APIC is set up and we don't need the external routing anymore). Modified: haiku/trunk/headers/private/kernel/arch/x86/apic.h =================================================================== --- haiku/trunk/headers/private/kernel/arch/x86/apic.h 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/headers/private/kernel/arch/x86/apic.h 2011-05-11 18:05:05 UTC (rev 41445) @@ -115,6 +115,8 @@ uint32 apic_local_id(); void apic_end_of_interrupt(); +void apic_disable_local_ints(); + status_t apic_init(kernel_args *args); status_t apic_per_cpu_init(kernel_args *args, int32 cpu); Modified: haiku/trunk/headers/private/kernel/arch/x86/ioapic.h =================================================================== --- haiku/trunk/headers/private/kernel/arch/x86/ioapic.h 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/headers/private/kernel/arch/x86/ioapic.h 2011-05-11 18:05:05 UTC (rev 41445) @@ -5,8 +5,12 @@ #ifndef _KERNEL_ARCH_x86_IOAPIC_H #define _KERNEL_ARCH_x86_IOAPIC_H +#include <SupportDefs.h> + struct kernel_args; +bool ioapic_is_interrupt_available(int32 gsi); + void ioapic_map(kernel_args* args); void ioapic_init(kernel_args* args); Modified: haiku/trunk/src/system/kernel/arch/x86/apic.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/apic.cpp 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/src/system/kernel/arch/x86/apic.cpp 2011-05-11 18:05:05 UTC (rev 41445) @@ -56,6 +56,15 @@ } +void +apic_disable_local_ints() +{ + // just clear them out completely + apic_write(APIC_LVT_LINT0, APIC_LVT_MASKED); + apic_write(APIC_LVT_LINT1, APIC_LVT_MASKED); +} + + status_t apic_init(kernel_args *args) { @@ -72,7 +81,6 @@ return B_ERROR; } - msi_init(); return B_OK; } Modified: haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/src/system/kernel/arch/x86/arch_int.cpp 2011-05-11 18:05:05 UTC (rev 41445) @@ -28,6 +28,7 @@ #include <arch/x86/apic.h> #include <arch/x86/descriptors.h> +#include <arch/x86/msi.h> #include <arch/x86/vm86.h> #include "interrupts.h" @@ -866,6 +867,7 @@ arch_int_init_io(kernel_args* args) { ioapic_init(args); + msi_init(); return B_OK; } Modified: haiku/trunk/src/system/kernel/arch/x86/ioapic.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/ioapic.cpp 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/src/system/kernel/arch/x86/ioapic.cpp 2011-05-11 18:05:05 UTC (rev 41445) @@ -171,13 +171,6 @@ static bool -ioapic_is_interrupt_available(int32 gsi) -{ - return find_ioapic(gsi) != NULL; -} - - -static bool ioapic_is_spurious_interrupt(int32 gsi) { // the spurious interrupt vector is initialized to the max value in smp @@ -456,6 +449,13 @@ } +bool +ioapic_is_interrupt_available(int32 gsi) +{ + return find_ioapic(gsi) != NULL; +} + + void ioapic_map(kernel_args* args) { @@ -577,6 +577,14 @@ entry.polarity | entry.trigger_mode); } + // kill the local ints on the local APIC + apic_disable_local_ints(); + // TODO: This uses the assumption that our init is running on the + // boot CPU and only the boot CPU has the local ints configured + // because it was running in legacy PIC mode. Possibly the other + // local APICs of the other CPUs have them configured as well. It + // shouldn't really harm, but should eventually be corrected. + // disable the legacy PIC pic_disable(); Modified: haiku/trunk/src/system/kernel/arch/x86/msi.cpp =================================================================== --- haiku/trunk/src/system/kernel/arch/x86/msi.cpp 2011-05-11 17:14:05 UTC (rev 41444) +++ haiku/trunk/src/system/kernel/arch/x86/msi.cpp 2011-05-11 18:05:05 UTC (rev 41445) @@ -5,14 +5,17 @@ #include <arch/x86/apic.h> #include <arch/x86/arch_int.h> +#include <arch/x86/ioapic.h> #include <arch/x86/msi.h> #include <debug.h> #include <lock.h> +static const uint32 kVectorCount = 256 - ARCH_INTERRUPT_BASE; +static const uint8 kNumISAVectors = 16; + static bool sMSISupported = false; -static const uint32 kVectorCount = 256 - ARCH_INTERRUPT_BASE; static bool sAllocatedVectors[kVectorCount]; static mutex sMSIAllocationLock = MUTEX_INITIALIZER("msi_allocation"); @@ -25,13 +28,19 @@ return; } - for (uint16 i = 0; i < kVectorCount; i++) - sAllocatedVectors[i] = false; + // TODO: less hardcoding! - // the first 24 vectors are addressable with a single ioapic config - for (uint16 i = 0; i < 24; i++) + // the first 16 vectors are legacy ISA in all cases + for (uint16 i = 0; i < kNumISAVectors; i++) sAllocatedVectors[i] = true; + for (uint16 i = kNumISAVectors; i < kVectorCount; i++) { + // if ioapics aren't in use this will always return false, leaving + // the vectors free for us; otherwise we'll avoid any vector that + // can be addressed by an IO-APIC + sAllocatedVectors[i] = ioapic_is_interrupt_available(i); + } + // performance testing and syscall interrupts sAllocatedVectors[98 - ARCH_INTERRUPT_BASE] = true; sAllocatedVectors[99 - ARCH_INTERRUPT_BASE] = true;