[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH RFC V2 04/17] hw/acpi: add _CRS method for extra
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [PATCH RFC V2 04/17] hw/acpi: add _CRS method for extra root busses |
Date: |
Mon, 16 Feb 2015 12:37:56 +0100 |
On Mon, Feb 16, 2015 at 11:07:06AM +0100, Igor Mammedov wrote:
> On Mon, 16 Feb 2015 11:54:04 +0200
> Marcel Apfelbaum <address@hidden> 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 <address@hidden>
> > ---
> > 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);
> > }
> >
- [Qemu-devel] [PATCH RFC V2 09/17] hw/pci: introduce TYPE_PCI_MAIN_HOST_BRIDGE interface, (continued)
- [Qemu-devel] [PATCH RFC V2 09/17] hw/pci: introduce TYPE_PCI_MAIN_HOST_BRIDGE interface, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 05/17] hw/acpi: remove from root bus 0 the crs resources used by other busses., Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 15/17] hw/pxb: add map_irq func, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 16/17] hw/pci_bus: add support for NUMA nodes, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 10/17] hw/pci: removed 'rootbus nr is 0' assumption from qmp_pci_query, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 03/17] hw/apci: add _PRT method for extra root busses, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 01/17] acpi: added needed acpi constructs, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 04/17] hw/acpi: add _CRS method for extra root busses, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 17/17] hw/pxb: add numa_node parameter, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 02/17] hw/acpi: add support for multiple root busses, Marcel Apfelbaum, 2015/02/16
- [Qemu-devel] [PATCH RFC V2 14/17] hw/pci: piix - suport multiple host bridges, Marcel Apfelbaum, 2015/02/16