Message ID | 20200217111818.766-2-miaoyubo@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | pci_expander_brdige:acpi:Support pxb-pcie for ARM | expand |
On Mon, Feb 17, 2020 at 07:18:18PM +0800, Yubo Miao wrote: > From: miaoyubo <miaoyubo@huawei.com> > > 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 <miaoyubo@huawei.com> A unit test would be nic. > --- > 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, > - 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, > - nr_pcie_buses)); > - aml_append(rbuf, > - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, > - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, > - base_mmio + size_mmio - 1, 0x0000, size_mmio)); > - aml_append(rbuf, > - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, > - AML_ENTIRE_RANGE, 0x0000, 0x0000, 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, 0x0000, > - base_mmio_high, > - base_mmio_high + size_mmio_high - 1, 0x0000, > - 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 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) > @@ -298,7 +251,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} > @@ -316,6 +270,170 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, > buf = aml_buffer(1, byte_list); > aml_append(method, aml_return(buf)); > aml_append(dev, method); > +} > + > +static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, > + uint32_t irq, bool use_highmem, bool highmem_ecam, > + VirtMachineState *vms) > +{ > + int ecam_id = VIRT_ECAM_ID(highmem_ecam); > + 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; > + /* > + * 0x600000 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 = 0x600000; > + 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, 0x0000, > + bus_num, bus_num + 1, 0x0000, > + 2)); > + aml_append(rbuf, > + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, > + AML_MAX_FIXED, AML_NON_CACHEABLE, > + AML_READ_WRITE, 0x0000, > + base_mmio + size_mmio - > + size_addr * count, > + base_mmio + size_mmio - 1 - > + size_addr * (count - 1), > + 0x0000, size_addr)); > + aml_append(rbuf, > + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, > + AML_POS_DECODE, AML_ENTIRE_RANGE, > + 0x0000, (size_pio) / 2 - size_io * count, > + (size_pio / 2) - 1 - size_io * (count - 1), > + base_pio, size_io)); > + > + 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, 0x0000, > + base_mmio_high + size_mmio_high - > + size_addr * count, > + base_mmio_high + size_mmio_high - > + 1 - size_addr * (count - 1), > + 0x0000, size_addr)); > + } > + > + aml_append(method, aml_name_decl("RBUF", rbuf)); > + aml_append(method, aml_return(rbuf)); > + aml_append(dev, method); > + > + acpi_dsdt_add_pci_osc(dev, scope); > + > + Aml *dev_rp0 = aml_device("%s", "RP0"); > + aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0))); > + aml_append(dev, dev_rp0); > + > + aml_append(scope, dev); > + > + } > + } > + > + 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))); > + > + 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, > + 0x0000, 0x0000, root_bus_limit, 0x0000, > + root_bus_limit + 1)); > + aml_append(rbuf, > + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, > + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, > + base_mmio + size_mmio - 1 - size_addr * count, > + 0x0000, size_mmio - size_addr * count)); > + aml_append(rbuf, > + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, > + AML_ENTIRE_RANGE, 0x0000, 0x0000, > + size_pio / 2 - 1 - size_io * count, base_pio, > + size_pio / 2 - size_io * count)); > + > + 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, 0x0000, > + base_mmio_high, > + base_mmio_high + size_mmio_high - 1 - > + size_addr * count, > + 0x0000, size_mmio_high - size_addr * count)); > + } > + > + aml_append(method, aml_name_decl("RBUF", rbuf)); > + aml_append(method, aml_return(rbuf)); > + aml_append(dev, method); > + > + acpi_dsdt_add_pci_osc(dev, scope); > > Aml *dev_rp0 = aml_device("%s", "RP0"); > aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0))); this will be easier to review if you first refactor existing code, then add pxb support on top. > @@ -744,7 +862,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) > acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], > (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); > acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), > - vms->highmem, vms->highmem_ecam); > + vms->highmem, vms->highmem_ecam, vms); > if (vms->acpi_dev) { > build_ged_aml(scope, "\\_SB."GED_DEVICE, > HOTPLUG_HANDLER(vms->acpi_dev), > diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c > index 0ca604dc62..2c18cdfec4 100644 > --- a/hw/pci-host/gpex.c > +++ b/hw/pci-host/gpex.c > @@ -36,6 +36,7 @@ > #include "hw/qdev-properties.h" > #include "migration/vmstate.h" > #include "qemu/module.h" > +#include "hw/arm/virt.h" > > /**************************************************************************** > * GPEX host > @@ -98,6 +99,9 @@ static void gpex_host_realize(DeviceState *dev, Error **errp) > pci_swizzle_map_irq_fn, s, &s->io_mmio, > &s->io_ioport, 0, 4, TYPE_PCIE_BUS); > > +#ifdef __aarch64__ > + VIRT_MACHINE(qdev_get_machine())->bus = pci->bus; > +#endif > qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); > pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq); > qdev_init_nofail(DEVICE(&s->gpex_root)); What does all this have to do with building on aarch64? > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h > index 71508bf40c..cfc65dd19b 100644 > --- a/include/hw/arm/virt.h > +++ b/include/hw/arm/virt.h > @@ -140,6 +140,7 @@ typedef struct { > DeviceState *gic; > DeviceState *acpi_dev; > Notifier powerdown_notifier; > + PCIBus *bus; > } VirtMachineState; Again one bus per machine? Pls give this field a better name and add some comments. > > #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM) > -- > 2.19.1 >
> -----Original Message----- > From: Michael S. Tsirkin [mailto:mst@redhat.com] > Sent: Monday, February 17, 2020 9:09 PM > To: miaoyubo <miaoyubo@huawei.com> > Cc: peter.maydell@linaro.org; shannon.zhaosl@gmail.com; Xiexiangyou > <xiexiangyou@huawei.com>; imammedo@redhat.com; qemu- > devel@nongnu.org > Subject: Re: [RFC v2 1/1] arm: acpi: pci-expender-bus: Make arm to support > PXB-PCIE > > On Mon, Feb 17, 2020 at 07:18:18PM +0800, Yubo Miao wrote: > > From: miaoyubo <miaoyubo@huawei.com> > > > > 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 <miaoyubo@huawei.com> > > A unit test would be nic. > Thanks for replying, I will add the unit test in patch V3. > > --- > > 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 > > > > + 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, > > + 0x0000, 0x0000, root_bus_limit, 0x0000, > > + root_bus_limit + 1)); > > + aml_append(rbuf, > > + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, > AML_MAX_FIXED, > > + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, > base_mmio, > > + base_mmio + size_mmio - 1 - size_addr * count, > > + 0x0000, size_mmio - size_addr * count)); > > + aml_append(rbuf, > > + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, > AML_POS_DECODE, > > + AML_ENTIRE_RANGE, 0x0000, 0x0000, > > + size_pio / 2 - 1 - size_io * count, base_pio, > > + size_pio / 2 - size_io * count)); > > + > > + 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, 0x0000, > > + base_mmio_high, > > + base_mmio_high + size_mmio_high - 1 - > > + size_addr * count, > > + 0x0000, size_mmio_high - size_addr * count)); > > + } > > + > > + aml_append(method, aml_name_decl("RBUF", rbuf)); > > + aml_append(method, aml_return(rbuf)); > > + aml_append(dev, method); > > + > > + acpi_dsdt_add_pci_osc(dev, scope); > > > > Aml *dev_rp0 = aml_device("%s", "RP0"); > > aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0))); > > > this will be easier to review if you first refactor existing code, then add pxb > support on top. > Thanks for the suggestion, the next patch would separate this patch into two patches, one is to refactor existing code and another one add pxb support. > > @@ -744,7 +862,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, > VirtMachineState *vms) > > acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], > > (irqmap[VIRT_MMIO] + ARM_SPI_BASE), > NUM_VIRTIO_TRANSPORTS); > > acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + > ARM_SPI_BASE), > > - vms->highmem, vms->highmem_ecam); > > + vms->highmem, vms->highmem_ecam, vms); > > if (vms->acpi_dev) { > > build_ged_aml(scope, "\\_SB."GED_DEVICE, > > HOTPLUG_HANDLER(vms->acpi_dev), diff --git > > a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index 0ca604dc62..2c18cdfec4 > > 100644 > > --- a/hw/pci-host/gpex.c > > +++ b/hw/pci-host/gpex.c > > @@ -36,6 +36,7 @@ > > #include "hw/qdev-properties.h" > > #include "migration/vmstate.h" > > #include "qemu/module.h" > > +#include "hw/arm/virt.h" > > > > > /********************************************************** > ****************** > > * GPEX host > > @@ -98,6 +99,9 @@ static void gpex_host_realize(DeviceState *dev, Error > **errp) > > pci_swizzle_map_irq_fn, s, &s->io_mmio, > > &s->io_ioport, 0, 4, > > TYPE_PCIE_BUS); > > > > +#ifdef __aarch64__ > > + VIRT_MACHINE(qdev_get_machine())->bus = pci->bus; #endif > > qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); > > pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq); > > qdev_init_nofail(DEVICE(&s->gpex_root)); > > > What does all this have to do with building on aarch64? > > gpex.c is the public file for Generic PCI Express Bridge Emulation, using aarch64 to avoid affect other architectures > > diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index > > 71508bf40c..cfc65dd19b 100644 > > --- a/include/hw/arm/virt.h > > +++ b/include/hw/arm/virt.h > > @@ -140,6 +140,7 @@ typedef struct { > > DeviceState *gic; > > DeviceState *acpi_dev; > > Notifier powerdown_notifier; > > + PCIBus *bus; > > } VirtMachineState; > > Again one bus per machine? Pls give this field a better name and add some > comments. > Not one bus, the bus include the root bus and all pxb-pcie buses. it is pointer to the device objects. By go through the bus, we get the pxbs defined and also the numa_node, the usage and the name is just the same with X86.(also PCIBus *bus in PCMachineState) The comments would be add in next patch ,And do u have any suggestion for the better name? > > > > #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : > > VIRT_PCIE_ECAM) > > -- > > 2.19.1 > > Regards, Miao
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, - 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, - nr_pcie_buses)); - aml_append(rbuf, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, - base_mmio + size_mmio - 1, 0x0000, size_mmio)); - aml_append(rbuf, - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - AML_ENTIRE_RANGE, 0x0000, 0x0000, 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, 0x0000, - base_mmio_high, - base_mmio_high + size_mmio_high - 1, 0x0000, - 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 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) @@ -298,7 +251,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} @@ -316,6 +270,170 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, buf = aml_buffer(1, byte_list); aml_append(method, aml_return(buf)); aml_append(dev, method); +} + +static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, + uint32_t irq, bool use_highmem, bool highmem_ecam, + VirtMachineState *vms) +{ + int ecam_id = VIRT_ECAM_ID(highmem_ecam); + 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; + /* + * 0x600000 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 = 0x600000; + 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, 0x0000, + bus_num, bus_num + 1, 0x0000, + 2)); + aml_append(rbuf, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, + AML_MAX_FIXED, AML_NON_CACHEABLE, + AML_READ_WRITE, 0x0000, + base_mmio + size_mmio - + size_addr * count, + base_mmio + size_mmio - 1 - + size_addr * (count - 1), + 0x0000, size_addr)); + aml_append(rbuf, + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, + AML_POS_DECODE, AML_ENTIRE_RANGE, + 0x0000, (size_pio) / 2 - size_io * count, + (size_pio / 2) - 1 - size_io * (count - 1), + base_pio, size_io)); + + 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, 0x0000, + base_mmio_high + size_mmio_high - + size_addr * count, + base_mmio_high + size_mmio_high - + 1 - size_addr * (count - 1), + 0x0000, size_addr)); + } + + aml_append(method, aml_name_decl("RBUF", rbuf)); + aml_append(method, aml_return(rbuf)); + aml_append(dev, method); + + acpi_dsdt_add_pci_osc(dev, scope); + + Aml *dev_rp0 = aml_device("%s", "RP0"); + aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0))); + aml_append(dev, dev_rp0); + + aml_append(scope, dev); + + } + } + + 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))); + + 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, + 0x0000, 0x0000, root_bus_limit, 0x0000, + root_bus_limit + 1)); + aml_append(rbuf, + aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, + AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_mmio, + base_mmio + size_mmio - 1 - size_addr * count, + 0x0000, size_mmio - size_addr * count)); + aml_append(rbuf, + aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, + AML_ENTIRE_RANGE, 0x0000, 0x0000, + size_pio / 2 - 1 - size_io * count, base_pio, + size_pio / 2 - size_io * count)); + + 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, 0x0000, + base_mmio_high, + base_mmio_high + size_mmio_high - 1 - + size_addr * count, + 0x0000, size_mmio_high - size_addr * count)); + } + + aml_append(method, aml_name_decl("RBUF", rbuf)); + aml_append(method, aml_return(rbuf)); + aml_append(dev, method); + + acpi_dsdt_add_pci_osc(dev, scope); Aml *dev_rp0 = aml_device("%s", "RP0"); aml_append(dev_rp0, aml_name_decl("_ADR", aml_int(0))); @@ -744,7 +862,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), - vms->highmem, vms->highmem_ecam); + vms->highmem, vms->highmem_ecam, vms); if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(vms->acpi_dev), diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index 0ca604dc62..2c18cdfec4 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -36,6 +36,7 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "qemu/module.h" +#include "hw/arm/virt.h" /**************************************************************************** * GPEX host @@ -98,6 +99,9 @@ static void gpex_host_realize(DeviceState *dev, Error **errp) pci_swizzle_map_irq_fn, s, &s->io_mmio, &s->io_ioport, 0, 4, TYPE_PCIE_BUS); +#ifdef __aarch64__ + VIRT_MACHINE(qdev_get_machine())->bus = pci->bus; +#endif qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus)); pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq); qdev_init_nofail(DEVICE(&s->gpex_root)); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 71508bf40c..cfc65dd19b 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -140,6 +140,7 @@ typedef struct { DeviceState *gic; DeviceState *acpi_dev; Notifier powerdown_notifier; + PCIBus *bus; } VirtMachineState; #define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)