From e223e8e94b8918a0ff3aab12a09e20e7f7c17d6e Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 29 May 2023 15:02:19 -0400 Subject: [PATCH] kernel/x86: Initialize IO-APIC only after PCI enumeration is complete. Before the PCI refactor, PCI initialization/enumeration occurred immediately after the PCI module was loaded, and so by the time we got to IOAPIC initialization, it was already complete. After the refactor, PCI enumeration is deferred until slightly later, and so we would try to initialize IO-APICs without knowing PCI information. This would fail, as read_irq_routing_table needs to have that available. Hopefully fixes #18425, #18393, #18398. Change-Id: I1e4b06367da26eeb10085a1c6322ed39885b632b Reviewed-on: https://review.haiku-os.org/c/haiku/+/6476 Reviewed-by: X512 Reviewed-by: waddlesplash --- headers/private/kernel/arch/x86/ioapic.h | 3 +- .../busses/pci/x86/X86PCIController.cpp | 33 ++++++------------- .../kernel/busses/pci/x86/X86PCIController.h | 8 +---- src/system/kernel/arch/x86/arch_int.cpp | 2 +- src/system/kernel/arch/x86/ioapic.cpp | 22 +++++++++---- 5 files changed, 30 insertions(+), 38 deletions(-) diff --git a/headers/private/kernel/arch/x86/ioapic.h b/headers/private/kernel/arch/x86/ioapic.h index a48e215ea7..d08ebf8ad4 100644 --- a/headers/private/kernel/arch/x86/ioapic.h +++ b/headers/private/kernel/arch/x86/ioapic.h @@ -11,6 +11,7 @@ struct kernel_args; bool ioapic_is_interrupt_available(int32 gsi); -void ioapic_init(kernel_args* args); +void ioapic_preinit(kernel_args* args); +void ioapic_init(); #endif // _KERNEL_ARCH_x86_IOAPIC_H diff --git a/src/add-ons/kernel/busses/pci/x86/X86PCIController.cpp b/src/add-ons/kernel/busses/pci/x86/X86PCIController.cpp index 999ba37a6d..0941d15d23 100644 --- a/src/add-ons/kernel/busses/pci/x86/X86PCIController.cpp +++ b/src/add-ons/kernel/busses/pci/x86/X86PCIController.cpp @@ -6,6 +6,8 @@ #include "X86PCIController.h" +#include + #include #include @@ -152,11 +154,18 @@ X86PCIController::WriteIrq(uint8 bus, uint8 device, uint8 function, status_t X86PCIController::GetRange(uint32 index, pci_resource_range* range) { - return B_BAD_INDEX; } +status_t +X86PCIController::Finalize() +{ + ioapic_init(); + return B_OK; +} + + //#pragma mark - X86PCIControllerMeth1 @@ -238,13 +247,6 @@ status_t X86PCIControllerMeth1::GetMaxBusDevices(int32& count) } -status_t -X86PCIControllerMeth1::Finalize() -{ - return B_OK; -} - - //#pragma mark - X86PCIControllerMeth2 @@ -332,13 +334,6 @@ status_t X86PCIControllerMeth2::GetMaxBusDevices(int32& count) } -status_t -X86PCIControllerMeth2::Finalize() -{ - return B_OK; -} - - //#pragma mark - X86PCIControllerMethPcie @@ -410,11 +405,3 @@ X86PCIControllerMethPcie::GetRange(uint32 index, pci_resource_range* range) { return fECAMPCIController.GetRange(index, range); } - - -status_t -X86PCIControllerMethPcie::Finalize() -{ - // No need to call fECAMPCIController.Finalize(): IRQ routing is handled by IOAPIC on x86. - return B_OK; -} diff --git a/src/add-ons/kernel/busses/pci/x86/X86PCIController.h b/src/add-ons/kernel/busses/pci/x86/X86PCIController.h index b9d06a03b3..d6a80a73c3 100644 --- a/src/add-ons/kernel/busses/pci/x86/X86PCIController.h +++ b/src/add-ons/kernel/busses/pci/x86/X86PCIController.h @@ -41,7 +41,7 @@ public: virtual status_t GetRange(uint32 index, pci_resource_range* range); - virtual status_t Finalize() = 0; + virtual status_t Finalize() final; status_t ReadIrq( uint8 bus, uint8 device, uint8 function, @@ -78,8 +78,6 @@ public: uint16 offset, uint8 size, uint32 value) override; status_t GetMaxBusDevices(int32& count) override; - - status_t Finalize() override; }; @@ -98,8 +96,6 @@ public: uint16 offset, uint8 size, uint32 value) final; status_t GetMaxBusDevices(int32& count) final; - - status_t Finalize() final; }; @@ -121,8 +117,6 @@ public: status_t GetRange(uint32 index, pci_resource_range* range) final; - status_t Finalize() final; - private: ECAMPCIControllerACPI fECAMPCIController; }; diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 025d431dd6..9281a5e71a 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -467,7 +467,7 @@ status_t arch_int_init_io(kernel_args* args) { msi_init(args); - ioapic_init(args); + ioapic_preinit(args); return B_OK; } diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index fff4fa7d63..bfba9c0eb1 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -108,6 +108,7 @@ struct ioapic { }; +static int32 sIOAPICPhys = 0; static ioapic* sIOAPICs = NULL; static int32 sSourceOverrides[ISA_INTERRUPT_COUNT]; @@ -670,7 +671,16 @@ ioapic_is_interrupt_available(int32 gsi) void -ioapic_init(kernel_args* args) +ioapic_preinit(kernel_args* args) +{ + sIOAPICPhys = args->arch_args.ioapic_phys; + + // The real IO-APIC initialization occurs after PCI initialization. +} + + +void +ioapic_init() { static const interrupt_controller ioapicController = { "82093AA IOAPIC", @@ -683,10 +693,10 @@ ioapic_init(kernel_args* args) &ioapic_assign_interrupt_to_cpu, }; - if (args->arch_args.apic == NULL) + if (!apic_available()) return; - if (args->arch_args.ioapic_phys == 0) { + if (sIOAPICPhys == 0) { dprintf("no io-apics available, not using io-apics for interrupt " "routing\n"); return; @@ -698,12 +708,12 @@ ioapic_init(kernel_args* args) return; } - // load acpi module + // load ACPI module status_t status; acpi_module_info* acpiModule; status = get_module(B_ACPI_MODULE_NAME, (module_info**)&acpiModule); if (status != B_OK) { - dprintf("acpi module not available, not configuring io-apics\n"); + dprintf("ACPI module not available, not configuring io-apics\n"); return; } BPrivate::CObjectDeleter @@ -743,7 +753,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]; + uint8 targetAPIC = x86_get_cpu_apic_id(0); struct ioapic* current = sIOAPICs; while (current != NULL) {