[PATCH v8 5/8] acpi: Align the size to 128k

2020-05-20 Thread Yubo Miao
If table size is changed between virt_acpi_build and
virt_acpi_build_update, the table size would not be updated to
UEFI, therefore, just align the size to 128kb, which is enough
and same with x86. It would warn if 64k is not enough and the
align size should be updated.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 14fcabd197..d0616738e5 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -57,6 +57,8 @@
 #include "hw/pci/pcie_host.h"
 #define ARM_SPI_BASE 32
 
+#define ACPI_BUILD_TABLE_SIZE 0x2
+
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
 uint16_t i;
@@ -885,6 +887,15 @@ struct AcpiBuildState {
 bool patched;
 } AcpiBuildState;
 
+static void acpi_align_size(GArray *blob, unsigned align)
+{
+/*
+ * Align size to multiple of given size. This reduces the chance
+ * we need to change size in the future (breaking cross version migration).
+ */
+g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
+}
+
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
@@ -967,6 +978,20 @@ void virt_acpi_build(VirtMachineState *vms, 
AcpiBuildTables *tables)
 build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
 }
 
+/*
+ * The align size is 128, warn if 64k is not enough therefore
+ * the align size could be resized.
+ */
+if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
+warn_report("ACPI table size %u exceeds %d bytes,"
+" migration may not work",
+tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
+error_printf("Try removing CPUs, NUMA nodes, memory slots"
+ " or PCI bridges.");
+}
+acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
+
+
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
 }
-- 
2.19.1





[PATCH v8 4/8] acpi: Refactor the source of host bridge and build tables for pxb

2020-05-20 Thread Yubo Miao
The resources of pxbs are obtained by crs_build and the resources
used by pxbs would be moved from the resources defined for host-bridge.

The resources for pxb are composed of following two parts:
1. The bar space of the pci-bridge/pcie-root-port behined it
2. The config space of devices behind it.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 127 +--
 1 file changed, 110 insertions(+), 17 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 24ebc06a9f..14fcabd197 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -51,6 +51,10 @@
 #include "migration/vmstate.h"
 #include "hw/acpi/ghes.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pcie_host.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -268,19 +272,80 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+int i;
+Aml *method, *crs, *dev_pxb;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+CrsRangeEntry *entry;
+CrsRangeSet crs_range_set;
+
+crs_range_set_init(&crs_range_set);
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
 
 Aml *dev = aml_device("%s", "PCI0");
+PCIHostState *s = PCI_GET_PCIE_HOST_STATE;
+
+PCIBus *bus = s->bus;
+/* start to construct the tables for pxb */
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+/*
+ * 0 - (nr_pcie_buses - 1) is the bus range for the main
+ * host-bridge and it equals the MIN of the
+ * busNr defined for pxb-pcie.
+ */
+if (bus_num < nr_pcie_buses) {
+nr_pcie_buses = bus_num;
+}
+
+dev_pxb = aml_device("PC%.02X", bus_num);
+aml_append(dev_pxb, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev_pxb, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev_pxb, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev_pxb, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev_pxb, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev_pxb, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev_pxb, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev_pxb,
+   aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev_pxb, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev_pxb, scope, irq);
+
+/*
+ * Resources defined for PXBs are composed by the folling parts:
+ * 1. The resources the pci-brige/pcie-root-port need.
+ * 2. The resources the devices behind pxb need.
+ */
+crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+aml_append(dev_pxb, aml_name_decl("_CRS", crs));
+
+acpi_dsdt_add_pci_osc(dev_pxb, scope);
+
+aml_append(scope, dev_pxb);
+
+}
+}
+
+/* tables for the main */
 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
 aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
 aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
@@ -301,25 +366,51 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
 0x, 0x, nr_pcie_buses - 1, 0x,
 nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
-   

[PATCH v8 6/8] unit-test: The files changed.

2020-05-20 Thread Yubo Miao
The unit-test is seperated into three patches:
1. The files changed and list in bios-tables-test-allowed-diff.h
2. The unit-test
3. The binary file and clear bios-tables-test-allowed-diff.h

The ASL diff would also be listed.
Sice there are 1000+lines diff, some changes would be omitted.

  * Original Table Header:
  * Signature"DSDT"
- * Length   0x14BB (5307)
+ * Length   0x1E7A (7802)
  * Revision 0x02
- * Checksum 0xD1
+ * Checksum 0x57
  * OEM ID   "BOCHS "
  * OEM Table ID "BXPCDSDT"
  * OEM Revision 0x0001 (1)

+Device (PC80)
+{
+Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+Name (_ADR, Zero)  // _ADR: Address
+Name (_CCA, One)  // _CCA: Cache Coherency Attribute
+Name (_SEG, Zero)  // _SEG: PCI Segment
+Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
+Name (_UID, 0x80)  // _UID: Unique ID
+Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
+Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
+{
+Package (0x04)
+{
+0x,
+Zero,
+GSI0,
+Zero
+},
+

Packages are omitted.

+Package (0x04)
+{
+0x001F,
+0x03,
+GSI2,
+Zero
+}
+})
+Device (GSI0)
+{
+Name (_HID, "PNP0C0F" /* PCI Interrupt Link Device */)  // 
_HID: Hardware ID
+Name (_UID, Zero)  // _UID: Unique ID
+Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Method (_SRS, 1, NotSerialized)  // _SRS: Set Resource Settings
+{
+}
+}

GSI1,2,3 are omitted.

+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
+{
+WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+0x, // Granularity
+0x0080, // Range Minimum
+0x0080, // Range Maximum
+0x, // Translation Offset
+0x0001, // Length
+,, )
+})
+Name (SUPP, Zero)
+Name (CTRL, Zero)
+Method (_OSC, 4, NotSerialized)  // _OSC: Operating System 
Capabilities
+{
+CreateDWordField (Arg3, Zero, CDW1)
+If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") 
/* PCI Host Bridge Device */))
+{
+CreateDWordField (Arg3, 0x04, CDW2)
+CreateDWordField (Arg3, 0x08, CDW3)
+SUPP = CDW2 /* \_SB_.PC80._OSC.CDW2 */
+CTRL = CDW3 /* \_SB_.PC80._OSC.CDW3 */
+CTRL &= 0x1F
+If ((Arg1 != One))
+{
+CDW1 |= 0x08
+}
+
+If ((CDW3 != CTRL))
+{
+CDW1 |= 0x10
+}
+
+CDW3 = CTRL /* \_SB_.PC80.CTRL */
+Return (Arg3)
+}
+Else
+{
+CDW1 |= 0x04
+Return (Arg3)
+}
+}

DSM is are omitted

 Device (PCI0)
 {
 Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
PosDecode,
 0x, // Granularity
 0x, // Range Minimum
-0x00FF, // Range Maximum
+0x007F, // Range Maximum
 0x, // Translation Offset
-0x0100, // Length
+0x0080, // Length

Signed-off-by: Yubo Miao 
---

[PATCH v8 3/8] acpi: Extract crs build form acpi_build.c

2020-05-20 Thread Yubo Miao
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 
---
 hw/acpi/aml-build.c | 275 ++
 hw/i386/acpi-build.c| 285 
 include/hw/acpi/aml-build.h |  25 
 3 files changed, 300 insertions(+), 285 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 3681ec6e3d..5802597f8a 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -26,6 +26,9 @@
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
 #include "hw/boards.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -54,6 +57,125 @@ static void build_append_array(GArray *array, GArray *val)
 
 #define ACPI_NAMESEG_LEN 4
 
+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);
+}
+
+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);
+}
+
+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] }.
+ */
+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);
+}
+
+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 void
 build_append_nameseg(GArray *array, const char *seg)
 {
@@ -1877,6 +1999,159 @@ build_hdr:
  "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
 }
 
+Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
+{
+Aml *crs = 

[PATCH v8 8/8] unit-test: Add the binary file and clear diff.h

2020-05-20 Thread Yubo Miao
Add the binary file DSDT.pxb and clear bios-tables-test-allowed-diff.h

Signed-off-by: Yubo Miao 
---
 tests/data/acpi/virt/DSDT.pxb   | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 -
 2 files changed, 1 deletion(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb
new file mode 100644
index 
..d5f0533a02d62bc2ae2db9b9de9484e5c06652fe
GIT binary patch
literal 7802
zcmeI1%WoT16o;=LiS6+tw&OgUms2Pe&&rRcNlRN|kDbINPK+mQkW$GN2t>&y5*4DY
z5GE1@x}%ZUunAHY{255B*s){5x*Prhb`0mvok@O&o()@MN3!S4-1E)-#wYff>!#D(
zdAOidc(<`_Z#avMce{3z_Jx#EdRxC{zj_wB({~#Ey~7#1TrS7^8|`MgZg<-hEUS3`
zR=cV84zJqVo#0rnvr#TrD*mx}-|jiN8EfisLTO+^WtIANRE0w4D0)D-m9e1W1K-`?I3==%fJX5q(*jFqgf=xI;=+i!j2&*$h#YZ&sEUM@nAgr*&hytUE
zjGD-ZNQ_Zn)R1vWWJD!K92l37u_Q7^B!&fyC1hL{8KV*-1&qtcSQZ&EiID-uGBQ>~
zMqFZKfw6*&DG%GO{fw77VxlVHu;{{;Uks;S<
zUSgaFMgtjgosLV43&5~}QI+eoATeGBMiUuwolZ!MSAo$&hFqtU661AXtRX|L(Vw8cgfeg7$ixQ&>j5adlI-QXimw<5-8FHP@N{q|EcpDjVoz6*&6<};4
zL$1?#iE$Me9bnYtI$e+$*MPBw47pBA65|FiwtYtDhpxTi&!fB5E!WE{)VJ8wgqf&D
zQN7vI`@BBFX|2AGs&X_uAR4$*c+C9j#H9`7}G}OzaP-oI?ys;54Gnhd{>C9kg#AMP?FOx!@Ni*^?sUtLF
z{m6IphEmhyTLvL|jxf&=@0@|>h{+5lPa%4aGEZuLX$HYiYO>IiLiCI=&lvNJaZd`-
zGtNBYUS@Dfs3}8F3ehvcJgIFrSI@g73GPWDdRolWVxH8*p(lmtnPi?x=9%Q46ryK}
zd8U{rHGSwwA$q2nXPSAYxhI9_nPHw8=1EN=dQymU3el5po1kv9%#)f*
z^rR3ybIdcxJagQWLiEft&ph*_CKNp>M9*>NInF%CxhI9_Szw+8=1EN}dQym<6U=jh
zc}{Ro3ej_tc}_ARl0q^1}>DMZgA^DHvYBKM>a
zJ!hEb4D+NW8a*jQ&spX<%RFbfCxz%a$2{klCpF#ZNg;a9GtYVEInO;QL{D1OFrQi8
zXZ!;5q$V9bDMZf_^DHsX68EIgcZYER-{LZqUNJz{O9IR6<1D|`%V{aWZ#O?fGWMl>9uyC1I^JJHH~_tpRAI8KF&Tp
zx)=JKj#RwSmE*~$N5MF=JF5>K=)rpb$^MTSvtOU2a0Ek
zp0J{OUnX^Ex184IVqw1Dy1kP)(81l~?9rpUmR_}c+}-Uptij%4QEy

[PATCH v8 7/8] unit-test: Add testcase for pxb

2020-05-20 Thread Yubo Miao
Add testcase for pxb to make sure the ACPI table is correct for guest.

Signed-off-by: Yubo Miao 
---
 tests/qtest/bios-tables-test.c | 58 ++
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index c9843829b3..557b7e40ff 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -621,12 +621,21 @@ static void test_acpi_one(const char *params, test_data 
*data)
  * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
  * when arm/virt boad starts to support it.
  */
-args = g_strdup_printf("-machine %s %s -accel tcg -nodefaults 
-nographic "
-"-drive if=pflash,format=raw,file=%s,readonly "
-"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
-data->machine, data->tcg_only ? "" : "-accel kvm",
-data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
-
+if (data->cd) {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : 
"");
+} else {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, params ? params : "");
+}
 } else {
 /* Disable kernel irqchip to be able to override apic irq0. */
 args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg "
@@ -966,6 +975,40 @@ static void test_acpi_virt_tcg_numamem(void)
 
 }
 
+#ifdef CONFIG_PXB
+static void test_acpi_virt_tcg_pxb(void)
+{
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+/*
+ * While using -cdrom, the cdrom would auto plugged into pxb-pcie,
+ * the reason is the bus of pxb-pcie is also root bus, it would lead
+ * to the error only PCI/PCIE bridge could plug onto pxb.
+ * Therefore,thr cdrom is defined and plugged onto the scsi controller
+ * to solve the conflicts.
+ */
+data.variant = ".pxb";
+test_acpi_one(" -device pcie-root-port,chassis=1,id=pci.1"
+  " -device virtio-scsi-pci,id=scsi0,bus=pci.1"
+  " -drive file="
+  
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2,"
+  "if=none,media=cdrom,id=drive-scsi0-0-0-1,readonly=on"
+  " -device scsi-cd,bus=scsi0.0,scsi-id=0,"
+  "drive=drive-scsi0-0-0-1,id=scsi0-0-0-1,bootindex=1"
+  " -cpu cortex-a57"
+  " -device pxb-pcie,bus_nr=128",
+  &data);
+
+free_test_data(&data);
+}
+#endif
+
 static void test_acpi_tcg_acpi_hmat(const char *machine)
 {
 test_data data;
@@ -1058,6 +1101,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
 qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem);
 qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
+#ifdef CONFIG_PXB
+qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
+#endif
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.19.1





[PATCH v8 2/8] fw_cfg: Write the extra roots into the fw_cfg

2020-05-20 Thread Yubo Miao
Write the extra roots into the fw_cfg, therefore the uefi could
get the extra roots. Only if the uefi knows there are extra roots,
the config space of devices behind the root could be obtained.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt.c  |  8 
 hw/i386/pc.c   | 18 ++
 hw/nvram/fw_cfg.c  | 20 
 include/hw/nvram/fw_cfg.h  |  2 ++
 include/hw/pci/pcie_host.h |  4 
 5 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c41d5f9778..f64ff42ab5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -78,6 +78,8 @@
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/char/pl011.h"
 #include "qemu/guest-random.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pcie_host.h"
 
 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
 static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
@@ -1457,6 +1459,10 @@ void virt_machine_done(Notifier *notifier, void *data)
 ARMCPU *cpu = ARM_CPU(first_cpu);
 struct arm_boot_info *info = &vms->bootinfo;
 AddressSpace *as = arm_boot_address_space(cpu, info);
+PCIHostState *s = PCI_GET_PCIE_HOST_STATE;
+
+PCIBus *bus = s->bus;
+FWCfgState *fw_cfg = vms->fw_cfg;
 
 /*
  * If the user provided a dtb, we assume the dynamic sysbus nodes
@@ -1475,6 +1481,8 @@ void virt_machine_done(Notifier *notifier, void *data)
 exit(1);
 }
 
+fw_cfg_write_extra_pci_roots(bus, fw_cfg);
+
 virt_acpi_setup(vms);
 virt_build_smbios(vms);
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2128f3d6fe..94b1d3df14 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -842,26 +842,12 @@ void pc_machine_done(Notifier *notifier, void *data)
 PCMachineState, machine_done);
 X86MachineState *x86ms = X86_MACHINE(pcms);
 PCIBus *bus = pcms->bus;
+FWCfgState *fw_cfg = x86ms->fw_cfg;
 
 /* set the number of CPUs */
 rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
 
-if (bus) {
-int extra_hosts = 0;
-
-QLIST_FOREACH(bus, &bus->child, sibling) {
-/* look for expander root buses */
-if (pci_bus_is_root(bus)) {
-extra_hosts++;
-}
-}
-if (extra_hosts && x86ms->fw_cfg) {
-uint64_t *val = g_malloc(sizeof(*val));
-*val = cpu_to_le64(extra_hosts);
-fw_cfg_add_file(x86ms->fw_cfg,
-"etc/extra-pci-roots", val, sizeof(*val));
-}
-}
+fw_cfg_write_extra_pci_roots(bus, fw_cfg);
 
 acpi_setup();
 if (x86ms->fw_cfg) {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 8dd50c2c72..824cfcf054 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -40,6 +40,7 @@
 #include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "hw/acpi/aml-build.h"
+#include "hw/pci/pci_bus.h"
 
 #define FW_CFG_FILE_SLOTS_DFLT 0x20
 
@@ -742,6 +743,25 @@ static void *fw_cfg_modify_bytes_read(FWCfgState *s, 
uint16_t key,
 return ptr;
 }
 
+void fw_cfg_write_extra_pci_roots(PCIBus *bus, FWCfgState *s)
+{
+if (bus) {
+int extra_hosts = 0;
+QLIST_FOREACH(bus, &bus->child, sibling) {
+/* look for expander root buses */
+if (pci_bus_is_root(bus)) {
+extra_hosts++;
+}
+}
+if (extra_hosts && s) {
+uint64_t *val = g_malloc(sizeof(*val));
+*val = cpu_to_le64(extra_hosts);
+fw_cfg_add_file(s,
+   "etc/extra-pci-roots", val, sizeof(*val));
+}
+}
+}
+
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
 {
 trace_fw_cfg_add_bytes(key, trace_key_name(key), len);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 25d9307018..eb86ee5ae6 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -79,6 +79,8 @@ struct FWCfgMemState {
 MemoryRegionOps wide_data_ops;
 };
 
+void fw_cfg_write_extra_pci_roots(PCIBus *bus, FWCfgState *s);
+
 /**
  * fw_cfg_add_bytes:
  * @s: fw_cfg device being modified
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 3f7b9886d1..c93f2d7011 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -27,6 +27,10 @@
 #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
 #define PCIE_HOST_BRIDGE(obj) \
 OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
+#define PCI_GET_PCIE_HOST_STATE \
+OBJECT_CHECK(PCIHostState, \
+ object_resolve_path_type("", "pcie-host-bridge", NULL), \
+ TYPE_PCIE_HOST_BRIDGE)
 
 #define PCIE_HOST_MCFG_BASE "MCFG"
 #define PCIE_HOST_MCFG_SIZE "mcfg_size"
-- 
2.19.1





[PATCH v8 1/8] acpi: Extract two APIs from acpi_dsdt_add_pci

2020-05-20 Thread Yubo Miao
Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc from acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 129 ++-
 1 file changed, 72 insertions(+), 57 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 1b0a584c7b..24ebc06a9f 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -148,29 +148,11 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, slot_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
 for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
@@ -206,41 +188,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -248,7 +200,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * identified by the Universal Unique IDentifier (UUID)
@@ -293,7 +246,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 
 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.6.

[PATCH v8 0/8] pci_expander_brdige:acpi: Support pxb-pcie for ARM

2020-05-20 Thread Yubo Miao
Changes with v7
v7->v8:
Fix the error:no member named 'fw_cfg' in 'struct PCMachineState'

I have one question for patch
[PATCH v8 8/8] unit-test: Add the binary file and clear diff.

I followed instructions in tests/qtest/bios-tables-test.c
to updated golden master binaries and empty
tests/qtest/bios-tables-test-allowed-diff.h.

However, checkpatch.pl would report the error
ERROR: Do not add expected files together with tests.

Does the error matters?

Changes with v6
v6->v7:
Refactor fw_cfg_write_extra_pci_roots
Add API PCI_GET_PCIE_HOST_STATE
Fix typos

Changes with v5
v5->v6: stat crs_range_insert in aml_build.h

Changes with v4
v4->v5: Not using specific resources for PXB.
Instead, the resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Only if the bios(uefi for arm) support multiple roots,
configure space of devices behind pxbs could be obtained.
The uefi work is updated for discussion by the following link:
https://edk2.groups.io/g/devel/message/56901?p=,,,20,0,0,0::Created,,add+extra+roots+for+Arm,20,2,0,72723351
[PATCH] ArmVirtPkg/FdtPciHostBridgeLib: add extra roots for Arm.

Currently pxb-pcie is not supported by arm,
the reason for it is pxb-pcie is not described in DSDT table
and only one main host bridge is described in acpi tables,
which means it is not impossible to present different io numas
for different devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Yubo Miao (8):
  acpi: Extract two APIs from acpi_dsdt_add_pci
  fw_cfg: Write the extra roots into the fw_cfg
  acpi: Extract crs build form acpi_build.c
  acpi: Refactor the source of host bridge and build tables for pxb
  acpi: Align the size to 128k
  unit-test: The files changed.
  unit-test: Add testcase for pxb
  unit-test: Add the binary file and clear diff.h

 hw/acpi/aml-build.c| 275 +++
 hw/arm/virt-acpi-build.c   | 249 +---
 hw/arm/virt.c  |   8 +
 hw/i386/acpi-build.c   | 285 -
 hw/i386/pc.c   |  18 +--
 hw/nvram/fw_cfg.c  |  20 +++
 include/hw/acpi/aml-build.h|  25 +++
 include/hw/nvram/fw_cfg.h  |   2 +
 include/hw/pci/pcie_host.h |   4 +
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test.c |  58 ++-
 11 files changed, 579 insertions(+), 365 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[PATCH v7 7/8] unit-test: Add testcase for pxb

2020-05-20 Thread Yubo Miao
Add testcase for pxb to make sure the ACPI table is correct for guest.

Signed-off-by: Yubo Miao 
---
 tests/qtest/bios-tables-test.c | 58 ++
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index c9843829b3..557b7e40ff 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -621,12 +621,21 @@ static void test_acpi_one(const char *params, test_data 
*data)
  * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
  * when arm/virt boad starts to support it.
  */
-args = g_strdup_printf("-machine %s %s -accel tcg -nodefaults 
-nographic "
-"-drive if=pflash,format=raw,file=%s,readonly "
-"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
-data->machine, data->tcg_only ? "" : "-accel kvm",
-data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
-
+if (data->cd) {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : 
"");
+} else {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, params ? params : "");
+}
 } else {
 /* Disable kernel irqchip to be able to override apic irq0. */
 args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg "
@@ -966,6 +975,40 @@ static void test_acpi_virt_tcg_numamem(void)
 
 }
 
+#ifdef CONFIG_PXB
+static void test_acpi_virt_tcg_pxb(void)
+{
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+/*
+ * While using -cdrom, the cdrom would auto plugged into pxb-pcie,
+ * the reason is the bus of pxb-pcie is also root bus, it would lead
+ * to the error only PCI/PCIE bridge could plug onto pxb.
+ * Therefore,thr cdrom is defined and plugged onto the scsi controller
+ * to solve the conflicts.
+ */
+data.variant = ".pxb";
+test_acpi_one(" -device pcie-root-port,chassis=1,id=pci.1"
+  " -device virtio-scsi-pci,id=scsi0,bus=pci.1"
+  " -drive file="
+  
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2,"
+  "if=none,media=cdrom,id=drive-scsi0-0-0-1,readonly=on"
+  " -device scsi-cd,bus=scsi0.0,scsi-id=0,"
+  "drive=drive-scsi0-0-0-1,id=scsi0-0-0-1,bootindex=1"
+  " -cpu cortex-a57"
+  " -device pxb-pcie,bus_nr=128",
+  &data);
+
+free_test_data(&data);
+}
+#endif
+
 static void test_acpi_tcg_acpi_hmat(const char *machine)
 {
 test_data data;
@@ -1058,6 +1101,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
 qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem);
 qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
+#ifdef CONFIG_PXB
+qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
+#endif
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.19.1





[PATCH v7 8/8] unit-test: Add the binary file and clear diff.h

2020-05-20 Thread Yubo Miao
Add the binary file DSDT.pxb and clear bios-tables-test-allowed-diff.h

Signed-off-by: Yubo Miao 
---
 tests/data/acpi/virt/DSDT.pxb   | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 -
 2 files changed, 1 deletion(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb
new file mode 100644
index 
..d5f0533a02d62bc2ae2db9b9de9484e5c06652fe
GIT binary patch
literal 7802
zcmeI1%WoT16o;=LiS6+tw&OgUms2Pe&&rRcNlRN|kDbINPK+mQkW$GN2t>&y5*4DY
z5GE1@x}%ZUunAHY{255B*s){5x*Prhb`0mvok@O&o()@MN3!S4-1E)-#wYff>!#D(
zdAOidc(<`_Z#avMce{3z_Jx#EdRxC{zj_wB({~#Ey~7#1TrS7^8|`MgZg<-hEUS3`
zR=cV84zJqVo#0rnvr#TrD*mx}-|jiN8EfisLTO+^WtIANRE0w4D0)D-m9e1W1K-`?I3==%fJX5q(*jFqgf=xI;=+i!j2&*$h#YZ&sEUM@nAgr*&hytUE
zjGD-ZNQ_Zn)R1vWWJD!K92l37u_Q7^B!&fyC1hL{8KV*-1&qtcSQZ&EiID-uGBQ>~
zMqFZKfw6*&DG%GO{fw77VxlVHu;{{;Uks;S<
zUSgaFMgtjgosLV43&5~}QI+eoATeGBMiUuwolZ!MSAo$&hFqtU661AXtRX|L(Vw8cgfeg7$ixQ&>j5adlI-QXimw<5-8FHP@N{q|EcpDjVoz6*&6<};4
zL$1?#iE$Me9bnYtI$e+$*MPBw47pBA65|FiwtYtDhpxTi&!fB5E!WE{)VJ8wgqf&D
zQN7vI`@BBFX|2AGs&X_uAR4$*c+C9j#H9`7}G}OzaP-oI?ys;54Gnhd{>C9kg#AMP?FOx!@Ni*^?sUtLF
z{m6IphEmhyTLvL|jxf&=@0@|>h{+5lPa%4aGEZuLX$HYiYO>IiLiCI=&lvNJaZd`-
zGtNBYUS@Dfs3}8F3ehvcJgIFrSI@g73GPWDdRolWVxH8*p(lmtnPi?x=9%Q46ryK}
zd8U{rHGSwwA$q2nXPSAYxhI9_nPHw8=1EN=dQymU3el5po1kv9%#)f*
z^rR3ybIdcxJagQWLiEft&ph*_CKNp>M9*>NInF%CxhI9_Szw+8=1EN}dQym<6U=jh
zc}{Ro3ej_tc}_ARl0q^1}>DMZgA^DHvYBKM>a
zJ!hEb4D+NW8a*jQ&spX<%RFbfCxz%a$2{klCpF#ZNg;a9GtYVEInO;QL{D1OFrQi8
zXZ!;5q$V9bDMZf_^DHsX68EIgcZYER-{LZqUNJz{O9IR6<1D|`%V{aWZ#O?fGWMl>9uyC1I^JJHH~_tpRAI8KF&Tp
zx)=JKj#RwSmE*~$N5MF=JF5>K=)rpb$^MTSvtOU2a0Ek
zp0J{OUnX^Ex184IVqw1Dy1kP)(81l~?9rpUmR_}c+}-Uptij%4QEy

[PATCH v7 1/8] acpi: Extract two APIs from acpi_dsdt_add_pci

2020-05-20 Thread Yubo Miao
Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc form acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 129 ++-
 1 file changed, 72 insertions(+), 57 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 1b0a584c7b..24ebc06a9f 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -148,29 +148,11 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, slot_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
 for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
@@ -206,41 +188,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -248,7 +200,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * identified by the Universal Unique IDentifier (UUID)
@@ -293,7 +246,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 
 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.6.

[PATCH v7 5/8] acpi: Align the size to 128k

2020-05-20 Thread Yubo Miao
If table size is changed between virt_acpi_build and
virt_acpi_build_update, the table size would not be updated to
UEFI, therefore, just align the size to 128kb, which is enough
and same with x86. It would warn if 64k is not enough and the
align size should be updated.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 14fcabd197..d0616738e5 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -57,6 +57,8 @@
 #include "hw/pci/pcie_host.h"
 #define ARM_SPI_BASE 32
 
+#define ACPI_BUILD_TABLE_SIZE 0x2
+
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
 uint16_t i;
@@ -885,6 +887,15 @@ struct AcpiBuildState {
 bool patched;
 } AcpiBuildState;
 
+static void acpi_align_size(GArray *blob, unsigned align)
+{
+/*
+ * Align size to multiple of given size. This reduces the chance
+ * we need to change size in the future (breaking cross version migration).
+ */
+g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
+}
+
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
@@ -967,6 +978,20 @@ void virt_acpi_build(VirtMachineState *vms, 
AcpiBuildTables *tables)
 build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
 }
 
+/*
+ * The align size is 128, warn if 64k is not enough therefore
+ * the align size could be resized.
+ */
+if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
+warn_report("ACPI table size %u exceeds %d bytes,"
+" migration may not work",
+tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
+error_printf("Try removing CPUs, NUMA nodes, memory slots"
+ " or PCI bridges.");
+}
+acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
+
+
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
 }
-- 
2.19.1





[PATCH v7 6/8] unit-test: The files changed.

2020-05-20 Thread Yubo Miao
The unit-test is seperated into three patches:
1. The files changed and list in bios-tables-test-allowed-diff.h
2. The unit-test
3. The binary file and clear bios-tables-test-allowed-diff.h

The ASL diff would also be listed.
Sice there are 1000+lines diff, some changes would be omitted.

  * Original Table Header:
  * Signature"DSDT"
- * Length   0x14BB (5307)
+ * Length   0x1E7A (7802)
  * Revision 0x02
- * Checksum 0xD1
+ * Checksum 0x57
  * OEM ID   "BOCHS "
  * OEM Table ID "BXPCDSDT"
  * OEM Revision 0x0001 (1)

+Device (PC80)
+{
+Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+Name (_ADR, Zero)  // _ADR: Address
+Name (_CCA, One)  // _CCA: Cache Coherency Attribute
+Name (_SEG, Zero)  // _SEG: PCI Segment
+Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
+Name (_UID, 0x80)  // _UID: Unique ID
+Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
+Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
+{
+Package (0x04)
+{
+0x,
+Zero,
+GSI0,
+Zero
+},
+

Packages are omitted.

+Package (0x04)
+{
+0x001F,
+0x03,
+GSI2,
+Zero
+}
+})
+Device (GSI0)
+{
+Name (_HID, "PNP0C0F" /* PCI Interrupt Link Device */)  // 
_HID: Hardware ID
+Name (_UID, Zero)  // _UID: Unique ID
+Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Method (_SRS, 1, NotSerialized)  // _SRS: Set Resource Settings
+{
+}
+}

GSI1,2,3 are omitted.

+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
+{
+WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+0x, // Granularity
+0x0080, // Range Minimum
+0x0080, // Range Maximum
+0x, // Translation Offset
+0x0001, // Length
+,, )
+})
+Name (SUPP, Zero)
+Name (CTRL, Zero)
+Method (_OSC, 4, NotSerialized)  // _OSC: Operating System 
Capabilities
+{
+CreateDWordField (Arg3, Zero, CDW1)
+If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") 
/* PCI Host Bridge Device */))
+{
+CreateDWordField (Arg3, 0x04, CDW2)
+CreateDWordField (Arg3, 0x08, CDW3)
+SUPP = CDW2 /* \_SB_.PC80._OSC.CDW2 */
+CTRL = CDW3 /* \_SB_.PC80._OSC.CDW3 */
+CTRL &= 0x1F
+If ((Arg1 != One))
+{
+CDW1 |= 0x08
+}
+
+If ((CDW3 != CTRL))
+{
+CDW1 |= 0x10
+}
+
+CDW3 = CTRL /* \_SB_.PC80.CTRL */
+Return (Arg3)
+}
+Else
+{
+CDW1 |= 0x04
+Return (Arg3)
+}
+}

DSM is are omitted

 Device (PCI0)
 {
 Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
PosDecode,
 0x, // Granularity
 0x, // Range Minimum
-0x00FF, // Range Maximum
+0x007F, // Range Maximum
 0x, // Translation Offset
-0x0100, // Length
+0x0080, // Length

Signed-off-by: Yubo Miao 
---

[PATCH v7 3/8] acpi: Extract crs build form acpi_build.c

2020-05-20 Thread Yubo Miao
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 
---
 hw/acpi/aml-build.c | 275 ++
 hw/i386/acpi-build.c| 285 
 include/hw/acpi/aml-build.h |  25 
 3 files changed, 300 insertions(+), 285 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 3681ec6e3d..5802597f8a 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -26,6 +26,9 @@
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
 #include "hw/boards.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -54,6 +57,125 @@ static void build_append_array(GArray *array, GArray *val)
 
 #define ACPI_NAMESEG_LEN 4
 
+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);
+}
+
+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);
+}
+
+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] }.
+ */
+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);
+}
+
+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 void
 build_append_nameseg(GArray *array, const char *seg)
 {
@@ -1877,6 +1999,159 @@ build_hdr:
  "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
 }
 
+Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
+{
+Aml *crs = 

[PATCH v7 4/8] acpi: Refactor the source of host bridge and build tables for pxb

2020-05-20 Thread Yubo Miao
The resources of pxbs are obtained by crs_build and the resources
used by pxbs would be moved from the resources defined for host-bridge.

The resources for pxb are composed of following two parts
1. The bar space of the pci-bridge/pcie-root-port behined it
2. The config space of devices behind it.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt-acpi-build.c | 127 +--
 1 file changed, 110 insertions(+), 17 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 24ebc06a9f..14fcabd197 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -51,6 +51,10 @@
 #include "migration/vmstate.h"
 #include "hw/acpi/ghes.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pcie_host.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -268,19 +272,80 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+int i;
+Aml *method, *crs, *dev_pxb;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+CrsRangeEntry *entry;
+CrsRangeSet crs_range_set;
+
+crs_range_set_init(&crs_range_set);
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
 
 Aml *dev = aml_device("%s", "PCI0");
+PCIHostState *s = PCI_GET_PCIE_HOST_STATE;
+
+PCIBus *bus = s->bus;
+/* start to construct the tables for pxb */
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+/*
+ * 0 - (nr_pcie_buses - 1) is the bus range for the main
+ * host-bridge and it equals the MIN of the
+ * busNr defined for pxb-pcie.
+ */
+if (bus_num < nr_pcie_buses) {
+nr_pcie_buses = bus_num;
+}
+
+dev_pxb = aml_device("PC%.02X", bus_num);
+aml_append(dev_pxb, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev_pxb, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev_pxb, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev_pxb, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev_pxb, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev_pxb, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev_pxb, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev_pxb,
+   aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev_pxb, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev_pxb, scope, irq);
+
+/*
+ * Resources defined for PXBs are composed by the folling parts:
+ * 1. The resources the pci-brige/pcie-root-port need.
+ * 2. The resources the devices behind pxb need.
+ */
+crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+aml_append(dev_pxb, aml_name_decl("_CRS", crs));
+
+acpi_dsdt_add_pci_osc(dev_pxb, scope);
+
+aml_append(scope, dev_pxb);
+
+}
+}
+
+/* tables for the main */
 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
 aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
 aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
@@ -301,25 +366,51 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
 0x, 0x, nr_pcie_buses - 1, 0x,
 nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
-   

[PATCH v7 2/8] fw_cfg: Write the extra roots into the fw_cfg

2020-05-20 Thread Yubo Miao
Write the extra roots into the fw_cfg, therefore the uefi could
get the extra roots. Only if the uefi knows there are extra roots,
the config space of devices behind the root could be obtained.

Signed-off-by: Yubo Miao 
---
 hw/arm/virt.c  |  8 
 hw/i386/pc.c   | 18 ++
 hw/nvram/fw_cfg.c  | 20 
 include/hw/nvram/fw_cfg.h  |  2 ++
 include/hw/pci/pcie_host.h |  4 
 5 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c41d5f9778..f64ff42ab5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -78,6 +78,8 @@
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/char/pl011.h"
 #include "qemu/guest-random.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pcie_host.h"
 
 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
 static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
@@ -1457,6 +1459,10 @@ void virt_machine_done(Notifier *notifier, void *data)
 ARMCPU *cpu = ARM_CPU(first_cpu);
 struct arm_boot_info *info = &vms->bootinfo;
 AddressSpace *as = arm_boot_address_space(cpu, info);
+PCIHostState *s = PCI_GET_PCIE_HOST_STATE;
+
+PCIBus *bus = s->bus;
+FWCfgState *fw_cfg = vms->fw_cfg;
 
 /*
  * If the user provided a dtb, we assume the dynamic sysbus nodes
@@ -1475,6 +1481,8 @@ void virt_machine_done(Notifier *notifier, void *data)
 exit(1);
 }
 
+fw_cfg_write_extra_pci_roots(bus, fw_cfg);
+
 virt_acpi_setup(vms);
 virt_build_smbios(vms);
 }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2128f3d6fe..3227e0d2ea 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -842,26 +842,12 @@ void pc_machine_done(Notifier *notifier, void *data)
 PCMachineState, machine_done);
 X86MachineState *x86ms = X86_MACHINE(pcms);
 PCIBus *bus = pcms->bus;
+FWCfgState *fw_cfg = pcms->fw_cfg;
 
 /* set the number of CPUs */
 rtc_set_cpus_count(x86ms->rtc, x86ms->boot_cpus);
 
-if (bus) {
-int extra_hosts = 0;
-
-QLIST_FOREACH(bus, &bus->child, sibling) {
-/* look for expander root buses */
-if (pci_bus_is_root(bus)) {
-extra_hosts++;
-}
-}
-if (extra_hosts && x86ms->fw_cfg) {
-uint64_t *val = g_malloc(sizeof(*val));
-*val = cpu_to_le64(extra_hosts);
-fw_cfg_add_file(x86ms->fw_cfg,
-"etc/extra-pci-roots", val, sizeof(*val));
-}
-}
+fw_cfg_write_extra_pci_roots(bus, fw_cfg);
 
 acpi_setup();
 if (x86ms->fw_cfg) {
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 8dd50c2c72..824cfcf054 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -40,6 +40,7 @@
 #include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "hw/acpi/aml-build.h"
+#include "hw/pci/pci_bus.h"
 
 #define FW_CFG_FILE_SLOTS_DFLT 0x20
 
@@ -742,6 +743,25 @@ static void *fw_cfg_modify_bytes_read(FWCfgState *s, 
uint16_t key,
 return ptr;
 }
 
+void fw_cfg_write_extra_pci_roots(PCIBus *bus, FWCfgState *s)
+{
+if (bus) {
+int extra_hosts = 0;
+QLIST_FOREACH(bus, &bus->child, sibling) {
+/* look for expander root buses */
+if (pci_bus_is_root(bus)) {
+extra_hosts++;
+}
+}
+if (extra_hosts && s) {
+uint64_t *val = g_malloc(sizeof(*val));
+*val = cpu_to_le64(extra_hosts);
+fw_cfg_add_file(s,
+   "etc/extra-pci-roots", val, sizeof(*val));
+}
+}
+}
+
 void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len)
 {
 trace_fw_cfg_add_bytes(key, trace_key_name(key), len);
diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h
index 25d9307018..eb86ee5ae6 100644
--- a/include/hw/nvram/fw_cfg.h
+++ b/include/hw/nvram/fw_cfg.h
@@ -79,6 +79,8 @@ struct FWCfgMemState {
 MemoryRegionOps wide_data_ops;
 };
 
+void fw_cfg_write_extra_pci_roots(PCIBus *bus, FWCfgState *s);
+
 /**
  * fw_cfg_add_bytes:
  * @s: fw_cfg device being modified
diff --git a/include/hw/pci/pcie_host.h b/include/hw/pci/pcie_host.h
index 3f7b9886d1..c93f2d7011 100644
--- a/include/hw/pci/pcie_host.h
+++ b/include/hw/pci/pcie_host.h
@@ -27,6 +27,10 @@
 #define TYPE_PCIE_HOST_BRIDGE "pcie-host-bridge"
 #define PCIE_HOST_BRIDGE(obj) \
 OBJECT_CHECK(PCIExpressHost, (obj), TYPE_PCIE_HOST_BRIDGE)
+#define PCI_GET_PCIE_HOST_STATE \
+OBJECT_CHECK(PCIHostState, \
+ object_resolve_path_type("", "pcie-host-bridge", NULL), \
+ TYPE_PCIE_HOST_BRIDGE)
 
 #define PCIE_HOST_MCFG_BASE "MCFG"
 #define PCIE_HOST_MCFG_SIZE "mcfg_size"
-- 
2.19.1





[PATCH v7 0/8] pci_expander_brdige:acpi: Support pxb-pcie for ARM

2020-05-20 Thread Yubo Miao
Changes with v6
v6->v7:
Refactor fw_cfg_write_extra_pci_roots
Add API PCI_GET_PCIE_HOST_STATE
Fix typos

I have one question for patch
[PATCH v7 8/8] unit-test: Add the binary file and clear diff.

I followed instructions in tests/qtest/bios-tables-test.c
to updated golden master binaries and empty
tests/qtest/bios-tables-test-allowed-diff.h.

However, checkpatch.pl would report the error
ERROR: Do not add expected files together with tests.

Does the error matters?

Changes with v5
v5->v6: stat crs_range_insert in aml_build.h

Changes with v4
v4->v5: Not using specific resources for PXB.
Instead, the resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Only if the bios(uefi for arm) support multiple roots,
configure space of devices behind pxbs could be obtained.
The uefi work is updated for discussion by the following link:
https://edk2.groups.io/g/devel/message/56901?p=,,,20,0,0,0::Created,,add+extra+roots+for+Arm,20,2,0,72723351
[PATCH] ArmVirtPkg/FdtPciHostBridgeLib: add extra roots for Arm.

Currently pxb-pcie is not supported by arm,
the reason for it is pxb-pcie is not described in DSDT table
and only one main host bridge is described in acpi tables,
which means it is not impossible to present different io numas
for different devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Yubo Miao (8):
  acpi: Extract two APIs from acpi_dsdt_add_pci
  fw_cfg: Write the extra roots into the fw_cfg
  acpi: Extract crs build form acpi_build.c
  acpi: Refactor the source of host bridge and build tables for pxb
  acpi: Align the size to 128k
  unit-test: The files changed.
  unit-test: Add testcase for pxb
  unit-test: Add the binary file and clear diff.h

 hw/acpi/aml-build.c| 275 +++
 hw/arm/virt-acpi-build.c   | 249 +---
 hw/arm/virt.c  |   8 +
 hw/i386/acpi-build.c   | 285 -
 hw/i386/pc.c   |  18 +--
 hw/nvram/fw_cfg.c  |  20 +++
 include/hw/acpi/aml-build.h|  25 +++
 include/hw/nvram/fw_cfg.h  |   2 +
 include/hw/pci/pcie_host.h |   4 +
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test.c |  58 ++-
 11 files changed, 579 insertions(+), 365 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[PATCH v6 5/8] acpi: Align the size to 128k

2020-04-08 Thread Yubo Miao
From: miaoyubo 

If table size is changed between virt_acpi_build and
virt_acpi_build_update, the table size would not be updated to
UEFI, therefore, just align the size to 128kb, which is enough
and same with x86. It would warn if 64k is not enough and the
align size should be updated.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 7bcd04dfb7..89bb768b0c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -54,6 +54,8 @@
 #include "hw/pci/pci_bridge.h"
 #define ARM_SPI_BASE 32
 
+#define ACPI_BUILD_TABLE_SIZE 0x2
+
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
 uint16_t i;
@@ -883,6 +885,15 @@ struct AcpiBuildState {
 bool patched;
 } AcpiBuildState;
 
+static void acpi_align_size(GArray *blob, unsigned align)
+{
+/*
+ * Align size to multiple of given size. This reduces the chance
+ * we need to change size in the future (breaking cross version migration).
+ */
+g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
+}
+
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
@@ -953,6 +964,20 @@ void virt_acpi_build(VirtMachineState *vms, 
AcpiBuildTables *tables)
 build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
 }
 
+/*
+ * The align size is 128, warn if 64k is not enough therefore
+ * the align size could be resized.
+ */
+if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
+warn_report("ACPI table size %u exceeds %d bytes,"
+" migration may not work",
+tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
+error_printf("Try removing CPUs, NUMA nodes, memory slots"
+ " or PCI bridges.");
+}
+acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
+
+
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
 }
-- 
2.19.1





[PATCH v6 0/8] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-04-08 Thread Yubo Miao
From: miaoyubo 

Changes with v5
v5->v6: stat crs_range_insert in aml_build.h

Changes with v4
v4->v5: Not using specific resources for PXB.
Instead, the resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Only if the bios(uefi for arm) support multiple roots,
configure space of devices behind pxbs could be obtained.
The uefi work is updated for discussion by the following link:
https://edk2.groups.io/g/devel/message/56901?p=,,,20,0,0,0::Created,,add+extra+roots+for+Arm,20,2,0,72723351
 
[PATCH] ArmVirtPkg/FdtPciHostBridgeLib: add extra roots for Arm.

Currently pxb-pcie is not supported by arm,
the reason for it is pxb-pcie is not described in DSDT table
and only one main host bridge is described in acpi tables,
which means it is not impossible to present different io numas
for different devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

miaoyubo (8):
  acpi: Extract two APIs from acpi_dsdt_add_pci
  fw_cfg: Write the extra roots into the fw_cfg
  acpi: Extract crs build form acpi_build.c
  acpi: Refactor the source of host bridge and build tables for pxb
  acpi: Align the size to 128k
  unit-test: The files changed.
  unit-test: Add testcase for pxb
  unit-test: Add the binary file and clear diff.h

 hw/acpi/aml-build.c| 275 +++
 hw/arm/virt-acpi-build.c   | 251 ++---
 hw/arm/virt.c  |  23 +++
 hw/i386/acpi-build.c   | 285 -
 include/hw/acpi/aml-build.h|  25 +++
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test.c |  58 ++-
 7 files changed, 566 insertions(+), 351 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[PATCH v6 8/8] unit-test: Add the binary file and clear diff.h

2020-04-08 Thread Yubo Miao
From: miaoyubo 

Add the binary file DSDT.pxb and clear bios-tables-test-allowed-diff.h

Signed-off-by: miaoyubo 
---
 tests/data/acpi/virt/DSDT.pxb   | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 -
 2 files changed, 1 deletion(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb
new file mode 100644
index 
..d5f0533a02d62bc2ae2db9b9de9484e5c06652fe
GIT binary patch
literal 7802
zcmeI1%WoT16o;=LiS6+tw&OgUms2Pe&&rRcNlRN|kDbINPK+mQkW$GN2t>&y5*4DY
z5GE1@x}%ZUunAHY{255B*s){5x*Prhb`0mvok@O&o()@MN3!S4-1E)-#wYff>!#D(
zdAOidc(<`_Z#avMce{3z_Jx#EdRxC{zj_wB({~#Ey~7#1TrS7^8|`MgZg<-hEUS3`
zR=cV84zJqVo#0rnvr#TrD*mx}-|jiN8EfisLTO+^WtIANRE0w4D0)D-m9e1W1K-`?I3==%fJX5q(*jFqgf=xI;=+i!j2&*$h#YZ&sEUM@nAgr*&hytUE
zjGD-ZNQ_Zn)R1vWWJD!K92l37u_Q7^B!&fyC1hL{8KV*-1&qtcSQZ&EiID-uGBQ>~
zMqFZKfw6*&DG%GO{fw77VxlVHu;{{;Uks;S<
zUSgaFMgtjgosLV43&5~}QI+eoATeGBMiUuwolZ!MSAo$&hFqtU661AXtRX|L(Vw8cgfeg7$ixQ&>j5adlI-QXimw<5-8FHP@N{q|EcpDjVoz6*&6<};4
zL$1?#iE$Me9bnYtI$e+$*MPBw47pBA65|FiwtYtDhpxTi&!fB5E!WE{)VJ8wgqf&D
zQN7vI`@BBFX|2AGs&X_uAR4$*c+C9j#H9`7}G}OzaP-oI?ys;54Gnhd{>C9kg#AMP?FOx!@Ni*^?sUtLF
z{m6IphEmhyTLvL|jxf&=@0@|>h{+5lPa%4aGEZuLX$HYiYO>IiLiCI=&lvNJaZd`-
zGtNBYUS@Dfs3}8F3ehvcJgIFrSI@g73GPWDdRolWVxH8*p(lmtnPi?x=9%Q46ryK}
zd8U{rHGSwwA$q2nXPSAYxhI9_nPHw8=1EN=dQymU3el5po1kv9%#)f*
z^rR3ybIdcxJagQWLiEft&ph*_CKNp>M9*>NInF%CxhI9_Szw+8=1EN}dQym<6U=jh
zc}{Ro3ej_tc}_ARl0q^1}>DMZgA^DHvYBKM>a
zJ!hEb4D+NW8a*jQ&spX<%RFbfCxz%a$2{klCpF#ZNg;a9GtYVEInO;QL{D1OFrQi8
zXZ!;5q$V9bDMZf_^DHsX68EIgcZYER-{LZqUNJz{O9IR6<1D|`%V{aWZ#O?fGWMl>9uyC1I^JJHH~_tpRAI8KF&Tp
zx)=JKj#RwSmE*~$N5MF=JF5>K=)rpb$^MTSvtOU2a0Ek
zp0J{OUnX^Ex184IVqw1Dy1kP)(81l~?9rpUmR_}c+}-Uptij%4QEy

[PATCH v6 4/8] acpi: Refactor the source of host bridge and build tables for pxb

2020-04-08 Thread Yubo Miao
From: miaoyubo 

The resources of pxbs and obtained by crs_build and the resources
used by pxbs would be moved form the resources defined for host-bridge.

The resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 131 +--
 1 file changed, 111 insertions(+), 20 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index e8ba09855c..7bcd04dfb7 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,9 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -266,19 +269,81 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+int i;
+Aml *method, *crs, *dev;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+CrsRangeEntry *entry;
+CrsRangeSet crs_range_set;
+
+crs_range_set_init(&crs_range_set);
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+PCIHostState *s = OBJECT_CHECK(PCIHostState,
+   object_resolve_path_type("",
+   "pcie-host-bridge", NULL),
+   TYPE_PCI_HOST_BRIDGE);
+
+PCIBus *bus = s->bus;
+/* start to construct the tables for pxb*/
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+/*
+ * Coded up the MIN of the busNr defined for pxb-pcie,
+ * the MIN - 1 would be the MAX bus number for the main
+ * host bridge.
+ */
+if (bus_num < nr_pcie_buses) {
+nr_pcie_buses = bus_num;
+}
+
+dev = aml_device("PC%.02X", bus_num);
+aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev, scope, irq);
+
+/*
+ * Resources deined for PXBs are composed by the folling parts:
+ * 1. The resources the pci-brige/pcie-root-port need.
+ * 2. The resources the devices behind pxb need.
+ */
+crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+aml_append(dev, aml_name_decl("_CRS", crs));
+
+acpi_dsdt_add_pci_osc(dev, scope);
+
+aml_append(scope, dev);
+
+}
+}
 
-Aml *dev = aml_device("%s", "PCI0");
+/* start to construct the tables for main host bridge */
+dev = aml_device("%s", "PCI0");
 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
 aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
 aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
@@ -299,25 +364,51 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
 0x, 0x, nr_pcie_buses - 1, 0x,
 nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-  

[PATCH v6 7/8] unit-test: Add testcase for pxb

2020-04-08 Thread Yubo Miao
From: miaoyubo 

Add testcase for pxb to make sure the ACPI table is correct for guest.

Signed-off-by: miaoyubo 
---
 tests/qtest/bios-tables-test.c | 58 ++
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 0a597bbacf..4bba680917 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -621,12 +621,21 @@ static void test_acpi_one(const char *params, test_data 
*data)
  * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
  * when arm/virt boad starts to support it.
  */
-args = g_strdup_printf("-machine %s %s -accel tcg -nodefaults 
-nographic "
-"-drive if=pflash,format=raw,file=%s,readonly "
-"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
-data->machine, data->tcg_only ? "" : "-accel kvm",
-data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
-
+if (data->cd) {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : 
"");
+} else {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, params ? params : "");
+}
 } else {
 /* Disable kernel irqchip to be able to override apic irq0. */
 args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg "
@@ -961,6 +970,40 @@ static void test_acpi_virt_tcg_numamem(void)
 
 }
 
+#ifdef CONFIG_PXB
+static void test_acpi_virt_tcg_pxb(void)
+{
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+/*
+ * While using -cdrom, the cdrom would auto plugged into pxb-pcie,
+ * the reason is the bus of pxb-pcie is also root bus, it would lead
+ * to the error only PCI/PCIE bridge could plug onto pxb.
+ * Therefore,thr cdrom is defined and plugged onto the scsi controller
+ * to solve the conflicts.
+ */
+data.variant = ".pxb";
+test_acpi_one(" -device pcie-root-port,chassis=1,id=pci.1"
+  " -device virtio-scsi-pci,id=scsi0,bus=pci.1"
+  " -drive file="
+  
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2,"
+  "if=none,media=cdrom,id=drive-scsi0-0-0-1,readonly=on"
+  " -device scsi-cd,bus=scsi0.0,scsi-id=0,"
+  "drive=drive-scsi0-0-0-1,id=scsi0-0-0-1,bootindex=1"
+  " -cpu cortex-a57"
+  " -device pxb-pcie,bus_nr=128",
+  &data);
+
+free_test_data(&data);
+}
+#endif
+
 static void test_acpi_tcg_acpi_hmat(const char *machine)
 {
 test_data data;
@@ -1053,6 +1096,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
 qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem);
 qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
+#ifdef CONFIG_PXB
+qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
+#endif
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.19.1





[PATCH v6 1/8] acpi: Extract two APIs from acpi_dsdt_add_pci

2020-04-08 Thread Yubo Miao
From: miaoyubo 

Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc form acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 129 ++-
 1 file changed, 72 insertions(+), 57 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 7ef0733d71..e8ba09855c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -146,29 +146,11 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, slot_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
 for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
@@ -204,41 +186,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -246,7 +198,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * identified by the Universal Unique IDentifier (UUID)
@@ -291,7 +244,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 
 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.6.1. _DSM for PCI Express Slot Information
  * The UUID in _DSM in this context is
  * {E5C937D0-3553-4D7A-9117-EA4D19C3434D}
@@ -309,6 +263,67 @@ static void acpi_dsdt_add_pci(

[PATCH v6 2/8] fw_cfg: Write the extra roots into the fw_cfg

2020-04-08 Thread Yubo Miao
From: miaoyubo 

Write the extra roots into the fw_cfg therefore the uefi could
get the extra roots. Only if the uefi know there are extra roots,
the config space of devices behind the root could be obtained.

Signed-off-by: miaoyubo 
---
 hw/arm/virt.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7dc96abf72..0fdfe4129c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -77,6 +77,7 @@
 #include "hw/acpi/generic_event_device.h"
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/char/pl011.h"
+#include "hw/pci/pci_bus.h"
 
 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
 static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
@@ -1435,6 +1436,12 @@ void virt_machine_done(Notifier *notifier, void *data)
 ARMCPU *cpu = ARM_CPU(first_cpu);
 struct arm_boot_info *info = &vms->bootinfo;
 AddressSpace *as = arm_boot_address_space(cpu, info);
+PCIHostState *s = OBJECT_CHECK(PCIHostState,
+   object_resolve_path_type("",
+   "pcie-host-bridge", NULL),
+   TYPE_PCI_HOST_BRIDGE);
+
+PCIBus *bus = s->bus;
 
 /*
  * If the user provided a dtb, we assume the dynamic sysbus nodes
@@ -1453,6 +1460,22 @@ void virt_machine_done(Notifier *notifier, void *data)
 exit(1);
 }
 
+if (bus) {
+int extra_hosts = 0;
+QLIST_FOREACH(bus, &bus->child, sibling) {
+/* look for expander root buses */
+if (pci_bus_is_root(bus)) {
+extra_hosts++;
+}
+}
+if (extra_hosts && vms->fw_cfg) {
+uint64_t *val = g_malloc(sizeof(*val));
+*val = cpu_to_le64(extra_hosts);
+fw_cfg_add_file(vms->fw_cfg,
+   "etc/extra-pci-roots", val, sizeof(*val));
+}
+}
+
 virt_acpi_setup(vms);
 virt_build_smbios(vms);
 }
-- 
2.19.1





[PATCH v6 3/8] acpi: Extract crs build form acpi_build.c

2020-04-08 Thread Yubo Miao
From: miaoyubo 

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 devices behind PXBs need.
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: miaoyubo 
---
 hw/acpi/aml-build.c | 275 ++
 hw/i386/acpi-build.c| 285 
 include/hw/acpi/aml-build.h |  25 
 3 files changed, 300 insertions(+), 285 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2c3702b882..252349d96d 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -26,6 +26,9 @@
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
 #include "hw/boards.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -54,6 +57,125 @@ static void build_append_array(GArray *array, GArray *val)
 
 #define ACPI_NAMESEG_LEN 4
 
+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);
+}
+
+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);
+}
+
+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] }.
+ */
+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);
+}
+
+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 void
 build_append_nameseg(GArray *array, const char *seg)
 {
@@ -1875,6 +1997,159 @@ build_hdr:
  "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
 }
 
+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_rang

[PATCH v6 6/8] unit-test: The files changed.

2020-04-08 Thread Yubo Miao
From: miaoyubo 

The unit-test is seperated into three patches:
1. The files changed and list in bios-tables-test-allowed-diff.h
2. The unit-test
3. The binary file and clear bios-tables-test-allowed-diff.h

The ASL diff would also be listed.
Sice there are 1000+lines diff, some changes would be omitted.

  * Original Table Header:
  * Signature"DSDT"
- * Length   0x14BB (5307)
+ * Length   0x1E7A (7802)
  * Revision 0x02
- * Checksum 0xD1
+ * Checksum 0x57
  * OEM ID   "BOCHS "
  * OEM Table ID "BXPCDSDT"
  * OEM Revision 0x0001 (1)

+Device (PC80)
+{
+Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+Name (_ADR, Zero)  // _ADR: Address
+Name (_CCA, One)  // _CCA: Cache Coherency Attribute
+Name (_SEG, Zero)  // _SEG: PCI Segment
+Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
+Name (_UID, 0x80)  // _UID: Unique ID
+Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
+Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
+{
+Package (0x04)
+{
+0x,
+Zero,
+GSI0,
+Zero
+},
+

Packages are omitted.

+Package (0x04)
+{
+0x001F,
+0x03,
+GSI2,
+Zero
+}
+})
+Device (GSI0)
+{
+Name (_HID, "PNP0C0F" /* PCI Interrupt Link Device */)  // 
_HID: Hardware ID
+Name (_UID, Zero)  // _UID: Unique ID
+Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Method (_SRS, 1, NotSerialized)  // _SRS: Set Resource Settings
+{
+}
+}

GSI1,2,3 are omitted.

+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
+{
+WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+0x, // Granularity
+0x0080, // Range Minimum
+0x0080, // Range Maximum
+0x, // Translation Offset
+0x0001, // Length
+,, )
+})
+Name (SUPP, Zero)
+Name (CTRL, Zero)
+Method (_OSC, 4, NotSerialized)  // _OSC: Operating System 
Capabilities
+{
+CreateDWordField (Arg3, Zero, CDW1)
+If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") 
/* PCI Host Bridge Device */))
+{
+CreateDWordField (Arg3, 0x04, CDW2)
+CreateDWordField (Arg3, 0x08, CDW3)
+SUPP = CDW2 /* \_SB_.PC80._OSC.CDW2 */
+CTRL = CDW3 /* \_SB_.PC80._OSC.CDW3 */
+CTRL &= 0x1F
+If ((Arg1 != One))
+{
+CDW1 |= 0x08
+}
+
+If ((CDW3 != CTRL))
+{
+CDW1 |= 0x10
+}
+
+CDW3 = CTRL /* \_SB_.PC80.CTRL */
+Return (Arg3)
+}
+Else
+{
+CDW1 |= 0x04
+Return (Arg3)
+}
+}

DSM is are omitted

 Device (PCI0)
 {
 Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
PosDecode,
 0x, // Granularity
 0x, // Range Minimum
-0x00FF, // Range Maximum
+0x007F, // Range Maximum
 0x, // Translation Offset
-0x0100, // Length
+0x0080, // Length

Signed-off-by: miaoyubo 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 1 +
 1 file changed, 1 insertion

[PATCH v5 8/8] unit-test: add the binary file and clear diff.h

2020-04-07 Thread Yubo Miao
From: miaoyubo 

Add the binary file DSDT.pxb and clear bios-tables-test-allowed-diff.h

Signed-off-by: miaoyubo 
---
 tests/data/acpi/virt/DSDT.pxb   | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 -
 2 files changed, 1 deletion(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb
new file mode 100644
index 
..d5f0533a02d62bc2ae2db9b9de9484e5c06652fe
GIT binary patch
literal 7802
zcmeI1%WoT16o;=LiS6+tw&OgUms2Pe&&rRcNlRN|kDbINPK+mQkW$GN2t>&y5*4DY
z5GE1@x}%ZUunAHY{255B*s){5x*Prhb`0mvok@O&o()@MN3!S4-1E)-#wYff>!#D(
zdAOidc(<`_Z#avMce{3z_Jx#EdRxC{zj_wB({~#Ey~7#1TrS7^8|`MgZg<-hEUS3`
zR=cV84zJqVo#0rnvr#TrD*mx}-|jiN8EfisLTO+^WtIANRE0w4D0)D-m9e1W1K-`?I3==%fJX5q(*jFqgf=xI;=+i!j2&*$h#YZ&sEUM@nAgr*&hytUE
zjGD-ZNQ_Zn)R1vWWJD!K92l37u_Q7^B!&fyC1hL{8KV*-1&qtcSQZ&EiID-uGBQ>~
zMqFZKfw6*&DG%GO{fw77VxlVHu;{{;Uks;S<
zUSgaFMgtjgosLV43&5~}QI+eoATeGBMiUuwolZ!MSAo$&hFqtU661AXtRX|L(Vw8cgfeg7$ixQ&>j5adlI-QXimw<5-8FHP@N{q|EcpDjVoz6*&6<};4
zL$1?#iE$Me9bnYtI$e+$*MPBw47pBA65|FiwtYtDhpxTi&!fB5E!WE{)VJ8wgqf&D
zQN7vI`@BBFX|2AGs&X_uAR4$*c+C9j#H9`7}G}OzaP-oI?ys;54Gnhd{>C9kg#AMP?FOx!@Ni*^?sUtLF
z{m6IphEmhyTLvL|jxf&=@0@|>h{+5lPa%4aGEZuLX$HYiYO>IiLiCI=&lvNJaZd`-
zGtNBYUS@Dfs3}8F3ehvcJgIFrSI@g73GPWDdRolWVxH8*p(lmtnPi?x=9%Q46ryK}
zd8U{rHGSwwA$q2nXPSAYxhI9_nPHw8=1EN=dQymU3el5po1kv9%#)f*
z^rR3ybIdcxJagQWLiEft&ph*_CKNp>M9*>NInF%CxhI9_Szw+8=1EN}dQym<6U=jh
zc}{Ro3ej_tc}_ARl0q^1}>DMZgA^DHvYBKM>a
zJ!hEb4D+NW8a*jQ&spX<%RFbfCxz%a$2{klCpF#ZNg;a9GtYVEInO;QL{D1OFrQi8
zXZ!;5q$V9bDMZf_^DHsX68EIgcZYER-{LZqUNJz{O9IR6<1D|`%V{aWZ#O?fGWMl>9uyC1I^JJHH~_tpRAI8KF&Tp
zx)=JKj#RwSmE*~$N5MF=JF5>K=)rpb$^MTSvtOU2a0Ek
zp0J{OUnX^Ex184IVqw1Dy1kP)(81l~?9rpUmR_}c+}-Uptij%4QEy

[PATCH v5 2/8] fw_cfg: Write the extra roots into the fw_cfg

2020-04-07 Thread Yubo Miao
From: miaoyubo 

Write the extra roots into the fw_cfg therefore the uefi could
get the extra roots. Only if the uefi know there are extra roots,
the config space of devices behind the root could be obtained.

Signed-off-by: miaoyubo 
---
 hw/arm/virt.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7dc96abf72..0fdfe4129c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -77,6 +77,7 @@
 #include "hw/acpi/generic_event_device.h"
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/char/pl011.h"
+#include "hw/pci/pci_bus.h"
 
 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
 static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
@@ -1435,6 +1436,12 @@ void virt_machine_done(Notifier *notifier, void *data)
 ARMCPU *cpu = ARM_CPU(first_cpu);
 struct arm_boot_info *info = &vms->bootinfo;
 AddressSpace *as = arm_boot_address_space(cpu, info);
+PCIHostState *s = OBJECT_CHECK(PCIHostState,
+   object_resolve_path_type("",
+   "pcie-host-bridge", NULL),
+   TYPE_PCI_HOST_BRIDGE);
+
+PCIBus *bus = s->bus;
 
 /*
  * If the user provided a dtb, we assume the dynamic sysbus nodes
@@ -1453,6 +1460,22 @@ void virt_machine_done(Notifier *notifier, void *data)
 exit(1);
 }
 
+if (bus) {
+int extra_hosts = 0;
+QLIST_FOREACH(bus, &bus->child, sibling) {
+/* look for expander root buses */
+if (pci_bus_is_root(bus)) {
+extra_hosts++;
+}
+}
+if (extra_hosts && vms->fw_cfg) {
+uint64_t *val = g_malloc(sizeof(*val));
+*val = cpu_to_le64(extra_hosts);
+fw_cfg_add_file(vms->fw_cfg,
+   "etc/extra-pci-roots", val, sizeof(*val));
+}
+}
+
 virt_acpi_setup(vms);
 virt_build_smbios(vms);
 }
-- 
2.19.1





[PATCH v5 3/8] acpi:Extract crs build form acpi_build.c

2020-04-07 Thread Yubo Miao
From: miaoyubo 

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 devices behind PXBs need.
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: miaoyubo 
---
 hw/acpi/aml-build.c | 275 ++
 hw/i386/acpi-build.c| 285 
 include/hw/acpi/aml-build.h |  23 +++
 3 files changed, 298 insertions(+), 285 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2c3702b882..2764c619d4 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -26,6 +26,9 @@
 #include "qemu/bitops.h"
 #include "sysemu/numa.h"
 #include "hw/boards.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -54,6 +57,125 @@ static void build_append_array(GArray *array, GArray *val)
 
 #define ACPI_NAMESEG_LEN 4
 
+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);
+}
+
+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);
+}
+
+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] }.
+ */
+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);
+}
+
+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 void
 build_append_nameseg(GArray *array, const char *seg)
 {
@@ -1875,6 +1997,159 @@ build_hdr:
  "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
 }
 
+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;
+
+cr

[PATCH v5 7/8] unit-test: Add testcase for pxb

2020-04-07 Thread Yubo Miao
From: miaoyubo 

Add testcase for pxb to make sure the ACPI table is correct for guest.

Signed-off-by: miaoyubo 
---
 tests/qtest/bios-tables-test.c | 58 ++
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 0a597bbacf..4bba680917 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -621,12 +621,21 @@ static void test_acpi_one(const char *params, test_data 
*data)
  * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
  * when arm/virt boad starts to support it.
  */
-args = g_strdup_printf("-machine %s %s -accel tcg -nodefaults 
-nographic "
-"-drive if=pflash,format=raw,file=%s,readonly "
-"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
-data->machine, data->tcg_only ? "" : "-accel kvm",
-data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
-
+if (data->cd) {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : 
"");
+} else {
+args = g_strdup_printf("-machine %s %s -accel tcg "
+"-nodefaults -nographic "
+"-drive if=pflash,format=raw,file=%s,readonly "
+"-drive if=pflash,format=raw,file=%s,snapshot=on %s",
+data->machine, data->tcg_only ? "" : "-accel kvm",
+data->uefi_fl1, data->uefi_fl2, params ? params : "");
+}
 } else {
 /* Disable kernel irqchip to be able to override apic irq0. */
 args = g_strdup_printf("-machine %s,kernel-irqchip=off %s -accel tcg "
@@ -961,6 +970,40 @@ static void test_acpi_virt_tcg_numamem(void)
 
 }
 
+#ifdef CONFIG_PXB
+static void test_acpi_virt_tcg_pxb(void)
+{
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+/*
+ * While using -cdrom, the cdrom would auto plugged into pxb-pcie,
+ * the reason is the bus of pxb-pcie is also root bus, it would lead
+ * to the error only PCI/PCIE bridge could plug onto pxb.
+ * Therefore,thr cdrom is defined and plugged onto the scsi controller
+ * to solve the conflicts.
+ */
+data.variant = ".pxb";
+test_acpi_one(" -device pcie-root-port,chassis=1,id=pci.1"
+  " -device virtio-scsi-pci,id=scsi0,bus=pci.1"
+  " -drive file="
+  
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2,"
+  "if=none,media=cdrom,id=drive-scsi0-0-0-1,readonly=on"
+  " -device scsi-cd,bus=scsi0.0,scsi-id=0,"
+  "drive=drive-scsi0-0-0-1,id=scsi0-0-0-1,bootindex=1"
+  " -cpu cortex-a57"
+  " -device pxb-pcie,bus_nr=128",
+  &data);
+
+free_test_data(&data);
+}
+#endif
+
 static void test_acpi_tcg_acpi_hmat(const char *machine)
 {
 test_data data;
@@ -1053,6 +1096,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt", test_acpi_virt_tcg);
 qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem);
 qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp);
+#ifdef CONFIG_PXB
+qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb);
+#endif
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.19.1





[PATCH v5 6/8] unit-test: The files changed.

2020-04-07 Thread Yubo Miao
From: miaoyubo 

The unit-test is seperated into three patches:
1. The files changed and list in bios-tables-test-allowed-diff.h
2. The unit-test
3. The binary file and clear bios-tables-test-allowed-diff.h

The ASL diff would also be listed.
Sice there are 1000+lines diff, some changes would be omitted.

  * Original Table Header:
  * Signature"DSDT"
- * Length   0x14BB (5307)
+ * Length   0x1E7A (7802)
  * Revision 0x02
- * Checksum 0xD1
+ * Checksum 0x57
  * OEM ID   "BOCHS "
  * OEM Table ID "BXPCDSDT"
  * OEM Revision 0x0001 (1)

+Device (PC80)
+{
+Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+Name (_ADR, Zero)  // _ADR: Address
+Name (_CCA, One)  // _CCA: Cache Coherency Attribute
+Name (_SEG, Zero)  // _SEG: PCI Segment
+Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
+Name (_UID, 0x80)  // _UID: Unique ID
+Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
+Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
+{
+Package (0x04)
+{
+0x,
+Zero,
+GSI0,
+Zero
+},
+

Packages are omitted.

+Package (0x04)
+{
+0x001F,
+0x03,
+GSI2,
+Zero
+}
+})
+Device (GSI0)
+{
+Name (_HID, "PNP0C0F" /* PCI Interrupt Link Device */)  // 
_HID: Hardware ID
+Name (_UID, Zero)  // _UID: Unique ID
+Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Method (_SRS, 1, NotSerialized)  // _SRS: Set Resource Settings
+{
+}
+}

GSI1,2,3 are omitted.

+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource Settings
+{
+WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+0x, // Granularity
+0x0080, // Range Minimum
+0x0080, // Range Maximum
+0x, // Translation Offset
+0x0001, // Length
+,, )
+})
+Name (SUPP, Zero)
+Name (CTRL, Zero)
+Method (_OSC, 4, NotSerialized)  // _OSC: Operating System 
Capabilities
+{
+CreateDWordField (Arg3, Zero, CDW1)
+If ((Arg0 == ToUUID ("33db4d5b-1ff7-401c-9657-7441c03dd766") 
/* PCI Host Bridge Device */))
+{
+CreateDWordField (Arg3, 0x04, CDW2)
+CreateDWordField (Arg3, 0x08, CDW3)
+SUPP = CDW2 /* \_SB_.PC80._OSC.CDW2 */
+CTRL = CDW3 /* \_SB_.PC80._OSC.CDW3 */
+CTRL &= 0x1F
+If ((Arg1 != One))
+{
+CDW1 |= 0x08
+}
+
+If ((CDW3 != CTRL))
+{
+CDW1 |= 0x10
+}
+
+CDW3 = CTRL /* \_SB_.PC80.CTRL */
+Return (Arg3)
+}
+Else
+{
+CDW1 |= 0x04
+Return (Arg3)
+}
+}

DSM is are omitted

 Device (PCI0)
 {
 Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
 WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
PosDecode,
 0x, // Granularity
 0x, // Range Minimum
-0x00FF, // Range Maximum
+0x007F, // Range Maximum
 0x, // Translation Offset
-0x0100, // Length
+0x0080, // Length

Signed-off-by: miaoyubo 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 1 +
 1 file changed, 1 insertion

[PATCH v5 4/8] acpi: Refactor the source of host bridge and build tables for pxb

2020-04-07 Thread Yubo Miao
From: miaoyubo 

The resources of pxbs and obtained by crs_build and the resources
used by pxbs would be moved form the resources defined for host-bridge.

The resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 131 +--
 1 file changed, 111 insertions(+), 20 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index e8ba09855c..7bcd04dfb7 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,9 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_bridge.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -266,19 +269,81 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+int i;
+Aml *method, *crs, *dev;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+CrsRangeEntry *entry;
+CrsRangeSet crs_range_set;
+
+crs_range_set_init(&crs_range_set);
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+PCIHostState *s = OBJECT_CHECK(PCIHostState,
+   object_resolve_path_type("",
+   "pcie-host-bridge", NULL),
+   TYPE_PCI_HOST_BRIDGE);
+
+PCIBus *bus = s->bus;
+/* start to construct the tables for pxb*/
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+/*
+ * Coded up the MIN of the busNr defined for pxb-pcie,
+ * the MIN - 1 would be the MAX bus number for the main
+ * host bridge.
+ */
+if (bus_num < nr_pcie_buses) {
+nr_pcie_buses = bus_num;
+}
+
+dev = aml_device("PC%.02X", bus_num);
+aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev, scope, irq);
+
+/*
+ * Resources deined for PXBs are composed by the folling parts:
+ * 1. The resources the pci-brige/pcie-root-port need.
+ * 2. The resources the devices behind pxb need.
+ */
+crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set);
+aml_append(dev, aml_name_decl("_CRS", crs));
+
+acpi_dsdt_add_pci_osc(dev, scope);
+
+aml_append(scope, dev);
+
+}
+}
 
-Aml *dev = aml_device("%s", "PCI0");
+/* start to construct the tables for main host bridge */
+dev = aml_device("%s", "PCI0");
 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
 aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
 aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
@@ -299,25 +364,51 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
 0x, 0x, nr_pcie_buses - 1, 0x,
 nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-  

[PATCH v5 5/8] acpi: align the size to 128k

2020-04-07 Thread Yubo Miao
From: miaoyubo 

If table size is changed between virt_acpi_build and
virt_acpi_build_update, the table size would not be updated to
UEFI, therefore, just align the size to 128kb, which is enough
and same with x86. It would warn if 64k is not enough and the
align size should be updated.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 7bcd04dfb7..89bb768b0c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -54,6 +54,8 @@
 #include "hw/pci/pci_bridge.h"
 #define ARM_SPI_BASE 32
 
+#define ACPI_BUILD_TABLE_SIZE 0x2
+
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 {
 uint16_t i;
@@ -883,6 +885,15 @@ struct AcpiBuildState {
 bool patched;
 } AcpiBuildState;
 
+static void acpi_align_size(GArray *blob, unsigned align)
+{
+/*
+ * Align size to multiple of given size. This reduces the chance
+ * we need to change size in the future (breaking cross version migration).
+ */
+g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
+}
+
 static
 void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
 {
@@ -953,6 +964,20 @@ void virt_acpi_build(VirtMachineState *vms, 
AcpiBuildTables *tables)
 build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
 }
 
+/*
+ * The align size is 128, warn if 64k is not enough therefore
+ * the align size could be resized.
+ */
+if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
+warn_report("ACPI table size %u exceeds %d bytes,"
+" migration may not work",
+tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
+error_printf("Try removing CPUs, NUMA nodes, memory slots"
+ " or PCI bridges.");
+}
+acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
+
+
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
 }
-- 
2.19.1





[PATCH v5 1/8] acpi:Extract two APIs from acpi_dsdt_add_pci

2020-04-07 Thread Yubo Miao
From: miaoyubo 

Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc form acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 129 ++-
 1 file changed, 72 insertions(+), 57 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 7ef0733d71..e8ba09855c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -146,29 +146,11 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, slot_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
 for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
@@ -204,41 +186,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -246,7 +198,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * identified by the Universal Unique IDentifier (UUID)
@@ -291,7 +244,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 
 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.6.1. _DSM for PCI Express Slot Information
  * The UUID in _DSM in this context is
  * {E5C937D0-3553-4D7A-9117-EA4D19C3434D}
@@ -309,6 +263,67 @@ static void acpi_dsdt_add_pci(

[PATCH v5 0/8] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-04-07 Thread Yubo Miao
From: miaoyubo 

Changes with v4
v5->v4: Not using specific resources for PXB.
Instead, the resources for pxb are composed of the bar space of the
pci-bridge/pcie-root-port behined it and the config space of devices
behind it.

Only if the bios(uefi for arm) support multiple roots,
configure space of devices behind pxbs could be obtained.
The uefi work is updated for discussion by the following link:
https://edk2.groups.io/g/devel/message/56901?p=,,,20,0,0,0::Created,,add+extra+roots+for+Arm,20,2,0,72723351
 
[PATCH] ArmVirtPkg/FdtPciHostBridgeLib: add extra roots for Arm.

Currently pxb-pcie is not supported by arm,
the reason for it is pxb-pcie is not described in DSDT table
and only one main host bridge is described in acpi tables,
which means it is not impossible to present different io numas
for different devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9


miaoyubo (8):
  acpi:Extract two APIs from acpi_dsdt_add_pci
  fw_cfg: Write the extra roots into the fw_cfg
  acpi:Extract crs build form acpi_build.c
  acpi: Refactor the source of host bridge and build tables for pxb
  acpi: align the size to 128k
  unit-test: The files changed.
  unit-test: Add testcase for pxb
  unit-test: add the binary file and clear diff.h

 hw/acpi/aml-build.c| 275 +++
 hw/arm/virt-acpi-build.c   | 251 ++---
 hw/arm/virt.c  |  23 +++
 hw/i386/acpi-build.c   | 285 -
 include/hw/acpi/aml-build.h|  23 +++
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 7802 bytes
 tests/qtest/bios-tables-test.c |  58 ++-
 7 files changed, 564 insertions(+), 351 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[PATCH v4 3/3] ACPI/unit-test: Add a new test for pxb-pcie for arm

2020-02-24 Thread Yubo Miao
From: miaoyubo 

Currently, pxb-pcie could be defined by the cmdline like
--device pxb-pcie,id=pci.9,bus_nr=128
However pxb-pcie is not described in acpi tables for arm.

The formal two patches support pxb-pcie for arm, escpcially the
specification for pxb-pcie in DSDT table.

Add a testcase to make sure the ACPI table is correct for guest.

The following table need to be added for this test:
tests/data/acpi/virt/DSDT.pxb
Since the ASL diff has 1000+ lines, it would be presented in
commit log with the simply diff. the diff are:
Device (PC80) is presented in DSDT.
Resources allocated for Device (PCI0) is changed.

  * Disassembling to symbolic ASL+ operators
  *
- * Disassembly of /home/DSDT, Mon Feb 24 19:35:28 2020
+ * Disassembly of /home/DSDT.pxb, Mon Feb 24 19:33:38 2020
  *
  * Original Table Header:
  * Signature"DSDT"
- * Length   0x14BB (5307)
+ * Length   0x1F70 (8048)
  * Revision 0x02
- * Checksum 0xD1
+ * Checksum 0xCF
  * OEM ID   "BOCHS "
  * OEM Table ID "BXPCDSDT"
  * OEM Revision 0x0001 (1)
 })
 }

+Device (PC80)
+{
+Name (_HID, "PNP0A08" /* PCI Express Bus */)  // _HID: Hardware ID
+Name (_CID, "PNP0A03" /* PCI Bus */)  // _CID: Compatible ID
+Name (_ADR, Zero)  // _ADR: Address
+Name (_CCA, One)  // _CCA: Cache Coherency Attribute
+Name (_SEG, Zero)  // _SEG: PCI Segment
+Name (_BBN, 0x80)  // _BBN: BIOS Bus Number
+Name (_UID, 0x80)  // _UID: Unique ID
+Name (_STR, Unicode ("pxb Device"))  // _STR: Description String
+Name (_PRT, Package (0x80)  // _PRT: PCI Routing Table
+{
+Package (0x04)
+{
+0x,
+Zero,
+GSI0,
+Zero
+},

Packages are omitted.

+
+Package (0x04)
+{
+0x001F,
+0x03,
+GSI2,
+Zero
+}
+})
+Device (GSI0)
+{
+Name (_HID, "PNP0C0F" /* PCI Interrupt Link Device */)  // 
_HID: Hardware ID
+Name (_UID, Zero)  // _UID: Unique ID
+Name (_PRS, ResourceTemplate ()  // _PRS: Possible Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Name (_CRS, ResourceTemplate ()  // _CRS: Current Resource 
Settings
+{
+Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, 
,, )
+{
+0x0023,
+}
+})
+Method (_SRS, 1, NotSerialized)  // _SRS: Set Resource Settings
+{
+}
+}
+

GSI1,2,3 are omitted.

+Method (_CBA, 0, NotSerialized)  // _CBA: Configuration Base 
Address
+{
+Return (0x00401000)
+}
+
+Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
+{
+Name (RBUF, ResourceTemplate ()
+{
+WordBusNumber (ResourceProducer, MinFixed, MaxFixed, 
PosDecode,
+0x, // Granularity
+0x0080, // Range Minimum
+0x0081, // Range Maximum
+0x, // Translation Offset
+0x0002, // Length
+,, )
+DWordMemory (ResourceProducer, PosDecode, MinFixed, 
MaxFixed, NonCacheable, ReadWrite,
+0x, // Granularity
+0x3E9F, // Range Minimum
+0x3EFE, // Range Maximum
+0x, // Translation Offset
+0x0060, // Length
+,, , AddressRangeMemory, TypeStatic)
+DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, 
EntireRange,
+0x, // Granularity
+0xC000, // Range Minimum
+0x, // Range Maximum
+0x3EFF, // Translation Offset
+0x4000, // Length
+,, , TypeStatic, DenseTranslation)
+QWordMemory (ResourceProducer, PosDecode, MinFixed, 
MaxFixed, NonCacheable, ReadWrite,
+0x, // Granularit

[PATCH v4 1/3] acpi:Extract two APIs from acpi_dsdt_add_pci

2020-02-24 Thread Yubo Miao
From: miaoyubo 

Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc form acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 129 ++-
 1 file changed, 72 insertions(+), 57 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index fb4b166f82..37c34748a6 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -146,29 +146,11 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, slot_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS);
 for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) {
@@ -204,41 +186,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -246,7 +198,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * identified by the Universal Unique IDentifier (UUID)
@@ -291,7 +244,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 
 method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.6.1. _DSM for PCI Express Slot Information
  * The UUID in _DSM in this context is
  * {E5C937D0-3553-4D7A-9117-EA4D19C3434D}
@@ -309,6 +263,67 @@ static void acpi_dsdt_add_pci(

[PATCH v4 2/3] acpi:pci-expender-bus: Add pxb support for arm

2020-02-24 Thread Yubo Miao
From: miaoyubo 

Currently virt machine is not supported by pxb-pcie,
and only one main host bridge described in ACPI tables.
In this patch,PXB-PCIE is supproted by arm and certain
resource is allocated for each pxb-pcie in acpi table.
The resource for the main host bridge is also reallocated.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 115 ---
 hw/arm/virt.c|   3 +
 include/hw/arm/virt.h|   7 +++
 3 files changed, 118 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 37c34748a6..be1986c60d 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,8 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -266,19 +268,116 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+Aml *method, *crs, *dev;
+int count = 0;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+/*
+ * 0x60 would be enough for pxb device
+ * if it is too small, there is no enough space
+ * for a pcie device plugged in a pcie-root port
+ */
+hwaddr size_addr = 0x60;
+hwaddr size_io = 0x4000;
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+PCIBus *bus = VIRT_MACHINE(vms)->bus;
+
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+/*
+ * Coded up the MIN of the busNr defined for pxb-pcie,
+ * the MIN - 1 would be the MAX bus number for the main
+ * host bridge.
+ */
+if (bus_num < nr_pcie_buses) {
+nr_pcie_buses = bus_num;
+}
+count++;
+dev = aml_device("PC%.02X", bus_num);
+aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev, scope, irq);
+
+method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(base_ecam)));
+aml_append(dev, method);
+
+method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
+Aml *rbuf = aml_resource_template();
+aml_append(rbuf,
+   aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED,
+   AML_POS_DECODE, 0x,
+   bus_num, bus_num + 1, 0x,
+   2));
+aml_append(rbuf,
+   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+AML_MAX_FIXED, AML_NON_CACHEABLE,
+AML_READ_WRITE, 0x,
+base_mmio + size_mmio -
+size_addr * count,
+base_mmio + size_mmio - 1 -
+size_addr * (count - 1),
+0x, size_addr));
+aml_append(rbuf,
+   aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED,
+   AML_POS_DECODE, AML_ENTIRE_RANGE,
+   0x, size_pio - size_io * count,
+   size_pio - 1 - size_io * (count - 1),
+   base_pi

[PATCH v4 0/3] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-02-24 Thread Yubo Miao
From: miaoyubo 

Currently pxb-pcie is not supported by arm, the reason for it is
pxb-pcie is not described in DSDT table and only one main host bridge
is described in acpi tables, which means it is not impossible to
present different io numas for different devices, especially
host-passthrough devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Since the bus of pxb-pcie is root bus, devices could not be plugged
into pxb-pcie directly,pcie-root-port or pci-bridge should be defined
and plugged on pxb-pcie, then the device could be plugged onto the
pcie-root-port or pci-bridge.

With the patches,io numa could be presented to the guest by define a
pxb-pcie with the numa and plug the device on it.

miaoyubo (3):
  acpi:Extract two APIs from acpi_dsdt_add_pci
  acpi:pci-expender-bus: Add pxb support for arm
  ACPI/unit-test: Add a new test for pxb-pcie for arm

 hw/arm/virt-acpi-build.c| 232 +++-
 hw/arm/virt.c   |   3 +
 include/hw/arm/virt.h   |   7 +
 tests/data/acpi/virt/DSDT.pxb   | Bin 0 -> 8048 bytes
 tests/qtest/bios-tables-test-allowed-diff.h |   1 +
 tests/qtest/bios-tables-test.c  |  54 -
 6 files changed, 233 insertions(+), 64 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[RFC v3 2/3] acpi:pci-expender-bus: Add pxb support for arm

2020-02-20 Thread Yubo Miao
From: miaoyubo 

Currently virt machine is not supported by pxb-pcie,
and only one main host bridge described in ACPI tables.
In this patch,PXB-PCIE is supproted by arm and certain
resource is allocated for each pxb-pcie in acpi table.
The resource for the main host bridge is also reallocated.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 125 +++
 hw/pci-host/gpex.c   |   4 ++
 include/hw/arm/virt.h|   7 +++
 3 files changed, 125 insertions(+), 11 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 0540234b8a..2c1e0d2aaa 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,8 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -271,19 +273,117 @@ static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs;
+Aml *method, *dev, *crs;
+int count = 0;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+/*
+ * 0x60 would be enough for pxb device
+ * if it is too small, there is no enough space
+ * for a pcie device plugged in a pcie-root port
+ */
+hwaddr size_addr = 0x60;
+hwaddr size_io = 0x4000;
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+int root_bus_limit = 0xFF;
+PCIBus *bus = NULL;
+bus = VIRT_MACHINE(vms)->bus;
+
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+if (bus_num < root_bus_limit) {
+root_bus_limit = bus_num - 1;
+}
+count++;
+dev = aml_device("PC%.02X", bus_num);
+aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev, method);
+}
+
+acpi_dsdt_add_pci_route_table(dev, scope, nr_pcie_buses, irq);
+
+method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(base_ecam)));
+aml_append(dev, method);
+
+method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
+Aml *rbuf = aml_resource_template();
+aml_append(rbuf,
+   aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED,
+   AML_POS_DECODE, 0x,
+   bus_num, bus_num + 1, 0x,
+   2));
+aml_append(rbuf,
+   aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+AML_MAX_FIXED, AML_NON_CACHEABLE,
+AML_READ_WRITE, 0x,
+base_mmio + size_mmio -
+size_addr * count,
+base_mmio + size_mmio - 1 -
+size_addr * (count - 1),
+0x, size_addr));
+aml_append(rbuf,
+   aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED,
+   AML_POS_DECODE, AML_ENTIRE_RANGE,
+   0x, size_pio - size_io * count,
+   size_pio - 1 - size_io * (count - 1),
+   base_pio, size_io));
+
+if (use_highmem) {
+hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
+   

[RFC v3 0/3] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-02-20 Thread Yubo Miao
From: miaoyubo 

Currently pxb-pcie is not supported by arm, the reason for it is
pxb-pcie is not described in DSDT table and only one main host bridge
is described in acpi tables, which means it is not impossible to
present different io numas for different devices, especially
host-passthrough devices.

This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Since the bus of pxb-pcie is root bus, devices could not be plugged
into pxb-pcie directly,pcie-root-port or pci-bridge should be defined
and plugged on pxb-pcie, then the device could be plugged onto the
pcie-root-port or pci-bridge.

With the patches,io numa could be presented to the guest by define a
pxb-pcie with the numa and plug the device on it.

miaoyubo (3):
  acpi:Extract two APIs from acpi_dsdt_add_pci
  acpi:pci-expender-bus: Add pxb support for arm
  ACPI/unit-test: Add a new test for pxb-pcie for arm

 hw/arm/virt-acpi-build.c   | 240 -
 hw/pci-host/gpex.c |   4 +
 include/hw/arm/virt.h  |   7 +
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 34209 bytes
 tests/qtest/bios-tables-test.c |  54 +++-
 5 files changed, 238 insertions(+), 67 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

-- 
2.19.1





[RFC v3 3/3] ACPI/unit-test: Add a new test for pxb-pcie for arm

2020-02-20 Thread Yubo Miao
From: miaoyubo 

Currently, pxb-pcie could be defined by the cmdline like
--device pxb-pcie,id=pci.9,bus_nr=128
However pxb-pcie is not described in acpi tables for arm.

The formal two patches support pxb-pcie for arm, escpcially the
specification for pxb-pcie in DSDT table.

Add a testcase to make sure the ACPI table is correct for guest.

Signed-off-by: miaoyubo 
---
 tests/data/acpi/virt/DSDT.pxb  | Bin 0 -> 34209 bytes
 tests/qtest/bios-tables-test.c |  54 +
 2 files changed, 48 insertions(+), 6 deletions(-)
 create mode 100644 tests/data/acpi/virt/DSDT.pxb

diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/virt/DSDT.pxb
new file mode 100644
index 
..4eea3192c75ff28f7054d626a9363ca025b6c0ad
GIT binary patch
literal 34209
zcmeI*cXU+szJ~D)1PGxe5PG+us9-{YGz}UAMT!L#ks?x*Dx!d5hoIPd
z?}}o>iWL;GW5HgrlKbvVM&HM??^)~qbMIProvd|8p2_U*%qO!m?AgcPkRQ(HLbszg^Hd*
zYT59@{GfDxK}u{$QSzH5MFX?4va_qcnOYVriD$G-YqqdX5KgQUqzA#0T0ymH9aJ-P
zt=#;Qdf_)p=V$jH6t9{xXmH68P3ev)8EFlwrs(=X$_(9dxJh>6UU8FZi5vcVla%Bp
zz50)g^-pXvw4i9XAYFAU@nN}Xb+t___n%uw)`8L
z7F4goX88!*;pB+$X8&bG_2BOj*;OO*!h6xx&B+mI)uU#l*o>||BPVi3ji?#5Y(|dH
z=oUF6C2B^h&FJPcx<}5a88su#W_0%%JtAk+ikeZ+X7unGJtJq-j+)WHX7uzKy&`9%
zM$JgK8NGZ)@5mW-qGmL*8NF>rHhzu%+CS2wW@OrogM3EhZpvShs#sHrYy`MIZnvrEQ2KtQX{j^2YjIK7L
z&}T&Nr!Avqbh8+KeGpGv;lrQ5@@4bw`Q^7iZ;W_0oY$Ob29%%1Indg_l(x
zNW=>U=@nIzyEz+7!38n{QgZ4pwa9l7gm>7)H=Rj93E*aK%`Pv$F
zgOo;fQ|eY!1OwuQSwZ6KYWg}mXjCt}JgvH-Ycgsma)L(nQ|eVz=ol|?y{Zbg(iIyd
zzE`=OuA0nnOU%j8vc92DN7u3EXJGTc)4rt-QqDz{ADgBn4&W%8;u
z5?ku3m0K#qEp?A7x70yl;<{B;Wvslaj+?5K$#iE;IBQnkX3|+Rv1RhkE8STOP8|vB
z9we`-<1BY7-B}yX+HlsUQ|ZoBI8!UPO#Vo8T;@)tJL|xyWB9~RukuGyhfbwC)8I^l
zQ^#@cRJyY+oOR)>OQ+JEdLdztXFWJ|+~-cEJL|()AI|!8D&5%t&IWMmIMJO-cQ%Bx
zA)F2ARJv2Iq0E^Mr;aP#sdQ%soEdOt(5ZB1BRCtuspC+0D&5%_&c<*yrc>$8OgJ;)
z)N!jjmF{c;XA?M^(5ZB1Q#hN#spDLCD&5%(&Sr2nqf_Zly~4D|vpJkPE_SEVoh{&O
z0cQ(3mF{c_XG=JB9PLh}J6plo3eHw^D&5%{&em}1xZ9mdcea7E4V-Q0RJyY*oNeLM
zak@K|?raBVJ2>0XsdQ(1INQUi<9c^0-Kn!8+7pt0vvq*81D#5D?g8f>aO!n{JC*L-
z6V5&1+>=hFJNJTfFF5tO!JSHX?hWVOaPCc~(w!aQ>*#*unaO!oEJC*J{5Y7YPJdjSMJ9RqFo^P|@)axpDD&48GaQ6F|4QDo;
zN_Xnqo3>0Id3J?UufyD_bf?a^Y0KpCZ4R6{bSmAc^K9nq2B%)Pxl`#*on13$cR0J#
zsdT5#shP6}oO+$-PNh3_Ce55Z;p|DL(w#bgX3k!4>UE(zmG0D8GjsNavp1becj{c3
zIS+zUuOr>5bf?acne$*c52jP;PMsGs=OJ+Fb*DR(?$p^ZbM}F=51mSP>KvFk`@*T$
zsqR#|Q)j-+c_^HR(y4T3KRElr*^f@8J9U=JoVjr3(y4T(&TW}956(O~mG0CTEpx`;
zjM1rdr_N((%j7HId^q#zRJv1VugqBhX91l`cj}y#Is3!epH8Jab*9Rk1K=D$r_!A|
zKV{B=a1NwX=}w)MGG`&2g>)+2sdG{0JPgjm=v2B>XQ0e^IGl&msdT5#JDGD3oP+38
zx>IMH%vl6y5uHkR>Kv0f2g5m-PNh3_X33mG;2c7y(w)U{7QIFE$$NII47EQPZa&Qdy+?i>y0XgEjHsdVR2
za2^HcQFJQZc{H3y!+A8FN_UpQSq5hrol19(fpZL;W9U@6^B6dff%6zTmF^r1=U6z$
z(y4UkI5@|_IgU=HJCB9)SU8WRQ|V5f@3!aLeO=LvKw-FYIM
zC&GCmol19}1m{U`oCRK(JQdDU
z=~TM&G&oO#^E5h@?wkteR5+*7sdVS*aGnn5>2xaHIStNfa89FB>CQ9YJOj=%=v2CM
zI-JwtoKC0GoipH^0p|=lmF}Dg=S(
zHk@a}c{ZI&cb)_1IdGmsr_!AZ;9LOb0y>rMTnOhvI2Y2Xbmt;C7s0uRPNh2+!?_sF
z#dIp&xdhH7a4w-!>CUBaE`@U`ol19}3+K6To=d0Foy*`{2In$5mF_$b&hy|rk4~jK
zm&3Un&gFC}-FZHo=finEol19J0Otj8UO=bPoh#s60p|)jmF`>#=SnzN(y4UkDmYic
zxr$DuJ1>OuLO3s^Q|Zo&;JgUVi|ACkb2Xf+;ap9p(w!H>c`=+9)2VdlC2(E>=OuJ1
z-FYdTm%@1|ol19J2IpmPUPhc%sdVQRa9#oD6?7`yc_o}z!g(c~N_Vb-
za}Atp=v2CMEu3rNTuZ0Yo#k+r!&y$J(w*zzTnFbmI+gCc3eKzGyoyexJFkZGYB;Z^
zQ|Zq2aIS}QJ)KH-UIXVfa9%^F(w*1Bc`cmR(y4Ukb#Pt>=XG={-FZEn*TZ=|ol1A!
z0Ot*G-ax0)oj1aHBb+zVsdVQ}aNY#xO>`>Vc{7|h!+A5EN_XA@=PhvFLZ{N5x59ZV
zoVU`cbmwhw-UjDwbSm9>JDj(}c{`m-cisW#9dO=3r_!Bw!g(j0chaeJ=Us5#1?OFK
zD&2WEoOi={H=Rm%-UH`7aNa|w(w+Chc`uyz(y4UkeQ@3f=Y4c4-FZKp_rrNVol18;
z0Otd6K0v3^oe#qKAe;}cRmg0({Mgbr_!Cz!1)ZE&(NuK=d*A=3+JCSiHdaDGjv
z(w*PH`3;=k(5ZCiw{U(7=eKk!-T57y-@*AEol19p59jxAeov>;oj<_&1Drq5sdVR$
zaQ+DAk8~>C`4gN!!TA%NN_YMY=g)BdOsCSFyWrdf=Po*x?)(MLU*PQ=sg$DTpr{X4?<_uyrj
zwaVfp@oH70s+PTmYgGTcQF}#`>Z77>&@Tve8f!u;!FOyyTI
zg7yDrx11UuUR)fc#)g#)3NriGDH{@xr7WEs#PUaGmk+GHYC=ZiwDi)VZ8^KzweGii
zoT=cXO;?lX&4G}~F!
zVq>hRyw0jg`T^FcRxSKP@A*=6p7rr~*5~7?^v6@r#F~>_W7PnUX9GT-N`E{X;_+;V$Fm_HPo+Pe>3BTT
z@pz^uwoJY;fYO~AaAv@nL8sE4jo@qqXCpe5?raQaV>lbrsdQ&1oSATD(y4T36F8f|
z*@RA|JDbAU6wan}D&48SXKjzt->u<6P1Tz~G^11L&gO77hqF1IN_Vz^vjvVP@1k5|5z
z$zE{oMW@o8IzHBx$u;MD!?`z|N_XmTSX(BaZ#%--kxr#M_knXCIQOAb>CS!O+!xM$
z=~TM26P%sk>_n&1o%_MLADsKqsdT4~-R<$*AI|;hRJ!v3I1hmH06LZK>CS98v*FC9Q|ZpGaCU{WE1gPr=D?W)
zXAYf8cXorb8=T$fRJyY}oZaEcvCXAe4+?(7L?PdIzhsdQ&AID5g_i%z9G
zd&Aiq&fat?-FXn42f=v|ol18e4Cldc9!#gworl1A2%Lw|sdQ%_IQziahfbwCb+*8s
zZ~Ma8mrkWS4~6qkI1i;$>CS#|_Jgw@ol1A+!kG(aE}cqu=E0cCSvO^Wn^=Q|ZnEI1At`pi}A2{&4n(vp=0mcMgDa0GtEpRJwB@oCDz;NT<@Bg>V+a
zSxBeSorl4B7@UXEsdVSza2^il;dCn9IS9@{a1NqV>CPfJi{LDxQ|ZpZa1MrZFr7+w
z4uNwBoI~hTy0aM0VmOQGRJwC0oI~LpN~hADC2*F&Swg4MopCthaK`CWx^ozu!{8i7
zr_!Cn;T#UCQ4Z%it`d
zQ|V5fme=3e$@6_<;2cAz(w)b^c?_J#(5ZCiSUAVRIhIbPJIBE}4$g6OD&2W3oX5g>
zES*Ys9tY=fa2`je(w*bs91rJsI+gA`9?s+8Jf2RaJ14+70nQ0@D&08|&WUhNq*Lk6
zNpMbra}u3OcTR?LGMtm?RJ!v7I8T7{1Ui-OJQ2x^oJgQ{bFJr_!CLz3g@YGD&2V+oTtHg8l6gaPK9$SoKxvk
zy7P26Plxk#I+gC62In+5r_rf&=NWLG0p}TXD&099&gpPYr&H<98F0>ka|WGCcg}=!
zCY&?rRJwB(oU`DZMW@o8XTo_VoM+Ohbmwe1XTv$0PNh4~g7Yjm&!SW5&N*<-fpZR>
zN_WnMb1

[RFC v3 1/3] acpi:Extract two APIs from acpi_dsdt_add_pci

2020-02-20 Thread Yubo Miao
From: miaoyubo 

Extract two APIs acpi_dsdt_add_pci_route_table and
acpi_dsdt_add_pci_osc form acpi_dsdt_add_pci. The first
API is used to specify the pci route table and the second
API is used to declare the operation system capabilities.
These two APIs would be used to specify the pxb-pcie in DSDT.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 135 ++-
 1 file changed, 75 insertions(+), 60 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..0540234b8a 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -151,30 +151,12 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  int nr_pcie_buses,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, bus_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
 for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
@@ -190,7 +172,6 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 }
 aml_append(dev, aml_name_decl("_PRT", rt_pkg));
 
-/* Create GSI link device */
 for (i = 0; i < PCI_NUM_PINS; i++) {
 uint32_t irqs =  irq + i;
 Aml *dev_gsi = aml_device("GSI%d", i);
@@ -210,42 +191,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_name_decl("RBUF", rbuf));
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -253,7 +203,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 aml_append(method,
 aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
 
-/* PCI Firmware Specification 3.0
+/*
+ * PCI Firmware Specification 3.0
  * 4.5.1. _OSC Interface for PCI Host Bridge Devices
  * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is
  * id

[RFC v2 0/1] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-02-17 Thread Yubo Miao
From: miaoyubo 

Currently pxb-pcie is not supported by arm and only one
main host bridge is described in acpi tables, which means
it is not impossible to present different io numas for different
devices. This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Since devices could not be plugged into pxb-pcie directly,pcie-root-port
or pci-bridge should be defined and plugged on pxb-pcie, then the device
could be plugged onto the pcie-root-port or pci-bridge. 

With the patches,io numa could be presented to the guest by define a pxb-pcie
with the numa and plug the device on it.

miaoyubo (1):
  arm: acpi: pci-expender-bus: Make arm to support PXB-PCIE

 hw/arm/virt-acpi-build.c | 240 +--
 hw/pci-host/gpex.c   |   4 +
 include/hw/arm/virt.h|   1 +
 3 files changed, 184 insertions(+), 61 deletions(-)

-- 
2.19.1





[RFC v2 1/1] arm: acpi: pci-expender-bus: Make arm to support PXB-PCIE

2020-02-17 Thread Yubo Miao
From: miaoyubo 

Currently virt machine is not supported by pxb-pcie,
and only one main host bridge described in ACPI tables.
Under this circumstance, different io numas for differnt devices
is not possible, in order to present io numas to the guest,
especially for host pssthrough devices. PXB-PCIE is supproted
by arm and certain resource is allocated for each pxb-pcie
in acpi table.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 240 +--
 hw/pci-host/gpex.c   |   4 +
 include/hw/arm/virt.h|   1 +
 3 files changed, 184 insertions(+), 61 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..fc11525042 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,8 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -151,30 +153,12 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+static void acpi_dsdt_add_pci_route_table(Aml *dev, Aml *scope,
+  int nr_pcie_buses,
+  uint32_t irq)
 {
-int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
 int i, bus_no;
-hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
-hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
-hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
-hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
-hwaddr base_ecam = memmap[ecam_id].base;
-hwaddr size_ecam = memmap[ecam_id].size;
-int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
-
-Aml *dev = aml_device("%s", "PCI0");
-aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
-aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
-aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
-aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
-aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
-aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
-aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
-aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
-
+Aml *method, *crs;
 /* Declare the PCI Routing Table. */
 Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
 for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
@@ -190,7 +174,6 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry 
*memmap,
 }
 aml_append(dev, aml_name_decl("_PRT", rt_pkg));
 
-/* Create GSI link device */
 for (i = 0; i < PCI_NUM_PINS; i++) {
 uint32_t irqs =  irq + i;
 Aml *dev_gsi = aml_device("GSI%d", i);
@@ -210,42 +193,11 @@ static void acpi_dsdt_add_pci(Aml *scope, const 
MemMapEntry *memmap,
 aml_append(dev_gsi, method);
 aml_append(dev, dev_gsi);
 }
+}
 
-method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
-aml_append(method, aml_return(aml_int(base_ecam)));
-aml_append(dev, method);
-
-method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
-Aml *rbuf = aml_resource_template();
-aml_append(rbuf,
-aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
-0x, 0x, nr_pcie_buses - 1, 0x,
-nr_pcie_buses));
-aml_append(rbuf,
-aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x, base_mmio,
- base_mmio + size_mmio - 1, 0x, size_mmio));
-aml_append(rbuf,
-aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
- AML_ENTIRE_RANGE, 0x, 0x, size_pio - 1, base_pio,
- size_pio));
-
-if (use_highmem) {
-hwaddr base_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].base;
-hwaddr size_mmio_high = memmap[VIRT_HIGH_PCIE_MMIO].size;
-
-aml_append(rbuf,
-aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
- AML_NON_CACHEABLE, AML_READ_WRITE, 0x,
- base_mmio_high,
- base_mmio_high + size_mmio_high - 1, 0x,
- size_mmio_high));
-}
-
-aml_append(method, aml_name_decl("RBUF", rbuf));
-aml_append(method, aml_return(rbuf));
-aml_append(dev, method);
-
+static void acpi_dsdt_add_pci_osc(Aml *dev, Aml *scope)
+{
+Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf;
 /* Declare an _OSC (OS Control Handoff) method */
 aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
 aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
@@ -253,7 +205,8 @@ static void acp

[RFC 1/2] arm: acpi: pci-expender-bus: Make arm to support PXB-PCIE

2020-02-13 Thread Yubo Miao
From: miaoyubo 

Currently virt machine is not supported by pxb-pcie,
and only one main host bridge described in ACPI tables.
Under this circumstance, different io numas for differnt devices
is not possible, in order to present io numas to the guest,
especially for host pssthrough devices. PXB-PCIE is supproted
by arm and certain resource is allocated for each pxb-pcie
in acpi table.

Signed-off-by: miaoyubo 
---
 hw/arm/virt-acpi-build.c | 234 +--
 hw/pci-host/gpex.c   |   4 +
 include/hw/arm/virt.h|   1 +
 3 files changed, 228 insertions(+), 11 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index bd5f771e9b..2e449d0098 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -49,6 +49,8 @@
 #include "kvm_arm.h"
 #include "migration/vmstate.h"
 
+#include "hw/arm/virt.h"
+#include "hw/pci/pci_bus.h"
 #define ARM_SPI_BASE 32
 
 static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
@@ -152,20 +154,227 @@ static void acpi_dsdt_add_virtio(Aml *scope,
 }
 
 static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
-  uint32_t irq, bool use_highmem, bool 
highmem_ecam)
+  uint32_t irq, bool use_highmem, bool 
highmem_ecam,
+  VirtMachineState *vms)
 {
 int ecam_id = VIRT_ECAM_ID(highmem_ecam);
-Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
+Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf, *dev;
 int i, bus_no;
+int count = 0;
 hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
 hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
 hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
 hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
 hwaddr base_ecam = memmap[ecam_id].base;
 hwaddr size_ecam = memmap[ecam_id].size;
+/*
+ * 0x60 would be enough for pxb device
+ * if it is too small, there is no enough space
+ * for a pcie device plugged in a pcie-root port
+ */
+hwaddr size_addr = 0x60;
+hwaddr size_io = 0x4000;
 int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
+int root_bus_limit = 0xFF;
+PCIBus *bus = NULL;
+bus = VIRT_MACHINE(vms)->bus;
+
+if (bus) {
+QLIST_FOREACH(bus, &bus->child, sibling) {
+uint8_t bus_num = pci_bus_num(bus);
+uint8_t numa_node = pci_bus_numa_node(bus);
+
+if (!pci_bus_is_root(bus)) {
+continue;
+}
+if (bus_num < root_bus_limit) {
+root_bus_limit = bus_num - 1;
+}
+count++;
+dev = aml_device("PC%.02X", bus_num);
+aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08")));
+aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
+aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device")));
+if (numa_node != NUMA_NODE_UNASSIGNED) {
+method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
+aml_append(method, aml_return(aml_int(numa_node)));
+aml_append(dev, method);
+}
+/* Declare the PCI Routing Table. */
+Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
+for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
+for (i = 0; i < PCI_NUM_PINS; i++) {
+int gsi = (i + bus_no) % (PCI_NUM_PINS);
+Aml *pkg = aml_package(4);
+aml_append(pkg, aml_int((bus_no << 16) | 0x));
+aml_append(pkg, aml_int(i));
+aml_append(pkg, aml_name("GSI%d", gsi));
+aml_append(pkg, aml_int(0));
+aml_append(rt_pkg, pkg);
+}
+}
+aml_append(dev, aml_name_decl("_PRT", rt_pkg));
+
+for (i = 0; i < PCI_NUM_PINS; i++) {
+uint32_t irqs =  irq + i;
+Aml *dev_gsi = aml_device("GSI%d", i);
+aml_append(dev_gsi, aml_name_decl("_HID",
+   aml_string("PNP0C0F")));
+aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
+crs = aml_resource_template();
+aml_append(crs,
+   aml_interrupt(AML_CONSUMER, AML_LEVEL,
+ AML_ACTIVE_HIGH,
+ AML_EXCLUSIVE, &irqs, 1));
+aml_append(dev_gsi, aml_name_decl("_PRS", crs));
+crs = aml_resource_template();
+aml_appe

[RFC 2/2] pci-expender-bus:Add pcie-root-port to pxb-pcie under arm.

2020-02-13 Thread Yubo Miao
From: miaoyubo 

Since devices could not directly plugged into pxb-pcie, under arm, one
pcie-root port is plugged into pxb-pcie. Due to the bus for each pxb-pcie
is defined as 2 in acpi dsdt tables(one for pxb-pcie, one for pcie-root-port),
only one device could be plugged into one pxb-pcie.

Signed-off-by: miaoyubo 
---
 hw/pci-bridge/pci_expander_bridge.c | 9 +
 include/hw/pci/pcie_port.h  | 1 +
 2 files changed, 10 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 47aaaf8fd1..3d896dd452 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,6 +15,7 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_port.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
@@ -233,7 +234,15 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 
 ds = qdev_create(NULL, TYPE_PXB_HOST);
 if (pcie) {
+#ifdef __aarch64__
+bus = pci_root_bus_new(ds, "pxb-pcie-internal",
+   NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
+bds = qdev_create(BUS(bus), "pcie-root-port");
+bds->id = dev_name;
+qdev_prop_set_uint8(bds, PCIE_ROOT_PORT_PROP_CHASSIS, pxb->bus_nr);
+#else
 bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
+#endif
 } else {
 bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, 
TYPE_PXB_BUS);
 bds = qdev_create(BUS(bus), "pci-bridge");
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 4b3d254b08..b41d473220 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -64,6 +64,7 @@ int pcie_chassis_add_slot(struct PCIESlot *slot);
 void pcie_chassis_del_slot(PCIESlot *s);
 
 #define TYPE_PCIE_ROOT_PORT "pcie-root-port-base"
+#define PCIE_ROOT_PORT_PROP_CHASSIS "chassis"
 #define PCIE_ROOT_PORT_CLASS(klass) \
  OBJECT_CLASS_CHECK(PCIERootPortClass, (klass), TYPE_PCIE_ROOT_PORT)
 #define PCIE_ROOT_PORT_GET_CLASS(obj) \
-- 
2.19.1





[RFC 0/2] pci_expander_brdige:acpi:Support pxb-pcie for ARM

2020-02-13 Thread Yubo Miao
From: miaoyubo 

Currently pxb-pcie is not supported by arm and only one
main host bridge is described in acpi tables, which means
it is not impossible to present different io numas for different
devices. This series of patches make arm to support PXB-PCIE.

Users can configure pxb-pcie with certain numa, Example command
is:

   -device pxb-pcie,id=pci.7,bus_nr=128,numa_node=0,bus=pcie.0,addr=0x9

Since devices could not be plugged into pxb-pcie directly, one
pcie-root-port is auto plugged into the pxb, therefore, the devices
could be plugged into pxb-pcie.

With the patches,io numa could be presented to the guest by define a pxb-pcie
with the numa and plug the device into the pxb-pcie.

miaoyubo (2):
  arm: acpi: pci-expender-bus: Make arm to support PXB-PCIE
  pci-expender-bus:Add pcie-root-port to pxb-pcie under arm.

 hw/arm/virt-acpi-build.c| 234 ++--
 hw/pci-bridge/pci_expander_bridge.c |   9 ++
 hw/pci-host/gpex.c  |   4 +
 include/hw/arm/virt.h   |   1 +
 include/hw/pci/pcie_port.h  |   1 +
 5 files changed, 238 insertions(+), 11 deletions(-)

-- 
2.19.1