A hypervisor may want to perform PCI resource allocation (bus numbers, io and mmio ranges) and program the resulting values into the devices itself rather than delegate this to the firmware.
Introduce a new flag in fw_cfg, "etc/pci-noalloc", to instruct the firmware to skip the resource allocation phase and use whatever is already programmed in the devices.
Abhimanyu Saini (2): fw/pciinit: factor out pci resource allocation pci: skip pci resource allocation if instructed by platform
src/fw/pciinit.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-)
Factor out PCI resource allocation code to a separate function. This makes it easier to follow, and paves the way to support skipping this step when instructed by the platform (in a followup patch).
While at it, fix the leak of *busses in case pci_bios_check_devices fails.
Signed-off-by: Abhimanyu Saini sainiabr@amazon.de --- src/fw/pciinit.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index b3e359d7..334fd30c 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -1174,6 +1174,26 @@ static void pci_bios_map_devices(struct pci_bus *busses) } }
+static void pci_allocate_resources(void) +{ + struct pci_bus *busses; + + dprintf(1, "=== PCI new allocation pass #1 ===\n"); + busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1)); + if (!busses) { + warn_noalloc(); + return; + } + memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1)); + if (pci_bios_check_devices(busses)) + goto cleanup; + + dprintf(1, "=== PCI new allocation pass #2 ===\n"); + pci_bios_map_devices(busses); + +cleanup: + free(busses); +}
/**************************************************************** * Main setup code @@ -1217,22 +1237,9 @@ pci_setup(void) pcimem_start = RamSize; pci_bios_init_platform();
- dprintf(1, "=== PCI new allocation pass #1 ===\n"); - struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1)); - if (!busses) { - warn_noalloc(); - return; - } - memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1)); - if (pci_bios_check_devices(busses)) - return; - - dprintf(1, "=== PCI new allocation pass #2 ===\n"); - pci_bios_map_devices(busses); + pci_allocate_resources();
pci_bios_init_devices();
- free(busses); - pci_enable_default_vga(); }
A hypervisor may want to perform PCI resource allocation (bus numbers, io and mmio ranges) and program the resulting values into the devices itself rather than delegate this to the firmware.
One possible reason for doing so is more control for the hypervisor over assigned ranges. This will also be faster than entering the guest and then trapping on config space accesses.
Introduce a new flag in fw_cfg, "etc/pci-noalloc", to instruct the firmware to skip the resource allocation phase and use whatever is already programmed in the devices.
Signed-off-by: Abhimanyu Saini sainiabr@amazon.de --- src/fw/pciinit.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 334fd30c..e1c05410 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -1176,8 +1176,13 @@ static void pci_bios_map_devices(struct pci_bus *busses)
static void pci_allocate_resources(void) { + u64 noalloc; struct pci_bus *busses;
+ noalloc = romfile_loadint("etc/pci-noalloc", 0); + if (noalloc) + return; + dprintf(1, "=== PCI new allocation pass #1 ===\n"); busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1)); if (!busses) {