On Mon, Feb 16, 2015 at 11:07:06AM +0100, Igor Mammedov wrote: > On Mon, 16 Feb 2015 11:54:04 +0200 > Marcel Apfelbaum <mar...@redhat.com> wrote: > > > Save the IO/mem/bus numbers ranges assigned to the extra root busses > > to be removed from the root bus 0 range. > Is it possible to make BIOS program extra buses and root bus 0 > in sane way so their resources won't intersect? > That way QEMU will be able to just read resources from root buses > and generate AML in the same manner for every root bus instead of > collect->exclude hack and special casing root bus 0.
Even if it is, I think it's cleaner not to assume specific guest behaviour. Since it's not a lot of code to handle arbitrary configurations, it's easier to just do it generically. > > > > Signed-off-by: Marcel Apfelbaum <mar...@redhat.com> > > --- > > hw/i386/acpi-build.c | 146 > > +++++++++++++++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 146 insertions(+) > > > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > > index ee1a50a..0822a20 100644 > > --- a/hw/i386/acpi-build.c > > +++ b/hw/i386/acpi-build.c > > @@ -719,6 +719,145 @@ static AcpiAml build_prt(void) > > return method; > > } > > > > +typedef struct PciRangeEntry { > > + QLIST_ENTRY(PciRangeEntry) entry; > > + int64_t base; > > + int64_t limit; > > +} PciRangeEntry; > > + > > +typedef QLIST_HEAD(PciRangeQ, PciRangeEntry) PciRangeQ; > > + > > +static void pci_range_insert(PciRangeQ *list, int64_t base, int64_t limit) > > { > > + PciRangeEntry *entry, *next, *e; > > + > > + if (!base) { > > + return; > > + } > > + > > + if (limit - base + 1 < 0x1000) > > + limit = base + 0x1000 - 1; > > + > > + e = g_malloc(sizeof(*entry)); > > + e->base = base; > > + e->limit = limit; > > + > > + if (QLIST_EMPTY(list)) { > > + QLIST_INSERT_HEAD(list, e, entry); > > + } else { > > + QLIST_FOREACH_SAFE(entry, list, entry, next) { > > + if (base < entry->base) { > > + QLIST_INSERT_BEFORE(entry, e, entry); > > + break; > > + } else if (!next) { > > + QLIST_INSERT_AFTER(entry, e, entry); > > + break; > > + } > > + } > > + } > > +} > > + > > +static void pci_range_list_free(PciRangeQ *list) > > +{ > > + PciRangeEntry *entry, *next; > > + > > + QLIST_FOREACH_SAFE(entry, list, entry, next) { > > + QLIST_REMOVE(entry, entry); > > + g_free(entry); > > + } > > +} > > + > > +static AcpiAml build_crs(PcPciInfo *pci, PciInfo *bus_info, > > + PciRangeQ *io_ranges, PciRangeQ *mem_ranges) > > +{ > > + PciDeviceInfoList *dev_list; > > + PciMemoryRange range; > > + AcpiAml crs; > > + uint8_t max_bus; > > + > > + crs = acpi_resource_template(); > > + max_bus = bus_info->bus; > > + > > + for (dev_list = bus_info->devices; dev_list; dev_list = > > dev_list->next) { > > + PciMemoryRegionList *region; > > + > > + for (region = dev_list->value->regions; region; region = > > region->next) { > > + range.base = region->value->address; > > + range.limit = region->value->address + region->value->size - 1; > > + > > + if (!strcmp(region->value->type, "io")) { > > + aml_append(&crs, > > + acpi_word_io(acpi_min_fixed, acpi_max_fixed, > > + acpi_pos_decode, acpi_entire_range, > > + 0x0000, > > + range.base, > > + range.limit, > > + 0x0000, > > + range.limit - range.base + 1)); > > + pci_range_insert(io_ranges, range.base, range.limit); > > + } else { /* "memory" */ > > + aml_append(&crs, > > + acpi_dword_memory(acpi_pos_decode, acpi_min_fixed, > > + acpi_max_fixed, acpi_non_cacheable, > > acpi_ReadWrite, > > + 0, > > + range.base, > > + range.limit, > > + 0, > > + range.limit - range.base + 1)); > > + pci_range_insert(mem_ranges, range.base, range.limit); > > + } > > + } > > + > > + if (dev_list->value->has_pci_bridge) { > > + PciBridgeInfo *bridge_info = dev_list->value->pci_bridge; > > + > > + if (bridge_info->bus.subordinate > max_bus) { > > + max_bus = bridge_info->bus.subordinate; > > + } > > + > > + range = *bridge_info->bus.io_range; > > + aml_append(&crs, > > + acpi_word_io(acpi_min_fixed, acpi_max_fixed, > > + acpi_pos_decode, acpi_entire_range, > > + 0x0000, > > + range.base, > > + range.limit, > > + 0x0000, > > + range.limit - range.base + 1)); > > + pci_range_insert(io_ranges, range.base, range.limit); > > + > > + range = *bridge_info->bus.memory_range; > > + aml_append(&crs, > > + acpi_dword_memory(acpi_pos_decode, acpi_min_fixed, > > + acpi_max_fixed, acpi_non_cacheable, acpi_ReadWrite, > > + 0, > > + range.base, > > + range.limit, > > + 0, > > + range.limit - range.base + 1)); > > + pci_range_insert(mem_ranges, range.base, range.limit); > > + > > + range = *bridge_info->bus.prefetchable_range; > > + aml_append(&crs, > > + acpi_dword_memory(acpi_pos_decode, acpi_min_fixed, > > + acpi_max_fixed, acpi_non_cacheable, acpi_ReadWrite, > > + 0, > > + range.base, > > + range.limit, > > + 0, > > + range.limit - range.base + 1)); > > + pci_range_insert(mem_ranges, range.base, range.limit); > > + } > > + } > > + > > + aml_append(&crs, > > + acpi_word_bus_number(acpi_min_fixed, acpi_max_fixed, > > + acpi_pos_decode, > > + 0x0000, bus_info->bus, max_bus, > > + 0x0000, max_bus - bus_info->bus + 1)); > > + > > + return crs; > > +} > > + > > static void > > build_ssdt(AcpiAml *table_aml, GArray *linker, > > AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc, > > @@ -729,6 +868,8 @@ build_ssdt(AcpiAml *table_aml, GArray *linker, > > unsigned acpi_cpus = guest_info->apic_id_limit; > > AcpiAml pkg, scope, dev, method, crs, field, ifctx, ssdt; > > int i; > > + PciRangeQ io_ranges = QLIST_HEAD_INITIALIZER(io_ranges); > > + PciRangeQ mem_ranges = QLIST_HEAD_INITIALIZER(mem_ranges); > > > > /* The current AML generator can cover the APIC ID range [0..255], > > * inclusive, for VCPU hotplug. */ > > @@ -764,9 +905,14 @@ build_ssdt(AcpiAml *table_aml, GArray *linker, > > aml_append(&dev, > > acpi_name_decl("_BBN", acpi_int((uint8_t)bus_info->bus))); > > aml_append(&dev, build_prt()); > > + crs = build_crs(pci, bus_info, &io_ranges, &mem_ranges); > > + aml_append(&dev, acpi_name_decl("_CRS", crs)); > > aml_append(&scope, dev); > > aml_append(&ssdt, scope); > > } > > + > > + pci_range_list_free(&io_ranges); > > + pci_range_list_free(&mem_ranges); > > qapi_free_PciInfoList(info_list); > > } > >