diff options
author | Yubo Miao <miaoyubo@huawei.com> | 2020-11-19 09:48:36 +0800 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2020-12-08 13:48:57 -0500 |
commit | 37d5c0a8ff812682c50865cd314348611319d872 (patch) | |
tree | 7dd6b33dce6a5a1a766641bd9a9177d61effda87 /hw/i386 | |
parent | 09fad16744480938543c0e39cfbaecbbd162c39b (diff) |
acpi: Extract crs build form acpi_build.c
Extract crs build form acpi_build.c, the function could also be used
to build the crs for pxbs for arm. The resources are composed by two parts:
1. The bar space of pci-bridge/pcie-root-ports
2. The resources needed by devices behind PXBs.
The base and limit of memory/io are obtained from the config via two APIs:
pci_bridge_get_base and pci_bridge_get_limit
Signed-off-by: Yubo Miao <miaoyubo@huawei.com>
Signed-off-by: Jiahui Cen <cenjiahui@huawei.com>
Message-Id: <20201119014841.7298-5-cenjiahui@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386')
-rw-r--r-- | hw/i386/acpi-build.c | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 1f5c211245..76e27f8fad 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -613,299 +613,6 @@ static Aml *build_prt(bool is_pci0_prt) return method; } -typedef struct CrsRangeEntry { - uint64_t base; - uint64_t limit; -} CrsRangeEntry; - -static void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit) -{ - CrsRangeEntry *entry; - - entry = g_malloc(sizeof(*entry)); - entry->base = base; - entry->limit = limit; - - g_ptr_array_add(ranges, entry); -} - -static void crs_range_free(gpointer data) -{ - CrsRangeEntry *entry = (CrsRangeEntry *)data; - g_free(entry); -} - -typedef struct CrsRangeSet { - GPtrArray *io_ranges; - GPtrArray *mem_ranges; - GPtrArray *mem_64bit_ranges; - } CrsRangeSet; - -static void crs_range_set_init(CrsRangeSet *range_set) -{ - range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free); - range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free); - range_set->mem_64bit_ranges = - g_ptr_array_new_with_free_func(crs_range_free); -} - -static void crs_range_set_free(CrsRangeSet *range_set) -{ - g_ptr_array_free(range_set->io_ranges, true); - g_ptr_array_free(range_set->mem_ranges, true); - g_ptr_array_free(range_set->mem_64bit_ranges, true); -} - -static gint crs_range_compare(gconstpointer a, gconstpointer b) -{ - CrsRangeEntry *entry_a = *(CrsRangeEntry **)a; - CrsRangeEntry *entry_b = *(CrsRangeEntry **)b; - - if (entry_a->base < entry_b->base) { - return -1; - } else if (entry_a->base > entry_b->base) { - return 1; - } else { - return 0; - } -} - -/* - * crs_replace_with_free_ranges - given the 'used' ranges within [start - end] - * interval, computes the 'free' ranges from the same interval. - * Example: If the input array is { [a1 - a2],[b1 - b2] }, the function - * will return { [base - a1], [a2 - b1], [b2 - limit] }. - */ -static void crs_replace_with_free_ranges(GPtrArray *ranges, - uint64_t start, uint64_t end) -{ - GPtrArray *free_ranges = g_ptr_array_new(); - uint64_t free_base = start; - int i; - - g_ptr_array_sort(ranges, crs_range_compare); - for (i = 0; i < ranges->len; i++) { - CrsRangeEntry *used = g_ptr_array_index(ranges, i); - - if (free_base < used->base) { - crs_range_insert(free_ranges, free_base, used->base - 1); - } - - free_base = used->limit + 1; - } - - if (free_base < end) { - crs_range_insert(free_ranges, free_base, end); - } - - g_ptr_array_set_size(ranges, 0); - for (i = 0; i < free_ranges->len; i++) { - g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i)); - } - - g_ptr_array_free(free_ranges, true); -} - -/* - * crs_range_merge - merges adjacent ranges in the given array. - * Array elements are deleted and replaced with the merged ranges. - */ -static void crs_range_merge(GPtrArray *range) -{ - GPtrArray *tmp = g_ptr_array_new_with_free_func(crs_range_free); - CrsRangeEntry *entry; - uint64_t range_base, range_limit; - int i; - - if (!range->len) { - return; - } - - g_ptr_array_sort(range, crs_range_compare); - - entry = g_ptr_array_index(range, 0); - range_base = entry->base; - range_limit = entry->limit; - for (i = 1; i < range->len; i++) { - entry = g_ptr_array_index(range, i); - if (entry->base - 1 == range_limit) { - range_limit = entry->limit; - } else { - crs_range_insert(tmp, range_base, range_limit); - range_base = entry->base; - range_limit = entry->limit; - } - } - crs_range_insert(tmp, range_base, range_limit); - - g_ptr_array_set_size(range, 0); - for (i = 0; i < tmp->len; i++) { - entry = g_ptr_array_index(tmp, i); - crs_range_insert(range, entry->base, entry->limit); - } - g_ptr_array_free(tmp, true); -} - -static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) -{ - Aml *crs = aml_resource_template(); - CrsRangeSet temp_range_set; - CrsRangeEntry *entry; - uint8_t max_bus = pci_bus_num(host->bus); - uint8_t type; - int devfn; - int i; - - crs_range_set_init(&temp_range_set); - for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) { - uint64_t range_base, range_limit; - PCIDevice *dev = host->bus->devices[devfn]; - - if (!dev) { - continue; - } - - for (i = 0; i < PCI_NUM_REGIONS; i++) { - PCIIORegion *r = &dev->io_regions[i]; - - range_base = r->addr; - range_limit = r->addr + r->size - 1; - - /* - * Work-around for old bioses - * that do not support multiple root buses - */ - if (!range_base || range_base > range_limit) { - continue; - } - - if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - crs_range_insert(temp_range_set.io_ranges, - range_base, range_limit); - } else { /* "memory" */ - uint64_t length = range_limit - range_base + 1; - if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { - crs_range_insert(temp_range_set.mem_ranges, range_base, - range_limit); - } else { - crs_range_insert(temp_range_set.mem_64bit_ranges, - range_base, range_limit); - } - } - } - - type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; - if (type == PCI_HEADER_TYPE_BRIDGE) { - uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS]; - if (subordinate > max_bus) { - max_bus = subordinate; - } - - range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO); - range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO); - - /* - * Work-around for old bioses - * that do not support multiple root buses - */ - if (range_base && range_base <= range_limit) { - crs_range_insert(temp_range_set.io_ranges, - range_base, range_limit); - } - - range_base = - pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); - range_limit = - pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); - - /* - * Work-around for old bioses - * that do not support multiple root buses - */ - if (range_base && range_base <= range_limit) { - uint64_t length = range_limit - range_base + 1; - if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { - crs_range_insert(temp_range_set.mem_ranges, - range_base, range_limit); - } else { - crs_range_insert(temp_range_set.mem_64bit_ranges, - range_base, range_limit); - } - } - - range_base = - pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); - range_limit = - pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); - - /* - * Work-around for old bioses - * that do not support multiple root buses - */ - if (range_base && range_base <= range_limit) { - uint64_t length = range_limit - range_base + 1; - if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { - crs_range_insert(temp_range_set.mem_ranges, - range_base, range_limit); - } else { - crs_range_insert(temp_range_set.mem_64bit_ranges, - range_base, range_limit); - } - } - } - } - - crs_range_merge(temp_range_set.io_ranges); - for (i = 0; i < temp_range_set.io_ranges->len; i++) { - entry = g_ptr_array_index(temp_range_set.io_ranges, i); - aml_append(crs, - aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED, - AML_POS_DECODE, AML_ENTIRE_RANGE, - 0, entry->base, entry->limit, 0, - entry->limit - entry->base + 1)); - crs_range_insert(range_set->io_ranges, entry->base, entry->limit); - } - - crs_range_merge(temp_range_set.mem_ranges); - for (i = 0; i < temp_range_set.mem_ranges->len; i++) { - entry = g_ptr_array_index(temp_range_set.mem_ranges, i); - assert(entry->limit <= UINT32_MAX && - (entry->limit - entry->base + 1) <= UINT32_MAX); - aml_append(crs, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, - AML_MAX_FIXED, AML_NON_CACHEABLE, - AML_READ_WRITE, - 0, entry->base, entry->limit, 0, - entry->limit - entry->base + 1)); - crs_range_insert(range_set->mem_ranges, entry->base, entry->limit); - } - - crs_range_merge(temp_range_set.mem_64bit_ranges); - for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) { - entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i); - aml_append(crs, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, - AML_MAX_FIXED, AML_NON_CACHEABLE, - AML_READ_WRITE, - 0, entry->base, entry->limit, 0, - entry->limit - entry->base + 1)); - crs_range_insert(range_set->mem_64bit_ranges, - entry->base, entry->limit); - } - - crs_range_set_free(&temp_range_set); - - aml_append(crs, - aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - 0, - pci_bus_num(host->bus), - max_bus, - 0, - max_bus - pci_bus_num(host->bus) + 1)); - - return crs; -} - static void build_hpet_aml(Aml *table) { Aml *crs; |