From a56cbb2afbf4dbfb4a07dfdd95f10637a195a053 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 11 May 2011 18:05:05 +0000 Subject: [PATCH] * 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). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41445 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/apic.h | 2 ++ headers/private/kernel/arch/x86/ioapic.h | 4 ++++ src/system/kernel/arch/x86/apic.cpp | 10 +++++++++- src/system/kernel/arch/x86/arch_int.cpp | 2 ++ src/system/kernel/arch/x86/ioapic.cpp | 22 +++++++++++++++------- src/system/kernel/arch/x86/msi.cpp | 19 ++++++++++++++----- 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/headers/private/kernel/arch/x86/apic.h b/headers/private/kernel/arch/x86/apic.h index bb01d628e8..e0e18f7585 100644 --- a/headers/private/kernel/arch/x86/apic.h +++ b/headers/private/kernel/arch/x86/apic.h @@ -115,6 +115,8 @@ void apic_write(uint32 offset, uint32 data); 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); diff --git a/headers/private/kernel/arch/x86/ioapic.h b/headers/private/kernel/arch/x86/ioapic.h index b0195d0b38..a9ada3e262 100644 --- a/headers/private/kernel/arch/x86/ioapic.h +++ b/headers/private/kernel/arch/x86/ioapic.h @@ -5,8 +5,12 @@ #ifndef _KERNEL_ARCH_x86_IOAPIC_H #define _KERNEL_ARCH_x86_IOAPIC_H +#include + struct kernel_args; +bool ioapic_is_interrupt_available(int32 gsi); + void ioapic_map(kernel_args* args); void ioapic_init(kernel_args* args); diff --git a/src/system/kernel/arch/x86/apic.cpp b/src/system/kernel/arch/x86/apic.cpp index 63a332e0ff..2c83935402 100644 --- a/src/system/kernel/arch/x86/apic.cpp +++ b/src/system/kernel/arch/x86/apic.cpp @@ -56,6 +56,15 @@ apic_end_of_interrupt() } +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 @@ apic_init(kernel_args *args) return B_ERROR; } - msi_init(); return B_OK; } diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 17ffabd692..000cdcb327 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include "interrupts.h" @@ -866,6 +867,7 @@ status_t arch_int_init_io(kernel_args* args) { ioapic_init(args); + msi_init(); return B_OK; } diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index d4351ad9e8..4cd0459e2d 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -170,13 +170,6 @@ ioapic_write_64(struct ioapic& ioapic, uint8 registerSelect, uint64 value) } -static bool -ioapic_is_interrupt_available(int32 gsi) -{ - return find_ioapic(gsi) != NULL; -} - - static bool ioapic_is_spurious_interrupt(int32 gsi) { @@ -456,6 +449,13 @@ acpi_set_interrupt_model(acpi_module_info* acpiModule, uint32 interruptModel) } +bool +ioapic_is_interrupt_available(int32 gsi) +{ + return find_ioapic(gsi) != NULL; +} + + void ioapic_map(kernel_args* args) { @@ -577,6 +577,14 @@ ioapic_init(kernel_args* args) 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(); diff --git a/src/system/kernel/arch/x86/msi.cpp b/src/system/kernel/arch/x86/msi.cpp index 134f68d415..2972de74c0 100644 --- a/src/system/kernel/arch/x86/msi.cpp +++ b/src/system/kernel/arch/x86/msi.cpp @@ -5,14 +5,17 @@ #include #include +#include #include #include #include -static bool sMSISupported = false; static const uint32 kVectorCount = 256 - ARCH_INTERRUPT_BASE; +static const uint8 kNumISAVectors = 16; + +static bool sMSISupported = false; static bool sAllocatedVectors[kVectorCount]; static mutex sMSIAllocationLock = MUTEX_INITIALIZER("msi_allocation"); @@ -25,13 +28,19 @@ msi_init() 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;