[SeaBIOS] [Qemu-devel] [PATCH RFC V2 04/17] hw/acpi: add _CRS method for extra root busses

Michael S. Tsirkin mst at redhat.com
Mon Feb 16 12:37:56 CET 2015


On Mon, Feb 16, 2015 at 11:07:06AM +0100, Igor Mammedov wrote:
> On Mon, 16 Feb 2015 11:54:04 +0200
> Marcel Apfelbaum <marcel at 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 <marcel at 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);
> >      }
> >  



More information about the SeaBIOS mailing list