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:
committed by
waddlesplash
parent
b256fa4adf
commit
e223e8e94b
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user