From b28202e35612e62b9b7a328273770477e25a0f52 Mon Sep 17 00:00:00 2001 From: Liav A Date: Sat, 17 Sep 2022 05:59:29 +0300 Subject: [PATCH] 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. --- Kernel/Arch/x86/PCI/Initializer.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Kernel/Arch/x86/PCI/Initializer.cpp b/Kernel/Arch/x86/PCI/Initializer.cpp index 0b7a796e41..f6158e22a4 100644 --- a/Kernel/Arch/x86/PCI/Initializer.cpp +++ b/Kernel/Arch/x86/PCI/Initializer.cpp @@ -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 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; }