diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2020-09-24 10:53:36 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2020-10-15 11:21:43 +0200 |
commit | 90d8e56a1ee818f5f45b4dd84daaa13d80fff8e4 (patch) | |
tree | 438e944ed85c984e63a2c3b96c31de48ee398919 | |
parent | 118b792662dfcbd630c2224e844963549d4ebe92 (diff) | |
download | seabios-90d8e56a1ee818f5f45b4dd84daaa13d80fff8e4.tar.gz |
pci: add qemu gpex host bridge support.microvm
Find PCIe root using ACPI DSDT table.
Setup PCI bars.
initialize PCI devices.
Working:
- finds + drives xhci-pci / virtio-pci devices.
TODO / known issues:
- ioport setup is broken.
- bootorder needs fixing.
- 64bit mmio window not supported.
- irq routing not supported.
- pci config access in real mode is broken (not using mmconfig).
- this breaks pcibios support.
- which in turn breaks vgabios.
- fixable via temporary modeswitch to 32bit.
- which of course adds overhead.
Also:
- needed in the first place for microvm?
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r-- | src/fw/paravirt.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index fba4e52d..76070e18 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -198,6 +198,67 @@ static void msr_feature_control_setup(void) } void +gpex_setup(void) +{ + u16 pcie_eisaid = 0x0a08; + u16 ecam_eisaid = 0x0c02; + u16 link_eisaid = 0x0c0f; + struct acpi_device *pcie; + struct acpi_device *ecam; + struct acpi_device *link; + u64 min, max, irq; + + if (!hlist_empty(&PCIDevices)) { + dprintf(1, "%s: have pci devices, skipping\n", __func__); + return; + } + + pcie = acpi_dsdt_find_eisaid(NULL, pcie_eisaid); + if (!pcie) + return; + + for (ecam = acpi_dsdt_find_eisaid(NULL, ecam_eisaid); + ecam != NULL; + ecam = acpi_dsdt_find_eisaid(ecam, ecam_eisaid)) { + if (acpi_dsdt_is_parent(ecam, pcie)) + break; + } + if (!ecam) + return; + + if (acpi_dsdt_find_mem(ecam, &min, &max) < 0) + return; + dprintf(1, "%s: mmconfig: %llx -> %llx\n", __func__, min, max); + pci_enable_mmconfig(min, "gpex"); + + if (acpi_dsdt_find_io(pcie, &min, &max) < 0) + dprintf(1, "%s: no io window [ TODO ]\n", __func__); + else + dprintf(1, "%s: io: %llx -> %llx [ TODO ]\n", __func__, min, max); + + if (acpi_dsdt_find_mem(pcie, &pcimem_start, &pcimem_end) < 0) + return; + dprintf(1, "%s: mmio32: %llx -> %llx\n", __func__, pcimem_start, pcimem_end); + + dprintf(1, "%s: mmio64: [ TODO ]\n", __func__); + + for (link = acpi_dsdt_find_eisaid(NULL, link_eisaid); + link != NULL; + link = acpi_dsdt_find_eisaid(link, link_eisaid)) { + if (!acpi_dsdt_is_parent(link, pcie)) + continue; + if (acpi_dsdt_find_irq(link, &irq) < 0) + continue; + dprintf(1, "%s: %s -> uid %lld, irq %lld [ TODO ]\n", __func__, + acpi_dsdt_name(link), acpi_dsdt_uid(link), irq); + } + + dprintf(1, "=== PCI device probing ===\n"); + pci_probe_devices(); + pci_setup_alloc(); +} + +void qemu_platform_setup(void) { if (!CONFIG_QEMU) @@ -240,6 +301,7 @@ qemu_platform_setup(void) if (RsdpAddr) { acpi_dsdt_parse(); + gpex_setup(); virtio_mmio_setup_acpi(); return; } |