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 <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Augustin Cavalier
2023-05-29 19:44:32 +00:00
committed by waddlesplash
parent b256fa4adf
commit e223e8e94b
5 changed files with 30 additions and 38 deletions
+2 -1
View File
@@ -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
@@ -6,6 +6,8 @@
#include "X86PCIController.h"
#include <ioapic.h>
#include <AutoDeleterDrivers.h>
#include <util/AutoLock.h>
@@ -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;
}
@@ -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;
};
+1 -1
View File
@@ -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;
}
+16 -6
View File
@@ -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<const char, status_t, put_module>
@@ -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) {