Message ID | 1463340214-8721-5-git-send-email-marcel@redhat.com |
---|---|
State | New |
Headers | show |
On Sun, 15 May 2016 22:23:34 +0300 Marcel Apfelbaum <marcel@redhat.com> wrote: > In build_crs(), the calculation and merging of the ranges already happens > in 64-bit, but the entry boundaries are silently truncated to 32-bit in the > call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges separately. > This fixes 64-bit BARs behind PXBs. > > Signed-off-by: Marcel Apfelbaum <marcel@redhat.com> > --- > hw/i386/acpi-build.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 44 insertions(+), 9 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index 78f25ef..aaf4a34 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -739,18 +739,22 @@ static void crs_range_free(gpointer data) > 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) > @@ -908,8 +912,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > * that do not support multiple root buses > */ > if (range_base && range_base <= range_limit) { > - crs_range_insert(temp_range_set.mem_ranges, > - 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 = > @@ -922,8 +932,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > * that do not support multiple root buses > */ > if (range_base && range_base <= range_limit) { > - crs_range_insert(temp_range_set.mem_ranges, > - 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); > + } > } > } > } > @@ -951,6 +967,19 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > 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); > + } instead of adding another field, wouldn't following be a simpler approach: for (i = 0; i < temp_range_set.mem_ranges->len; i++) { entry = g_ptr_array_index(temp_range_set.mem_ranges, i); if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { aml_dword_memory(...); } else { aml_qword_memory(...); } > + > crs_range_set_free(&temp_range_set); > > aml_append(crs, > @@ -2182,11 +2211,17 @@ build_dsdt(GArray *table_data, GArray *linker, > } > > if (pci->w64.begin) { > - aml_append(crs, > - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, > - AML_CACHEABLE, AML_READ_WRITE, > - 0, pci->w64.begin, pci->w64.end - 1, 0, > - pci->w64.end - pci->w64.begin)); > + crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, > + pci->w64.begin, pci->w64.end - 1); > + for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { > + entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); > + aml_append(crs, > + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, > + AML_MAX_FIXED, > + AML_CACHEABLE, AML_READ_WRITE, > + 0, entry->base, entry->limit, > + 0, entry->limit - entry->base + 1)); > + } > } > > if (misc->tpm_version != TPM_VERSION_UNSPEC) {
On 05/16/2016 02:19 PM, Igor Mammedov wrote: > On Sun, 15 May 2016 22:23:34 +0300 > Marcel Apfelbaum <marcel@redhat.com> wrote: > >> In build_crs(), the calculation and merging of the ranges already happens >> in 64-bit, but the entry boundaries are silently truncated to 32-bit in the >> call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges separately. >> This fixes 64-bit BARs behind PXBs. >> >> Signed-off-by: Marcel Apfelbaum <marcel@redhat.com> >> --- >> hw/i386/acpi-build.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- >> 1 file changed, 44 insertions(+), 9 deletions(-) >> >> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c >> index 78f25ef..aaf4a34 100644 >> --- a/hw/i386/acpi-build.c >> +++ b/hw/i386/acpi-build.c >> @@ -739,18 +739,22 @@ static void crs_range_free(gpointer data) >> 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) >> @@ -908,8 +912,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> * that do not support multiple root buses >> */ >> if (range_base && range_base <= range_limit) { >> - crs_range_insert(temp_range_set.mem_ranges, >> - 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 = >> @@ -922,8 +932,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> * that do not support multiple root buses >> */ >> if (range_base && range_base <= range_limit) { >> - crs_range_insert(temp_range_set.mem_ranges, >> - 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); >> + } >> } >> } >> } >> @@ -951,6 +967,19 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> 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); >> + } > instead of adding another field, wouldn't following be a simpler approach: > This would be enough if we only need to create the ACPI table entries. However we need the mem_64bit_ranges field (I assume you are talking about it) for "accounting": We need to extract 'free' ranges given the used one for MMIO and 64-BIT MMIO separately, for each of them we will supply a different PCI Window. The approach I chose is easier to understand IMO: We have IO, MMIO and 64-MMIO ranges. For each of them we have a different window, but we apply the same algorithm. Unifying MMIO and 64-MMIO will not give us a real advantage, as the code we suppress for building the ACPI tables will become twice as long when we do the 'accounting'. (see: crs_replace_with_free_ranges) Thanks, Marcel > for (i = 0; i < temp_range_set.mem_ranges->len; i++) { > entry = g_ptr_array_index(temp_range_set.mem_ranges, i); > if (range_limit <= UINT32_MAX && length <= UINT32_MAX) { > aml_dword_memory(...); > } else { > aml_qword_memory(...); > } > > >> + >> crs_range_set_free(&temp_range_set); >> >> aml_append(crs, >> @@ -2182,11 +2211,17 @@ build_dsdt(GArray *table_data, GArray *linker, >> } >> >> if (pci->w64.begin) { >> - aml_append(crs, >> - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, >> - AML_CACHEABLE, AML_READ_WRITE, >> - 0, pci->w64.begin, pci->w64.end - 1, 0, >> - pci->w64.end - pci->w64.begin)); >> + crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, >> + pci->w64.begin, pci->w64.end - 1); >> + for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { >> + entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); >> + aml_append(crs, >> + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, >> + AML_MAX_FIXED, >> + AML_CACHEABLE, AML_READ_WRITE, >> + 0, entry->base, entry->limit, >> + 0, entry->limit - entry->base + 1)); >> + } >> } >> >> if (misc->tpm_version != TPM_VERSION_UNSPEC) { >
On Sun, May 15, 2016 at 10:23:34PM +0300, Marcel Apfelbaum wrote: > In build_crs(), the calculation and merging of the ranges already happens > in 64-bit, but the entry boundaries are silently truncated to 32-bit in the > call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges separately. > This fixes 64-bit BARs behind PXBs. > > Signed-off-by: Marcel Apfelbaum <marcel@redhat.com> Can this be based on master? Looks like bugfix useful in stable. > --- > hw/i386/acpi-build.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 44 insertions(+), 9 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index 78f25ef..aaf4a34 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -739,18 +739,22 @@ static void crs_range_free(gpointer data) > 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) > @@ -908,8 +912,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > * that do not support multiple root buses > */ > if (range_base && range_base <= range_limit) { > - crs_range_insert(temp_range_set.mem_ranges, > - 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 = > @@ -922,8 +932,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > * that do not support multiple root buses > */ > if (range_base && range_base <= range_limit) { > - crs_range_insert(temp_range_set.mem_ranges, > - 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); > + } > } > } > } > @@ -951,6 +967,19 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) > 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, > @@ -2182,11 +2211,17 @@ build_dsdt(GArray *table_data, GArray *linker, > } > > if (pci->w64.begin) { > - aml_append(crs, > - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, > - AML_CACHEABLE, AML_READ_WRITE, > - 0, pci->w64.begin, pci->w64.end - 1, 0, > - pci->w64.end - pci->w64.begin)); > + crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, > + pci->w64.begin, pci->w64.end - 1); > + for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { > + entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); > + aml_append(crs, > + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, > + AML_MAX_FIXED, > + AML_CACHEABLE, AML_READ_WRITE, > + 0, entry->base, entry->limit, > + 0, entry->limit - entry->base + 1)); > + } > } > > if (misc->tpm_version != TPM_VERSION_UNSPEC) { > -- > 2.4.3
On 05/18/2016 05:16 PM, Michael S. Tsirkin wrote: > On Sun, May 15, 2016 at 10:23:34PM +0300, Marcel Apfelbaum wrote: >> In build_crs(), the calculation and merging of the ranges already happens >> in 64-bit, but the entry boundaries are silently truncated to 32-bit in the >> call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges separately. >> This fixes 64-bit BARs behind PXBs. >> >> Signed-off-by: Marcel Apfelbaum <marcel@redhat.com> > > Can this be based on master? Looks like bugfix useful in > stable. You need patch 3/4 and you should be able to apply this on master. Also I did not test it without a valid 64bit MMIO range. Let me please test it and switch the patches in the series so it will start with 3/4 and 4/4. Thanks, Marel > >> --- >> hw/i386/acpi-build.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- >> 1 file changed, 44 insertions(+), 9 deletions(-) >> >> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c >> index 78f25ef..aaf4a34 100644 >> --- a/hw/i386/acpi-build.c >> +++ b/hw/i386/acpi-build.c >> @@ -739,18 +739,22 @@ static void crs_range_free(gpointer data) >> 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) >> @@ -908,8 +912,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> * that do not support multiple root buses >> */ >> if (range_base && range_base <= range_limit) { >> - crs_range_insert(temp_range_set.mem_ranges, >> - 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 = >> @@ -922,8 +932,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> * that do not support multiple root buses >> */ >> if (range_base && range_base <= range_limit) { >> - crs_range_insert(temp_range_set.mem_ranges, >> - 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); >> + } >> } >> } >> } >> @@ -951,6 +967,19 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) >> 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, >> @@ -2182,11 +2211,17 @@ build_dsdt(GArray *table_data, GArray *linker, >> } >> >> if (pci->w64.begin) { >> - aml_append(crs, >> - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, >> - AML_CACHEABLE, AML_READ_WRITE, >> - 0, pci->w64.begin, pci->w64.end - 1, 0, >> - pci->w64.end - pci->w64.begin)); >> + crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, >> + pci->w64.begin, pci->w64.end - 1); >> + for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { >> + entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); >> + aml_append(crs, >> + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, >> + AML_MAX_FIXED, >> + AML_CACHEABLE, AML_READ_WRITE, >> + 0, entry->base, entry->limit, >> + 0, entry->limit - entry->base + 1)); >> + } >> } >> >> if (misc->tpm_version != TPM_VERSION_UNSPEC) { >> -- >> 2.4.3
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 78f25ef..aaf4a34 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -739,18 +739,22 @@ static void crs_range_free(gpointer data) 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) @@ -908,8 +912,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) * that do not support multiple root buses */ if (range_base && range_base <= range_limit) { - crs_range_insert(temp_range_set.mem_ranges, - 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 = @@ -922,8 +932,14 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) * that do not support multiple root buses */ if (range_base && range_base <= range_limit) { - crs_range_insert(temp_range_set.mem_ranges, - 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); + } } } } @@ -951,6 +967,19 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set) 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, @@ -2182,11 +2211,17 @@ build_dsdt(GArray *table_data, GArray *linker, } if (pci->w64.begin) { - aml_append(crs, - aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_CACHEABLE, AML_READ_WRITE, - 0, pci->w64.begin, pci->w64.end - 1, 0, - pci->w64.end - pci->w64.begin)); + crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, + pci->w64.begin, pci->w64.end - 1); + for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { + entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); + aml_append(crs, + aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, + AML_MAX_FIXED, + AML_CACHEABLE, AML_READ_WRITE, + 0, entry->base, entry->limit, + 0, entry->limit - entry->base + 1)); + } } if (misc->tpm_version != TPM_VERSION_UNSPEC) {
In build_crs(), the calculation and merging of the ranges already happens in 64-bit, but the entry boundaries are silently truncated to 32-bit in the call to aml_dword_memory(). Fix it by handling the 64-bit MMIO ranges separately. This fixes 64-bit BARs behind PXBs. Signed-off-by: Marcel Apfelbaum <marcel@redhat.com> --- hw/i386/acpi-build.c | 53 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 9 deletions(-)