Kernel/PCI: Consider ACPI MCFG existence in IO probe test

We should aim to reliably determine if PCI hardware exists or not, and
we should consider the ACPI MCFG table in that test. Although it is
unusual to see an hardware setup where the PCI host bridge does not
respond to x86 IO instructions, it is expected to happen at least on the
QEMU microvm machine type as the host bridge only responds to memory
mapped IO requests. Therefore, we first test if ACPI is enabled, and we
try to use it to fetch the MCFG table. Later on we could also add FDT
parsing as part of the PCI IO test which would be useful for the QEMU
microvm machine type.
This commit is contained in:
Liav A 2022-09-17 05:59:29 +03:00 committed by Linus Groh
parent 02a980ee54
commit b28202e356
Notes: sideshowbarker 2024-07-17 07:31:31 +09:00

View file

@ -38,17 +38,24 @@ UNMAP_AFTER_INIT static PCIAccessLevel detect_optimal_access_type()
UNMAP_AFTER_INIT void initialize()
{
g_pci_access_io_probe_failed = !test_pci_io();
g_pci_access_is_disabled_from_commandline = kernel_command_line().is_pci_disabled();
Optional<PhysicalAddress> possible_mcfg;
// FIXME: There are other arch-specific methods to find the memory range
// for accessing the PCI configuration space.
// For example, the QEMU microvm machine type might expose an FDT so we could
// parse it to find a PCI host bridge.
if (ACPI::is_enabled()) {
possible_mcfg = ACPI::Parser::the()->find_table("MCFG"sv);
g_pci_access_io_probe_failed = (!test_pci_io()) && (!possible_mcfg.has_value());
} else {
g_pci_access_io_probe_failed = !test_pci_io();
}
if (g_pci_access_is_disabled_from_commandline || g_pci_access_io_probe_failed)
return;
switch (detect_optimal_access_type()) {
case PCIAccessLevel::MemoryAddressing: {
// FIXME: There are other arch-specific methods to find the memory range
// for accessing the PCI configuration space.
auto mcfg = ACPI::Parser::the()->find_table("MCFG"sv);
VERIFY(mcfg.has_value());
auto success = Access::initialize_for_multiple_pci_domains(mcfg.value());
VERIFY(possible_mcfg.has_value());
auto success = Access::initialize_for_multiple_pci_domains(possible_mcfg.value());
VERIFY(success);
break;
}