Re: [Qemu-devel] [RFC v5 0/6] pci_expander_brdige: support separate pci domain for pxb-pcie

2018-09-24 Thread Zihan Yang
Hi Marcel,

Marcel Apfelbaum  于2018年9月20日周四 下午2:39写道:
>
>   Hi Zihan,
>
> On 09/18/2018 04:41 PM, Michael S. Tsirkin wrote:
> > Cc Laine, Eric for an opinion about the management interface.
> >
> > On Mon, Sep 17, 2018 at 10:57:31PM +0800, Zihan Yang wrote:
> >> Hi all
> >>
> >> Here is a minimal working version of supporting multiple pci domains.
> >> The next a few paragraphs will illustrate the purpose and use example.
> >> Current issue and limitations will be in last 2 paragraphs, followed
> >> by the changelog of each verison.
> >>
> >> Currently only q35 host bridge is allocated an item in MCFG table, all
> >> pxb-pcie host bridges stay within pci domain 0. This series of patches
> >> allow each pxb-pcie to be put in separate pci domain, allocating a new
> >> MCFG table item for it.
> >>
> >> Users can configure whether to put pxb host bridge into separate domain
> >> by specifying property 'domain_nr' of pxb-pcie device. 'bus_nr' property
> >> indicates the Base Bus Number(BBN) of the pxb-pcie host bridge. Another
> >> property max_bus specifies the maximum desired bus numbers to reduce
> >> MCFG space cost. Example command is
> >>
> >>  -device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1,max_bus=15
> >>
> >> Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
> >> (15+1)=16 buses, which is much smaller than the default 256 buses.
> >>
> >> Compared with previous version, this version is much simpler because
> >> mcfg of extra domain now has a relatively fixed address, as suggested
> >> by Marcel and Gerd. Putting extra mmconfig above 4G and let seabios
> >> leave them for guest os will be expected in next version. The range is
> >> [0x8000, 0xb000), which allows us to hold 4x busses compared
> >> with before.
> >>
> >> A complete command line for test is follows, you need to replace 
> >> GUEST_IMAGE,
> >> DATA_IMAGE and SEABIOS_BIN with proper environment variable
> >>
> >> ./x86_64-softmmu/qemu-system-x86_64 \
> >>  -machine q35,accel=kvm -smp 2 -m 2048 \
> >>  -drive file=${GUEST_IMAGE}  -netdev user,id=realnet0 \
> >>  -device e1000e,netdev=realnet0,mac=52:54:00:12:34:56 \
> >>  -device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1 \
> >>  -device pcie-root-port,id=rp1,bus=bridge3,addr=1c.0,port=8,chassis=8 \
> >>  -drive if=none,id=drive0,file=${DATA_IMAGE} \
> >>  -device virtio-scsi-pci,id=scsi,bus=rp1,addr=00.0 \
> >>  -bios ${SEABIOS_BIN}
> >>
> >> There are a few limitations, though
> >> 1. Legacy interrupt routing is not dealt with yet. There is only support 
> >> for
> >> devices using MSI/MSIX
> > That's probably a must have. What makes it hard to add?
>
> Zihan, can you please elaborate on what is the exact problem?
> pxb-pcie devices placed in PCI domain 0 do support
> legacy  interrupts, the question is what is different for multiple
> PCI domains.

Sorry for the delay. One problem I know of interrupt is that pxb-pcie in domain
0 directly maps irq to pci root of q35 host. In multiple domains they are under
different pci root, so we need to change the routing rule and modify PRT
table of pxb pcie host to route interrupt to ich9. But pxb does not have ISA
under it, I'm not sure whether this would be a problem.

It seems to require some engineering effort, but first I'm trying to figure out
another issue: why the same device under domain 1 will also appear in domain 0.
I find there are many resource allocation failure for device under domain 1,
dmesg shows

[0.179664] pci 0001:00:00.0: BAR 14: no space for [mem size 0x0010]
[0.179667] pci 0001:00:00.0: BAR 14: failed to assign [mem size 0x0010]
[0.179668] pci 0001:00:00.0: BAR 13: no space for [io  size 0x1000]
[0.179670] pci 0001:00:00.0: BAR 13: failed to assign [io  size 0x1000]
[0.179672] pci 0001:00:00.0: BAR 0: no space for [mem size 0x0100 64bit]
[0.179673] pci 0001:00:00.0: BAR 0: failed to assign [mem size
0x0100 64bit]
[0.179676] pci 0001:01:10.0: BAR 6: no space for [mem size 0x0004 pref]
[0.179678] pci 0001:01:10.0: BAR 6: failed to assign [mem size
0x0004 pref]
[0.179680] pci 0001:01:10.0: BAR 0: no space for [mem size 0x0002]
[0.179681] pci 0001:01:10.0: BAR 0: failed to assign [mem size 0x0002]

A humble guess is that the pxb host bus is a child bus of pxb-pcie, which might
be scanned twice during initialization of q35 and pxb host bus and causes the
potential resource conflict. But that is just a guess now, not quite
sure it is the
issue of qemu or seabios. I will try to find out.

> Thanks,
> Marcel
>
> >
>
> [...]



Re: [Qemu-devel] [RFC v5 0/6] pci_expander_brdige: support separate pci domain for pxb-pcie

2018-09-24 Thread Zihan Yang
Marcel Apfelbaum  于2018年9月20日周四 下午2:41写道:
>
> Hi Zihan, Gerd
>
> On 09/20/2018 09:09 AM, Gerd Hoffmann wrote:
>  As for the management, will some checks when adding mcfg be enough for
>  management? Or I can maintain a variable to indicate how many space
>  have been consumed and warn the user if they exceed the threshold?
>  The latter allows us to do the check when the pxb-pcie is initializing.
> >>> I think qemu should not apply any restrictions here.
> >> But will that confuse users when their device is not listed in guest os
> >> while qemu does not throw any error/warning?
> > Well, that can happen anyway.  For example when using an old seabios
> > version without pci domain support, or other firmware without pci domain
> > support (coreboot, ovmf).  And there is no easy way for qemu to figure
> > this beforehand.
> >
> > You can detect this later, when generating the acpi tables, that there
> > are expander bridges where the hidden pci bar wasn't configured by the
> > firmware.  Logging a warning in that case - pointing out the missing
> > firmware support - is probably a good idea.
>
> Logging a warning if the pxb-pci was not configured is enough I think.
> It will also help in case QEMU uses other firmware not supporting
> multiple PCI domains at all, e.g. OVMF  (for now), or an older SeaBIOS.

OK, will be added in next version.

>
> Thanks,
> Marcel
>
> > cheers,
> >Gerd
> >
>



Re: [Qemu-devel] [RFC v5 0/6] pci_expander_brdige: support separate pci domain for pxb-pcie

2018-09-19 Thread Zihan Yang
Gerd Hoffmann  于2018年9月19日周三 下午12:26写道:
>
> > > > 2. Only 4x devices is supported, you need to be careful not to overuse
> > >
> > > Could you elaborate on this please? What happens if you are not careful?
> > > How does management know what the limits are?
> >
> > It means the user might use more space than 768MB for mmconfig,
> > which is [0x8000m 0xb000). If such situation happens,  seabios
> > will ignore all extra pxb-pcie devices and not adding e820 entry for them,
> > which makes all the devices under them unworkable.
>
> Ypu should clearly note that this is a limitation of the seabios support
> patches then, so not an issue of the qemu patches.

OK, description will be clearer in next version.

> > As for the management, will some checks when adding mcfg be enough for
> > management? Or I can maintain a variable to indicate how many space
> > have been consumed and warn the user if they exceed the threshold?
> > The latter allows us to do the check when the pxb-pcie is initializing.
>
> I think qemu should not apply any restrictions here.

But will that confuse users when their device is not listed in guest os
while qemu does not throw any error/warning?

> cheers,
>   Gerd
>

Thanks,
Zihan



Re: [Qemu-devel] [RFC v5 0/6] pci_expander_brdige: support separate pci domain for pxb-pcie

2018-09-18 Thread Zihan Yang
Michael S. Tsirkin  于2018年9月18日周二 下午9:41写道:
>
> Cc Laine, Eric for an opinion about the management interface.
>
> On Mon, Sep 17, 2018 at 10:57:31PM +0800, Zihan Yang wrote:
> > Hi all
> >
> > Here is a minimal working version of supporting multiple pci domains.
> > The next a few paragraphs will illustrate the purpose and use example.
> > Current issue and limitations will be in last 2 paragraphs, followed
> > by the changelog of each verison.
> >
> > Currently only q35 host bridge is allocated an item in MCFG table, all
> > pxb-pcie host bridges stay within pci domain 0. This series of patches
> > allow each pxb-pcie to be put in separate pci domain, allocating a new
> > MCFG table item for it.
> >
> > Users can configure whether to put pxb host bridge into separate domain
> > by specifying property 'domain_nr' of pxb-pcie device. 'bus_nr' property
> > indicates the Base Bus Number(BBN) of the pxb-pcie host bridge. Another
> > property max_bus specifies the maximum desired bus numbers to reduce
> > MCFG space cost. Example command is
> >
> > -device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1,max_bus=15
> >
> > Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
> > (15+1)=16 buses, which is much smaller than the default 256 buses.
> >
> > Compared with previous version, this version is much simpler because
> > mcfg of extra domain now has a relatively fixed address, as suggested
> > by Marcel and Gerd. Putting extra mmconfig above 4G and let seabios
> > leave them for guest os will be expected in next version. The range is
> > [0x8000, 0xb000), which allows us to hold 4x busses compared
> > with before.
> >
> > A complete command line for test is follows, you need to replace 
> > GUEST_IMAGE,
> > DATA_IMAGE and SEABIOS_BIN with proper environment variable
> >
> > ./x86_64-softmmu/qemu-system-x86_64 \
> > -machine q35,accel=kvm -smp 2 -m 2048 \
> > -drive file=${GUEST_IMAGE}  -netdev user,id=realnet0 \
> > -device e1000e,netdev=realnet0,mac=52:54:00:12:34:56 \
> > -device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1 \
> > -device pcie-root-port,id=rp1,bus=bridge3,addr=1c.0,port=8,chassis=8 \
> > -drive if=none,id=drive0,file=${DATA_IMAGE} \
> > -device virtio-scsi-pci,id=scsi,bus=rp1,addr=00.0 \
> > -bios ${SEABIOS_BIN}
> >
> > There are a few limitations, though
> > 1. Legacy interrupt routing is not dealt with yet. There is only support for
> >devices using MSI/MSIX
>
> That's probably a must have. What makes it hard to add?

I will try to support it in the next one or two versions. In previous
versoin, I was
trying to support legacy interrupt, but I was also trying to figure
out a way for
seabios to configure pxb-pcie devices whose mmconfig are above 4g. That makes
things a little bit complicated for me to locate whether a problem is caused by
incorrect AML or wrong interrupt routing or incomplete support in seabios.
Therefore, I jsut leave legacy interrupt at the moment and make it work first,
as suggested by Marcel. Now that it is indeed working, I think I will support
legacy interrupt in future versions.

> > 2. Only 4x devices is supported, you need to be careful not to overuse
>
> Could you elaborate on this please? What happens if you are not careful?
> How does management know what the limits are?

It means the user might use more space than 768MB for mmconfig,
which is [0x8000m 0xb000). If such situation happens,  seabios
will ignore all extra pxb-pcie devices and not adding e820 entry for them,
which makes all the devices under them unworkable.

As for the management, will some checks when adding mcfg be enough for
management? Or I can maintain a variable to indicate how many space
have been consumed and warn the user if they exceed the threshold?
The latter allows us to do the check when the pxb-pcie is initializing.

In future versions, I will try to put such 'extra' mmconfig above 4g and
completely let guest os configure them, as suggested by Gerd. By then,
the number limits may no longer be a problem, but I think you might want to
put some limits on it for now.
> > 3. I have not fully tested the functionality of devices under separate 
> > domain
> >yet, but Linux can recognize then when typing `lspci`
> >
> > Current issue:
> > * SCSI storage device will be recognized twice, one in domain 0 as 
> > :01.0,
> >   the other in domain 1 as 0001:01.0. I will try to fix it in next version
> >
> > v5 <- v4:
> > - Refactor the design and place pxb-pcie's mcfg in [0x8000, 0xb000)
> > - QEMU 

Re: [Qemu-devel] [RFC v5 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-09-18 Thread Zihan Yang
Gerd Hoffmann  于2018年9月18日周二 下午1:09写道:
>
>   Hi,
>
> > +static void pxb_pcie_host_get_mmcfg_base(Object *obj, Visitor *v, const 
> > char *name,
>
> > +void *opaque, Error **errp)
> > +{
> > +PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
> > +
> > +visit_type_uint64(v, name, >size, errp);
>   
>
> cut bug?

Thanks for pointing out. I was wondering how I got the right behavior with
wrong code, then I find I somehow fix it in patch 3/6... It will be solved in
next version.

> cheers,
>   Gerd
>



[Qemu-devel] [RFC v5 5/6] pci_expander_bridge: add config_write callback for pxb-pcie

2018-09-17 Thread Zihan Yang
This allows SeaBIOS to configure MCFG base during initialization.
The mcfg size is calculated using based on desired bus number

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 37 +
 include/hw/pci-bridge/pci_expander_bridge.h |  7 ++
 2 files changed, 44 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 1e1999d..09413df 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -20,6 +20,7 @@
 #include "hw/pci-bridge/pci_expander_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
+#include "qemu/units.h"
 #include "sysemu/numa.h"
 #include "qapi/visitor.h"
 
@@ -395,6 +396,41 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
 pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 }
 
+static void pxb_pcie_update_pciexbar(PXBDev *pxb)
+{
+PCIDevice *pci_dev = PCI_DEVICE(pxb);
+PCIBus *pxb_bus = pci_get_bus(pci_dev);
+BusState *bus = BUS(QLIST_FIRST(_bus->child));
+PCIExpressHost *pehb = PCIE_HOST_BRIDGE(bus->parent);
+
+uint64_t addr;
+uint32_t length;
+int enable;
+
+addr = pci_get_quad(pci_dev->config + PXB_PCIE_HOST_BRIDGE_MCFG_BAR);
+enable = addr & PXB_PCIE_HOST_BRIDGE_ENABLE;
+addr &= PXB_PCIE_HOST_BRIDGE_PCIEXBAR_ADMSK;
+length = (pxb->max_bus - pxb->bus_nr + 1) * MiB;
+
+pcie_host_mmcfg_update(pehb, enable, addr, length);
+}
+
+static void pxb_pcie_config_write(PCIDevice *d, uint32_t address,
+  uint32_t val, int len)
+{
+PXBDev *pxb = PXB_PCIE_DEV(d);
+
+pci_default_write_config(d, address, val, len);
+
+/* Since desired bus number is provided by pxb-pcie,
+   we just need seabios to decide the mcfg_base for us.
+   mcfg_size can be calculated easily */
+if (ranges_overlap(address, len, PXB_PCIE_HOST_BRIDGE_MCFG_BAR,
+   PXB_PCIE_HOST_BRIDGE_MCFG_BAR_SIZE)) {
+pxb_pcie_update_pciexbar(pxb);
+}
+}
+
 static Property pxb_dev_properties[] = {
 /* Note: 0 is not a legal PXB bus number. */
 DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
@@ -459,6 +495,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, 
void *data)
 k->vendor_id = PCI_VENDOR_ID_REDHAT;
 k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
 k->class_id = PCI_CLASS_BRIDGE_HOST;
+k->config_write = pxb_pcie_config_write;
 
 dc->desc = "PCI Express Expander Bridge";
 dc->props = pxb_pcie_dev_properties;
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index e017c62..5be0a8e 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -2,6 +2,7 @@
 #define HW_PCI_EXPANDER_H
 
 #include "hw/pci/pcie_host.h"
+#include "hw/pci-host/q35.h"
 
 #define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
 #define PXB_PCIE_HOST_DEVICE(obj) \
@@ -13,4 +14,10 @@ typedef struct PXBPCIEHost {
 /*< public >*/
 } PXBPCIEHost;
 
+#define PXB_PCIE_HOST_BRIDGE_MCFG_BAR   0x50/* 64bit register 
*/
+#define PXB_PCIE_HOST_BRIDGE_MCFG_BAR_SIZE  8
+#define PXB_PCIE_HOST_BRIDGE_ENABLE MCH_HOST_BRIDGE_PCIEXBAREN
+/* The mcfg_base of pxb-pcie is not 256MB-aligned, but MB-aligned */
+#define PXB_PCIE_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 20)
+
 #endif
-- 
2.7.4




[Qemu-devel] [RFC v5 4/6] i386/acpi-build: describe new pci domain in AML

2018-09-17 Thread Zihan Yang
Describe new pci segments of host bridges in AML as new pci devices,
with _SEG and _BBN to let them be in DSDT.

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c | 53 +---
 1 file changed, 30 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9b49b0e..00b9aff 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1879,10 +1879,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 crs_range_set_init(_range_set);
 bus = PC_MACHINE(machine)->bus;
+i = 1; // PCI0 is q35 host, pxb starts from PCI1
 if (bus) {
 QLIST_FOREACH(bus, >child, sibling) {
 uint8_t bus_num = pci_bus_num(bus);
 uint8_t numa_node = pci_bus_numa_node(bus);
+uint32_t domain_num = pci_bus_domain_num(bus);
 
 /* look only for expander root buses */
 if (!pci_bus_is_root(bus)) {
@@ -1894,9 +1896,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 
 scope = aml_scope("\\_SB");
-dev = aml_device("PC%.02X", bus_num);
+dev = aml_device("PCI%d", i++);
 aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
 aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
+aml_append(dev, aml_name_decl("_SEG", aml_int(domain_num)));
 aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
 if (pci_bus_is_express(bus)) {
 aml_append(dev, build_q35_osc_method());
@@ -2130,35 +2133,39 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 {
 Object *pci_host;
 PCIBus *bus = NULL;
+int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
+while (pci_host) {
 bus = PCI_HOST_BRIDGE(pci_host)->bus;
-}
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+if (bus) {
+Aml *scope = aml_scope("PCI%d", index);
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
-if (TPM_IS_TIS(tpm_find())) {
-dev = aml_device("ISA.TPM");
-aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
-aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
-/*
-FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
-Rewrite to take IRQ from TPM device model and
-fix default IRQ value there to use some unused IRQ
- */
-/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
+/* Only add TPM once in pci domain 0 */
+if (index++ == 0 && TPM_IS_TIS(tpm_find())) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", 
aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+}
+
+aml_append(sb_scope, scope);
 }
 
-aml_append(sb_scope, scope);
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
 }
 }
 
-- 
2.7.4




[Qemu-devel] [RFC v5 0/6] pci_expander_brdige: support separate pci domain for pxb-pcie

2018-09-17 Thread Zihan Yang
Hi all

Here is a minimal working version of supporting multiple pci domains.
The next a few paragraphs will illustrate the purpose and use example.
Current issue and limitations will be in last 2 paragraphs, followed
by the changelog of each verison.

Currently only q35 host bridge is allocated an item in MCFG table, all
pxb-pcie host bridges stay within pci domain 0. This series of patches
allow each pxb-pcie to be put in separate pci domain, allocating a new
MCFG table item for it.

Users can configure whether to put pxb host bridge into separate domain
by specifying property 'domain_nr' of pxb-pcie device. 'bus_nr' property
indicates the Base Bus Number(BBN) of the pxb-pcie host bridge. Another
property max_bus specifies the maximum desired bus numbers to reduce
MCFG space cost. Example command is

-device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1,max_bus=15

Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
(15+1)=16 buses, which is much smaller than the default 256 buses.

Compared with previous version, this version is much simpler because
mcfg of extra domain now has a relatively fixed address, as suggested
by Marcel and Gerd. Putting extra mmconfig above 4G and let seabios
leave them for guest os will be expected in next version. The range is
[0x8000, 0xb000), which allows us to hold 4x busses compared
with before.

A complete command line for test is follows, you need to replace GUEST_IMAGE,
DATA_IMAGE and SEABIOS_BIN with proper environment variable

./x86_64-softmmu/qemu-system-x86_64 \
-machine q35,accel=kvm -smp 2 -m 2048 \
-drive file=${GUEST_IMAGE}  -netdev user,id=realnet0 \
-device e1000e,netdev=realnet0,mac=52:54:00:12:34:56 \
-device pxb-pcie,id=bridge3,bus="pcie.0",domain_nr=1 \
-device pcie-root-port,id=rp1,bus=bridge3,addr=1c.0,port=8,chassis=8 \
-drive if=none,id=drive0,file=${DATA_IMAGE} \
-device virtio-scsi-pci,id=scsi,bus=rp1,addr=00.0 \
-bios ${SEABIOS_BIN}

There are a few limitations, though
1. Legacy interrupt routing is not dealt with yet. There is only support for
   devices using MSI/MSIX
2. Only 4x devices is supported, you need to be careful not to overuse
3. I have not fully tested the functionality of devices under separate domain
   yet, but Linux can recognize then when typing `lspci`

Current issue:
* SCSI storage device will be recognized twice, one in domain 0 as :01.0,
  the other in domain 1 as 0001:01.0. I will try to fix it in next version

v5 <- v4:
- Refactor the design and place pxb-pcie's mcfg in [0x8000, 0xb000)
- QEMU only decides the desired mcfg_size and leaves mcfg_base for seabios
- Does not connect PXBDev and PXBPCIEHost with link property anymore, but
  with the pcibus under them, which makes code simpler.

v4 <- v3:
- Fix bug in setting mcfg table
- bus_nr is not used when pxb-pcie is in a new pci domain

v3 <- v2:
- Replace duplicate properties in pxb pcie host with link property to PXBDev
- Allow seabios to access config space and data space of expander bridge
  through a different ioport, because 0xcf8 is attached only to sysbus.
- Add a new property start_bus to indicate the BBN of pxb host bridge. The
  bus_nr property is used as the bus number of pxb-pcie device on pcie.0 bus

v2 <- v1:
- Allow user to configure whether to put pxb-pcie into seperate domain
- Add AML description part of each host bridge
- Modify the location of MCFG space to between RAM hotplug and pci hole64

Many thanks to 
Please let me know if you have any suggestions.

Zihan Yang (6):
  pci_expander_bridge: add type TYPE_PXB_PCIE_HOST
  pci_expander_bridge: add domain_nr and max_bus property for pxb-pcie
  acpi-build: allocate mcfg for pxb-pcie host bridges
  i386/acpi-build: describe new pci domain in AML
  pci_expander_bridge: add config_write callback for pxb-pcie
  pci_expander_bridge: inform seabios of desired mcfg size via hidden
bar

 hw/i386/acpi-build.c| 162 ++
 hw/pci-bridge/pci_expander_bridge.c | 172 +++-
 hw/pci/pci.c|  30 -
 include/hw/pci-bridge/pci_expander_bridge.h |  25 
 include/hw/pci/pci.h|   2 +
 include/hw/pci/pci_bus.h|   2 +
 include/hw/pci/pci_host.h   |   2 +-
 7 files changed, 336 insertions(+), 59 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




[Qemu-devel] [RFC v5 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-09-17 Thread Zihan Yang
The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
add a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 86 +++--
 1 file changed, 82 insertions(+), 4 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..a052c4c 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,10 +15,12 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
+#include "qapi/visitor.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
@@ -40,6 +42,9 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_BUS_NR "bus_nr"
+#define PROP_PXB_NUMA_NODE "numa_node"
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
@@ -49,6 +54,16 @@ typedef struct PXBDev {
 uint16_t numa_node;
 } PXBDev;
 
+#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
+#define PXB_PCIE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
+
+typedef struct PXBPCIEHost {
+/*< private >*/
+PCIExpressHost parent_obj;
+/*< public >*/
+} PXBPCIEHost;
+
 static PXBDev *convert_to_pxb(PCIDevice *dev)
 {
 return pci_bus_is_express(pci_get_bus(dev))
@@ -142,6 +157,40 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static void pxb_pcie_host_get_mmcfg_base(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
+static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
+static void pxb_pcie_host_initfn(Object *obj)
+{
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4);
+memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
+  "pci-conf-data", 4);
+
+object_property_add(obj, PCIE_HOST_MCFG_BASE, "uint64",
+ pxb_pcie_host_get_mmcfg_base,
+ NULL, NULL, NULL, NULL);
+
+object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64",
+ pxb_pcie_host_get_mmcfg_size,
+ NULL, NULL, NULL, NULL);
+}
+
 static void pxb_host_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
@@ -161,6 +210,27 @@ static const TypeInfo pxb_host_info = {
 .class_init= pxb_host_class_init,
 };
 
+static void pxb_pcie_host_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
+PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
+
+dc->fw_name = "pcie";
+/* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself 
*/
+dc->user_creatable = false;
+sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
+hc->root_bus_path = pxb_host_root_bus_path;
+}
+
+static const TypeInfo pxb_pcie_host_info = {
+.name  = TYPE_PXB_PCIE_HOST,
+.parent= TYPE_PCIE_HOST_BRIDGE,
+.instance_size = sizeof(PXBPCIEHost),
+.instance_init = pxb_pcie_host_initfn,
+.class_init= pxb_pcie_host_class_init,
+};
+
 /*
  * Registers the PXB bus as a child of pci host root bus.
  */
@@ -228,10 +298,11 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 dev_name = dev->qdev.id;
 }
 
-ds = qdev_create(NULL, TYPE_PXB_HOST);
 if (pcie) {
+ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
 bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
 } else {
+ds = qdev_create(NULL, TYPE_PXB_HOST);
 bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, 
TYPE_PXB_BUS);
 bds = qdev_create(BUS(bus), "pci-bridge");
 bds->id = dev_name;
@@ -289,8 +360,14 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
 
 static Property pxb_dev_properties[] = {
 /* Note: 0 is not a legal PXB bus number. */
-DEFINE_PROP_U

[Qemu-devel] [RFC v5 2/6] pci_expander_bridge: add domain_nr and max_bus property for pxb-pcie

2018-09-17 Thread Zihan Yang
pxb-pcie resides in pci domain 0 by default and users can not specify the
domain number. This patch adds 2 new property 'domain_nr' and 'max_bus'
to pxb-pcie device.

The first property allows user to choose a non-zero pci domain so that
they can hopefully add more pcie devices without being restricted by
the 256 bus number of a single pci domain.

The second property max_bus allows user to specify the desired busses
to be used in the new domain. Since each pcie bus needs 1MB config
space, a full pci domain occupies 256MB, which is quite expensive.
But most times user may only want a sub-range of busses(e.g. [3,9]),
this is when max_bus becomes useful. By reducing the memory each
domain consumes, we can support more domains in a limited space.

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 23 +--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index a052c4c..20fec50 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -42,6 +42,8 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
+#define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_BUS_NR "bus_nr"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
@@ -52,6 +54,8 @@ typedef struct PXBDev {
 
 uint8_t bus_nr;
 uint16_t numa_node;
+uint32_t domain_nr; /* PCI domain, non-zero means separate domain */
+uint8_t max_bus;/* max bus number to use(including this one) */
 } PXBDev;
 
 #define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
@@ -81,6 +85,14 @@ static int pxb_bus_num(PCIBus *bus)
 return pxb->bus_nr;
 }
 
+static int pxb_domain_num(PCIBus *bus)
+{
+PXBDev *pxb = convert_to_pxb(bus->parent_dev);
+
+/* for pxb, this should always be zero */
+return pxb->domain_nr;
+}
+
 static bool pxb_is_root(PCIBus *bus)
 {
 return true; /* by definition */
@@ -122,7 +134,7 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 PXBBus *bus = pci_bus_is_express(rootbus) ?
   PXB_PCIE_BUS(rootbus) : PXB_BUS(rootbus);
 
-snprintf(bus->bus_path, 8, ":%02x", pxb_bus_num(rootbus));
+snprintf(bus->bus_path, 8, "%04x:%02x", pxb_domain_num(rootbus), 
pxb_bus_num(rootbus));
 return bus->bus_path;
 }
 
@@ -275,7 +287,10 @@ static gint pxb_compare(gconstpointer a, gconstpointer b)
 {
 const PXBDev *pxb_a = a, *pxb_b = b;
 
-return pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
+/* compare domain_nr first, then bus_nr */
+return pxb_a->domain_nr < pxb_b->domain_nr ? -1 :
+   pxb_a->domain_nr > pxb_b->domain_nr ?  1 :
+   pxb_a->bus_nr < pxb_b->bus_nr ? -1 :
pxb_a->bus_nr > pxb_b->bus_nr ?  1 :
0;
 }
@@ -299,6 +314,7 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 }
 
 if (pcie) {
+g_assert (pxb->domain_nr == 0 || pxb->max_bus >= pxb->bus_nr);
 ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
 bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
 } else {
@@ -368,6 +384,9 @@ static Property pxb_dev_properties[] = {
 static Property pxb_pcie_dev_properties[] = {
 DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
 DEFINE_PROP_UINT16(PROP_PXB_NUMA_NODE, PXBDev, numa_node, 
NUMA_NODE_UNASSIGNED),
+DEFINE_PROP_UINT32(PROP_PXB_PCIE_DOMAIN_NR, PXBDev, domain_nr, 0),
+/* set a small default value, bus range is [bus_nr, max_bus] */
+DEFINE_PROP_UINT8(PROP_PXB_PCIE_MAX_BUS, PXBDev, max_bus, 15),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.7.4




[Qemu-devel] [RFC v5 6/6] pci_expander_bridge: inform seabios of desired mcfg size via hidden bar

2018-09-17 Thread Zihan Yang
pxb-pcie may only consumes a subset of 256 busses in a pci domain, but seabios
does not know it unless pxb-pcies passes it to seabios. This patch places
desired mcfg size into a hidden pci bar. The size is calculated based on
desired bus number of a pxb-pcie

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 5 +
 include/hw/pci-bridge/pci_expander_bridge.h | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 09413df..661de7c 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -370,6 +370,11 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK);
 pci_config_set_class(dev->config, PCI_CLASS_BRIDGE_HOST);
 
+if (pcie && pxb->domain_nr > 0) {
+   pci_set_long(dev->config + PXB_PCIE_HOST_BRIDGE_MCFG_SIZE,
+(pxb->max_bus - pxb->bus_nr + 1) * MiB);
+}
+
 pxb_dev_list = g_list_insert_sorted(pxb_dev_list, pxb, pxb_compare);
 return;
 
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 5be0a8e..9103eaa 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -20,4 +20,6 @@ typedef struct PXBPCIEHost {
 /* The mcfg_base of pxb-pcie is not 256MB-aligned, but MB-aligned */
 #define PXB_PCIE_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 20)
 
+#define PXB_PCIE_HOST_BRIDGE_MCFG_SIZE  0x58/* 32bit register 
*/
+
 #endif
-- 
2.7.4




[Qemu-devel] [RFC v5 3/6] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-09-17 Thread Zihan Yang
Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
corresponding MCFG space for them. This allows user-defined pxb-pcie
host bridges to be placed in different pci domain than q35 host.

The pci_host_bridges list is changed to be tail list to ensure the q35 host
is always the first element when traversing the list, because q35 host is
inserted beofre pxb-pcie hosts

A few new callbacks are added to PCIBusClass to get domain number and
max_bus property of a given PCIBus. Only pxb-pcie with a non-zero domain
number will have an item in MCFG table, others will still reside in pci
domain 0 under q35 host

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 109 +---
 hw/pci-bridge/pci_expander_bridge.c |  51 +
 hw/pci/pci.c|  30 +++-
 include/hw/pci-bridge/pci_expander_bridge.h |  16 
 include/hw/pci/pci.h|   2 +
 include/hw/pci/pci_bus.h|   2 +
 include/hw/pci/pci_host.h   |   2 +-
 7 files changed, 167 insertions(+), 45 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e1ee8ae..9b49b0e 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -55,6 +55,7 @@
 #include "hw/i386/ich9.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "hw/i386/x86-iommu.h"
 
 #include "hw/acpi/aml-build.h"
@@ -89,6 +90,10 @@
 typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
+uint32_t domain_nr;
+uint8_t start_bus;
+uint8_t end_bus;
+QTAILQ_ENTRY(AcpiMcfgInfo) next;
 } AcpiMcfgInfo;
 
 typedef struct AcpiPmInfo {
@@ -119,6 +124,9 @@ typedef struct AcpiBuildPciBusHotplugState {
 bool pcihp_bridge_en;
 } AcpiBuildPciBusHotplugState;
 
+static QTAILQ_HEAD(, AcpiMcfgInfo) mcfg =
+ QTAILQ_HEAD_INITIALIZER(mcfg);
+
 static void init_common_fadt_data(Object *o, AcpiFadtData *data)
 {
 uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
@@ -2427,18 +2435,28 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 }
 
 static void
-build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
+build_mcfg_q35(GArray *table_data, BIOSLinker *linker)
 {
-AcpiTableMcfg *mcfg;
+AcpiTableMcfg *mcfg_tbl;
 const char *sig;
-int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
-
-mcfg = acpi_data_push(table_data, len);
-mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-/* Only a single allocation so no need to play with segments */
-mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-mcfg->allocation[0].start_bus_number = 0;
-mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
+int len, count = 0;
+AcpiMcfgInfo *info;
+
+QTAILQ_FOREACH(info, , next) {
+count++;
+}
+
+len = sizeof(*mcfg_tbl) + count * sizeof(mcfg_tbl->allocation[0]);
+
+mcfg_tbl = acpi_data_push(table_data, len);
+
+count = 0;
+QTAILQ_FOREACH(info, , next) {
+mcfg_tbl->allocation[count].address = cpu_to_le64(info->mcfg_base);
+mcfg_tbl->allocation[count].pci_segment = cpu_to_le16(info->domain_nr);
+mcfg_tbl->allocation[count].start_bus_number = info->start_bus;
+mcfg_tbl->allocation[count++].end_bus_number = info->end_bus;
+}
 
 /* MCFG is used for ECAM which can be enabled or disabled by guest.
  * To avoid table size changes (which create migration issues),
@@ -2446,13 +2464,13 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
  * but set the signature to a reserved value in this case.
  * ACPI spec requires OSPMs to ignore such tables.
  */
-if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
+if (QTAILQ_FIRST()->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
 /* Reserved signature: ignored by OSPM */
 sig = "QEMU";
 } else {
 sig = "MCFG";
 }
-build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
+build_header(linker, table_data, (void *)mcfg_tbl, sig, len, 1, NULL, 
NULL);
 }
 
 /*
@@ -2606,25 +2624,66 @@ struct AcpiBuildState {
 MemoryRegion *linker_mr;
 } AcpiBuildState;
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+static inline void cleanup_mcfg(void)
+{
+AcpiMcfgInfo *cfg, *tmp;
+
+QTAILQ_FOREACH_SAFE (cfg, , next, tmp) {
+QTAILQ_REMOVE(, cfg, next);
+free(cfg);
+}
+}
+
+static bool acpi_get_mcfg(void)
 {
 Object *pci_host;
 QObject *o;
+AcpiMcfgInfo *info;
+uint8_t bus_nr = 0, end_bus = 255;
+uint32_t domain_nr = 0, mcfg_size = MCH_HOST_BRIDGE_PCIEXBAR_MAX;
+

Re: [Qemu-devel] [SeaBIOS] [RFC v2 0/3] Support multiple pci domains in pci_device

2018-08-27 Thread Zihan Yang
Gerd Hoffmann  于2018年8月27日周一 上午7:04写道:
>
>   Hi,
>
> > >   However, QEMU only binds port 0xcf8 and 0xcfc to
> > > bus pcie.0. To avoid bus confliction, we should use other port pairs for
> > > busses under new domains.
> >
> > I would skip support for IO based configuration and use only MMCONFIG
> > for extra root buses.
> >
> > The question remains: how do we assign MMCONFIG space for
> > each PCI domain.
>
> Allocation-wise it would be easiest to place them above 4G.  Right after
> memory, or after etc/reserved-memory-end (if that fw_cfg file is
> present), where the 64bit pci bars would have been placed.  Move the pci
> bars up in address space to make room.
>
> Only problem is that seabios wouldn't be able to access mmconfig then.
>
> Placing them below 4G would work at least for a few pci domains.  q35
> mmconfig bar is placed at 0xb000 -> 0xbfff, basically for
> historical reasons.  Old qemu versions had 2.75G low memory on q35 (up
> to 0xafff), and I think old machine types still have that for live
> migration compatibility reasons.  Modern qemu uses 2G only, to make
> gigabyte alignment work.
>
> 32bit pci bars are placed above 0xc000.  The address space from 2G
> to 2.75G (0x800 -> 0xafff) is unused on new machine types.
> Enough room for three additional mmconfig bars (full size), so four
> pci domains total if you add the q35 one.

Maybe we can support 4 domains first before we come up
with a better solution. But I'm not sure if four domains are
enough for those who want too many devices?

> cheers,
>   Gerd
>



Re: [Qemu-devel] [RFC v4 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-26 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月25日周六 下午8:08写道:
>
> Hi Zihan,
>
> On 08/19/2018 04:51 AM, Zihan Yang wrote:
> > Hi Marcel,
> >
> > Marcel Apfelbaum  于2018年8月18日周六 上午1:14写道:
> >> Hi Zihan,
> >>
> >> On 08/09/2018 09:33 AM, Zihan Yang wrote:
> >>> The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> >>> change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe
> >>>
> >>> Signed-off-by: Zihan Yang 
> >>> ---
> >>>hw/pci-bridge/pci_expander_bridge.c | 127 
> >>> ++--
> >>>1 file changed, 122 insertions(+), 5 deletions(-)
> >>>
> >>> diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> >>> b/hw/pci-bridge/pci_expander_bridge.c
> >>> index e62de42..6dd38de 100644
> >>> --- a/hw/pci-bridge/pci_expander_bridge.c
> >>> +++ b/hw/pci-bridge/pci_expander_bridge.c
> >>> @@ -15,10 +15,12 @@
> >>>#include "hw/pci/pci.h"
> >>>#include "hw/pci/pci_bus.h"
> >>>#include "hw/pci/pci_host.h"
> >>> +#include "hw/pci/pcie_host.h"
> >>>#include "hw/pci/pci_bridge.h"
> >>>#include "qemu/range.h"
> >>>#include "qemu/error-report.h"
> >>>#include "sysemu/numa.h"
> >>> +#include "qapi/visitor.h"
> >>>
> >>>#define TYPE_PXB_BUS "pxb-bus"
> >>>#define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
> >>> @@ -40,11 +42,20 @@ typedef struct PXBBus {
> >>>#define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
> >>>#define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), 
> >>> TYPE_PXB_PCIE_DEVICE)
> >>>
> >>> +#define PROP_PXB_PCIE_DEV "pxbdev"
> >>> +
> >>> +#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
> >>> +#define PROP_PXB_PCIE_MAX_BUS "max_bus"
> >>> +#define PROP_PXB_BUS_NR "bus_nr"
> >>> +#define PROP_PXB_NUMA_NODE "numa_node"
> >>> +
> >>>typedef struct PXBDev {
> >>>/*< private >*/
> >>>PCIDevice parent_obj;
> >>>/*< public >*/
> >>>
> >>> +uint32_t domain_nr; /* PCI domain number, non-zero means separate 
> >>> domain */
> >> The commit message suggests this patch is only about
> >> re-factoring of the pxb host type, but you add here more fields.
> >> Please use two separate patches.
> >>
> >>> +uint8_t max_bus;/* max bus number to use(including this one) */
> >> That's a great idea! Limiting the max_bus will save us a lot
> >> of resource space,  we will not need 256 buses on pxbs probably.
> >>
> >> My concern is what happens with the current mode.
> >> Currently bus_nr is used to divide PCI domain 0 buses between pxbs.
> >> So if you have a pxb with bus_nr 100, and another with bus_nr 200,
> >> we divide them like this:
> >>   main host bridge 0...99
> >>   pxb1 100 -199
> >>   pxb2 200-255
> >>
> >> What will be the meaning of max_bus if we don't use the domain_nr 
> >> parameter?
> >> Maybe it will mean that some bus numbers are not assigned at all, for
> >> example:
> >> pxb1: bus_nr 100, max_bus 150
> >> pxb2: bus_nr 200, max_bus 210
> >>
> >> It may work.
> > Yes, it should mean so. Actually max_bus does not have to be specified
> > if domain_nr
> > is not used, but if users decide to use domain_nr and want to save
> > space, max_bus
> > could be used.
> >
> >>>uint8_t bus_nr;
> >>>uint16_t numa_node;
> >>>} PXBDev;
> >>> @@ -58,6 +69,16 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
> >>>static GList *pxb_dev_list;
> >>>
> >>>#define TYPE_PXB_HOST "pxb-host"
> >>> +#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
> >>> +#define PXB_PCIE_HOST_DEVICE(obj) \
> >>> + OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
> >>> +
> >>> +typedef struct PXBPCIEHost {
> >>> +PCIExpressHost parent_obj;
> >>> +
> >>> +/* pointers to PXBDev */
> >>> +PXBDev *pxbdev;
> >>> +} PXBP

Re: [Qemu-devel] [RFC v4 3/6] i386/acpi-build: describe new pci domain in AML

2018-08-26 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月25日周六 下午7:58写道:
>
>
>
> On 08/19/2018 05:00 AM, Zihan Yang wrote:
> > Marcel Apfelbaum  于2018年8月18日周六 上午1:49写道:
> >>
> >>
> >> On 08/09/2018 09:34 AM, Zihan Yang wrote:
> >>> Describe new pci segments of host bridges in AML as new pci devices,
> >>> with _SEG and _BBN to let them be in DSDT.
> >>>
> >>> Besides, bus_nr indicates the bus number of pxb-pcie under pcie.0 bus,
> >>> but since we put it into separate domain, it should be zero,
> >> Why should it be 0? Isn't possible we start another domain from bus_nr> 0?
> > In the last version, I got a misunderstanding about bus_nr, and you pointed 
> > me
> > out that we should start from bus 0 when in new domain. I can support this
> > start_bus in later patch, but I wonder when would we want to start a domain
> > from bus_nr > 0? I'm not quite familiar with the use case.
>
> That is a good point. I can't think of a reason to start a new PCI
> domain with a bus number  >0 , but is it possible.
> So if it doesn't complicate the implementation we don't
> want this kind of limitation.
> On the other hand, if it makes the code too complicated,
> we can argue for requiring it.

OK, then I will add it first and see its impact.

> Thanks,
> Marcel
>
> [...]



Re: [Qemu-devel] [RFC v4 6/6] i386/acpi-build: pxb-pcie start bus should always be 0 in separate pci domain

2018-08-18 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月18日周六 上午1:54写道:
>
>
>
> On 08/09/2018 09:35 AM, Zihan Yang wrote:
> > The bus_nr indicates the bus number of pxb-pcie under pcie.0, but since pxb
> > host can be put into different pci domain, the start bus should always be 0
>
> I am  not sure about this limitation. Do you know where is coming from?
> Why do we must start a different pci_domain from 0? (Maybe we do, I just
> want to be sure)

I'm not sure about it either, for the same reason in previous patch. I thought
we should start from bus 0 always. I think I'll bring start_bus back
in next version.

> Thanks,
> Marcel
>
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/i386/acpi-build.c| 14 ++
> >   hw/pci-bridge/pci_expander_bridge.c | 10 +-
> >   2 files changed, 7 insertions(+), 17 deletions(-)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index a7d9af2..0911008 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -91,7 +91,6 @@ typedef struct AcpiMcfgInfo {
> >   uint64_t mcfg_base;
> >   uint32_t mcfg_size;
> >   uint32_t domain_nr;
> > -uint8_t bus_nr; // start bus number
> >   struct AcpiMcfgInfo *next;
> >   } AcpiMcfgInfo;
> >
> > @@ -2470,8 +2469,8 @@ build_mcfg_q35(GArray *table_data, BIOSLinker 
> > *linker, AcpiMcfgInfo *info)
> >   while (info) {
> >   mcfg[0].allocation[count].address = cpu_to_le64(info->mcfg_base);
> >   mcfg[0].allocation[count].pci_segment = 
> > cpu_to_le16(info->domain_nr);
> > -mcfg[0].allocation[count].start_bus_number = info->bus_nr;
> > -mcfg[0].allocation[count++].end_bus_number = info->bus_nr + \
> > +mcfg[0].allocation[count].start_bus_number = 0;
> > +mcfg[0].allocation[count++].end_bus_number = \
> >   PCIE_MMCFG_BUS(info->mcfg_size - 1);
> >   info = info->next;
> >   }
> > @@ -2694,15 +2693,6 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
> >   mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
> >   qobject_unref(o);
> >
> > -o = object_property_get_qobject(obj, PROP_PXB_BUS_NR, NULL);
> > -if (!o) {
> > -/* we are in q35 host again */
> > -mcfg->bus_nr = 0;
> > -} else {
> > -mcfg->bus_nr = qnum_get_uint(qobject_to(QNum, o));
> > -qobject_unref(o);
> > -}
> > -
> >   pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
> >   }
> >
> > diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> > b/hw/pci-bridge/pci_expander_bridge.c
> > index 686b026..53f5776 100644
> > --- a/hw/pci-bridge/pci_expander_bridge.c
> > +++ b/hw/pci-bridge/pci_expander_bridge.c
> > @@ -91,7 +91,7 @@ static int pxb_bus_num(PCIBus *bus)
> >   {
> >   PXBDev *pxb = convert_to_pxb(bus->parent_dev);
> >
> > -return pxb->bus_nr;
> > +return pxb->domain_nr ? 0 : pxb->bus_nr;
> >   }
> >
> >   static int pxb_domain_num(PCIBus *bus)
> > @@ -145,8 +145,8 @@ static void pxb_pcie_foreach(gpointer data, gpointer 
> > user_data)
> >
> >   if (pxb->domain_nr > 0) {
> >   /* only reserve what users ask for to reduce memory cost. Plus one
> > - * as the interval [bus_nr, max_bus] has (max_bus-bus_nr+1) buses 
> > */
> > -pxb_mcfg_hole_size += ((pxb->max_bus - pxb->bus_nr + 1ULL) * MiB);
> > + * as the interval [0, max_bus] has (max_bus+1) buses */
> > +pxb_mcfg_hole_size += ((pxb->max_bus + 1ULL) * MiB);
> >   }
> >   }
> >
> > @@ -385,9 +385,9 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
> > pcie, Error **errp)
> >   /* will be overwritten by firmware, but kept for readability */
> >   qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
> >   pxb->domain_nr ? pxb_pcie_mcfg_base : 
> > MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
> > -/* +1 because [bus_nr, max_bus] has (max_bus-bus_nr+1) buses */
> > +/* +1 because [0, max_bus] has (max_bus+1) buses */
> >   qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_SIZE,
> > -pxb->domain_nr ? (pxb->max_bus - pxb->bus_nr + 1ULL) * MiB : 
> > 0);
> > +pxb->domain_nr ? (pxb->max_bus + 1ULL) * MiB : 0);
> >   if (pxb->domain_nr)
> >   pxb_pcie_mcfg_base += ((pxb->max_bus + 1ULL) * MiB);
> >
>



Re: [Qemu-devel] [RFC v4 5/6] pci_expander_bridge: Add ioport for pxb host bus

2018-08-18 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月18日周六 上午1:52写道:
>
>
>
> On 08/09/2018 09:35 AM, Zihan Yang wrote:
> > This enables seabios to read config file in pxb host bus other than sysbus
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/pci-bridge/pci_expander_bridge.c | 15 +++
> >   include/hw/pci-bridge/pci_expander_bridge.h |  3 +++
> >   2 files changed, 18 insertions(+)
> >
> > diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> > b/hw/pci-bridge/pci_expander_bridge.c
> > index c685c75..686b026 100644
> > --- a/hw/pci-bridge/pci_expander_bridge.c
> > +++ b/hw/pci-bridge/pci_expander_bridge.c
> > @@ -234,6 +234,20 @@ static void pxb_pcie_host_initfn(Object *obj)
> >qdev_prop_allow_set_link_before_realize, 0, 
> > NULL);
> >   }
> >
> > +static void pxb_pcie_host_realize(DeviceState *dev, Error **errp)
> > +{
> > +PCIHostState *pci = PCI_HOST_BRIDGE(dev);
> > +SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> > +
> > +// FIX ME! Use specific port number for pxb-pcie host bridge, not 
> > scalable!
> > +/* port layout is | pxb1_cmd | pxb1_data | pxb2_cmd | pxb2_data | ... 
> > | */
> > +sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE, 
> > >conf_mem);
> > +sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE + 
> > g_list_length(pxb_dev_list) * 8, 4);
> > +
> > +sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE, 
> > >data_mem);
> > +sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE + 
> > g_list_length(pxb_dev_list) * 8, 4);
>
> Why do we need this functionality? Can't we access the pxb-pcie config
> space only with
> MMCFG?

This is for the same reason as mentioned in previous patch.

> Thanks,
> Marcel
>
> > +}
> > +
> >   static Property pxb_pcie_host_props[] = {
> >   DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, 
> > parent_obj.base_addr,
> >   PCIE_BASE_ADDR_UNMAPPED),
> > @@ -262,6 +276,7 @@ static void pxb_pcie_host_class_init(ObjectClass 
> > *class, void *data)
> >
> >   dc->fw_name = "pcie";
> >   dc->props = pxb_pcie_host_props;
> > +dc->realize = pxb_pcie_host_realize;
> >   /* Reason: Internal part of the pxb/pxb-pcie device, not usable by 
> > itself */
> >   dc->user_creatable = false;
> >   sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
> > diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
> > b/include/hw/pci-bridge/pci_expander_bridge.h
> > index 1119210..e6d3b67 100644
> > --- a/include/hw/pci-bridge/pci_expander_bridge.h
> > +++ b/include/hw/pci-bridge/pci_expander_bridge.h
> > @@ -7,6 +7,9 @@
> >   #define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
> >   #define PROP_PXB_BUS_NR "bus_nr"
> >
> > +#define PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE 0x1000
> > +#define PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE 0x1004
> > +
> >   uint64_t pxb_pcie_mcfg_hole(void);
> >
> >   #endif
>



Re: [Qemu-devel] [RFC v4 3/6] i386/acpi-build: describe new pci domain in AML

2018-08-18 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月18日周六 上午1:49写道:
>
>
>
> On 08/09/2018 09:34 AM, Zihan Yang wrote:
> > Describe new pci segments of host bridges in AML as new pci devices,
> > with _SEG and _BBN to let them be in DSDT.
> >
> > Besides, bus_nr indicates the bus number of pxb-pcie under pcie.0 bus,
> > but since we put it into separate domain, it should be zero,
>
> Why should it be 0? Isn't possible we start another domain from bus_nr> 0?

In the last version, I got a misunderstanding about bus_nr, and you pointed me
out that we should start from bus 0 when in new domain. I can support this
start_bus in later patch, but I wonder when would we want to start a domain
from bus_nr > 0? I'm not quite familiar with the use case.

> >   which is
> > equal to BBN.
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/i386/acpi-build.c| 63 
> > -
> >   hw/pci-bridge/pci_expander_bridge.c |  8 +
> >   hw/pci/pci.c|  5 +++
> >   include/hw/pci/pci.h|  1 +
> >   include/hw/pci/pci_bus.h|  1 +
> >   5 files changed, 50 insertions(+), 28 deletions(-)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index c0fc2b4..a7d9af2 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -828,7 +828,7 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet 
> > *range_set)
> >   Aml *crs = aml_resource_template();
> >   CrsRangeSet temp_range_set;
> >   CrsRangeEntry *entry;
> > -uint8_t max_bus = pci_bus_num(host->bus);
> > +uint8_t max_bus = 0, host_bus = 0;
> >   uint8_t type;
> >   int devfn;
> >   int i;
> > @@ -967,10 +967,10 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet 
> > *range_set)
> >   aml_append(crs,
> >   aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
> >   0,
> > -pci_bus_num(host->bus),
> > +host_bus,
> >   max_bus,
> >   0,
> > -max_bus - pci_bus_num(host->bus) + 1));
> > +max_bus - host_bus + 1));
>
> I don't understand the above, can you please explain?

This is the same problem with above, the pci_bus_num will return bus_nr,
and I assumed the start bus is from 0.

>
> >
> >   return crs;
> >   }
> > @@ -1832,6 +1832,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> >   aml_append(dev, build_q35_osc_method());
> >   aml_append(sb_scope, dev);
> > +
>
> No need for this line
>
>
> Thanks,
> Marcel
>
> >   aml_append(dsdt, sb_scope);
> >
> >   build_hpet_aml(dsdt);
> > @@ -1875,10 +1876,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >
> >   crs_range_set_init(_range_set);
> >   bus = PC_MACHINE(machine)->bus;
> > +i = 1; // PCI0 is q35 host, pxb starts from 1
> >   if (bus) {
> >   QLIST_FOREACH(bus, >child, sibling) {
> >   uint8_t bus_num = pci_bus_num(bus);
> >   uint8_t numa_node = pci_bus_numa_node(bus);
> > +int domain_nr = pci_domain_num(bus);
> >
> >   /* look only for expander root buses */
> >   if (!pci_bus_is_root(bus)) {
> > @@ -1890,10 +1893,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   }
> >
> >   scope = aml_scope("\\_SB");
> > -dev = aml_device("PC%.02X", bus_num);
> > +dev = aml_device("PCI%d", i++);
> >   aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
> >   aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
> > -aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
> > +aml_append(dev, aml_name_decl("_ADR", aml_int(bus_num)));
> > +aml_append(dev, aml_name_decl("_SEG", aml_int(domain_nr)));
> > +aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
> >   if (pci_bus_is_express(bus)) {
> >   aml_append(dev, build_q35_osc_method());
> >   }
> > @@ -2126,35 +2131,37 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> &g

Re: [Qemu-devel] [RFC v4 2/6] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-08-18 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月18日周六 上午1:41写道:
>
> Hi Zihan,
>
> On 08/09/2018 09:33 AM, Zihan Yang wrote:
> > Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
> > corresponding MCFG space for them. This allows user-defined pxb-pcie
> > host bridges to be placed in different pci domain than q35 host.
> >
> > The pci_host_bridges list is changed to be tail list to ensure the q35 host
> > is always the first element when traversing the list, because q35 host is
> > inserted beofre pxb-pcie hosts
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/i386/acpi-build.c| 116 
> > +++-
> >   hw/i386/pc.c|  14 +++-
> >   hw/pci-bridge/pci_expander_bridge.c |  57 ++
> >   hw/pci-host/q35.c   |   2 +
> >   hw/pci/pci.c|   9 ++-
> >   include/hw/i386/pc.h|   1 +
> >   include/hw/pci-bridge/pci_expander_bridge.h |  11 +++
> >   include/hw/pci-host/q35.h   |   1 +
> >   include/hw/pci/pci_host.h   |   2 +-
> >   9 files changed, 169 insertions(+), 44 deletions(-)
> >   create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index e1ee8ae..c0fc2b4 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -55,6 +55,7 @@
> >   #include "hw/i386/ich9.h"
> >   #include "hw/pci/pci_bus.h"
> >   #include "hw/pci-host/q35.h"
> > +#include "hw/pci-bridge/pci_expander_bridge.h"
> >   #include "hw/i386/x86-iommu.h"
> >
> >   #include "hw/acpi/aml-build.h"
> > @@ -89,6 +90,9 @@
> >   typedef struct AcpiMcfgInfo {
> >   uint64_t mcfg_base;
> >   uint32_t mcfg_size;
> > +uint32_t domain_nr;
> > +uint8_t bus_nr; // start bus number
> > +struct AcpiMcfgInfo *next;
> >   } AcpiMcfgInfo;
> >
> >   typedef struct AcpiPmInfo {
> > @@ -2431,14 +2435,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker 
> > *linker, AcpiMcfgInfo *info)
> >   {
> >   AcpiTableMcfg *mcfg;
> >   const char *sig;
> > -int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
> > +int len, count = 0;
> > +AcpiMcfgInfo *cfg = info;
> > +
> > +while (cfg) {
> > +++count;
> > +cfg = cfg->next;
> > +}
> > +len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
> >
> >   mcfg = acpi_data_push(table_data, len);
> > -mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
> > -/* Only a single allocation so no need to play with segments */
>
> Now we do play :)

I will delete old comments in next version.

> > -mcfg->allocation[0].pci_segment = cpu_to_le16(0);
> > -mcfg->allocation[0].start_bus_number = 0;
> > -mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 
> > 1);
> >
> >   /* MCFG is used for ECAM which can be enabled or disabled by guest.
> >* To avoid table size changes (which create migration issues),
> > @@ -2452,6 +2458,17 @@ build_mcfg_q35(GArray *table_data, BIOSLinker 
> > *linker, AcpiMcfgInfo *info)
> >   } else {
> >   sig = "MCFG";
> >   }
> > +
> > +count = 0;
> > +while (info) {
> > +mcfg[0].allocation[count].address = cpu_to_le64(info->mcfg_base);
> > +mcfg[0].allocation[count].pci_segment = 
> > cpu_to_le16(info->domain_nr);
> > +mcfg[0].allocation[count].start_bus_number = info->bus_nr;
> > +mcfg[0].allocation[count++].end_bus_number = info->bus_nr + \
> > +PCIE_MMCFG_BUS(info->mcfg_size - 1);
>
> I don't understand this. It appears we have a max_bus_nr property in pxb,
> why don't we use it here? Or the mcfg_size is already computed based on
> that?

The mcfg_size is computed based on that, and I think this can explicitly show
the relationship of end bus and start bus, though max_bus seems shorter.

> > +info = info->next;
> > +}
> > +
> >   build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, 
> > NULL);
> >   }
> >
> > @@ -2606,26 +2623,83 @@ struct AcpiBuildState {
> >   MemoryRegion *linker_mr;
> >   } AcpiBuildState;
> >
> > -static bool acpi_get_mcfg(AcpiMc

Re: [Qemu-devel] [RFC v4 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-18 Thread Zihan Yang
Hi Marcel,

Marcel Apfelbaum  于2018年8月18日周六 上午1:14写道:
>
> Hi Zihan,
>
> On 08/09/2018 09:33 AM, Zihan Yang wrote:
> > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> > change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/pci-bridge/pci_expander_bridge.c | 127 
> > ++--
> >   1 file changed, 122 insertions(+), 5 deletions(-)
> >
> > diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> > b/hw/pci-bridge/pci_expander_bridge.c
> > index e62de42..6dd38de 100644
> > --- a/hw/pci-bridge/pci_expander_bridge.c
> > +++ b/hw/pci-bridge/pci_expander_bridge.c
> > @@ -15,10 +15,12 @@
> >   #include "hw/pci/pci.h"
> >   #include "hw/pci/pci_bus.h"
> >   #include "hw/pci/pci_host.h"
> > +#include "hw/pci/pcie_host.h"
> >   #include "hw/pci/pci_bridge.h"
> >   #include "qemu/range.h"
> >   #include "qemu/error-report.h"
> >   #include "sysemu/numa.h"
> > +#include "qapi/visitor.h"
> >
> >   #define TYPE_PXB_BUS "pxb-bus"
> >   #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
> > @@ -40,11 +42,20 @@ typedef struct PXBBus {
> >   #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
> >   #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), 
> > TYPE_PXB_PCIE_DEVICE)
> >
> > +#define PROP_PXB_PCIE_DEV "pxbdev"
> > +
> > +#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
> > +#define PROP_PXB_PCIE_MAX_BUS "max_bus"
> > +#define PROP_PXB_BUS_NR "bus_nr"
> > +#define PROP_PXB_NUMA_NODE "numa_node"
> > +
> >   typedef struct PXBDev {
> >   /*< private >*/
> >   PCIDevice parent_obj;
> >   /*< public >*/
> >
> > +uint32_t domain_nr; /* PCI domain number, non-zero means separate 
> > domain */
>
> The commit message suggests this patch is only about
> re-factoring of the pxb host type, but you add here more fields.
> Please use two separate patches.
>
> > +uint8_t max_bus;/* max bus number to use(including this one) */
>
> That's a great idea! Limiting the max_bus will save us a lot
> of resource space,  we will not need 256 buses on pxbs probably.
>
> My concern is what happens with the current mode.
> Currently bus_nr is used to divide PCI domain 0 buses between pxbs.
> So if you have a pxb with bus_nr 100, and another with bus_nr 200,
> we divide them like this:
>  main host bridge 0...99
>  pxb1 100 -199
>  pxb2 200-255
>
> What will be the meaning of max_bus if we don't use the domain_nr parameter?
> Maybe it will mean that some bus numbers are not assigned at all, for
> example:
>pxb1: bus_nr 100, max_bus 150
>pxb2: bus_nr 200, max_bus 210
>
> It may work.

Yes, it should mean so. Actually max_bus does not have to be specified
if domain_nr
is not used, but if users decide to use domain_nr and want to save
space, max_bus
could be used.

> >   uint8_t bus_nr;
> >   uint16_t numa_node;
> >   } PXBDev;
> > @@ -58,6 +69,16 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
> >   static GList *pxb_dev_list;
> >
> >   #define TYPE_PXB_HOST "pxb-host"
> > +#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
> > +#define PXB_PCIE_HOST_DEVICE(obj) \
> > + OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
> > +
> > +typedef struct PXBPCIEHost {
> > +PCIExpressHost parent_obj;
> > +
> > +/* pointers to PXBDev */
> > +PXBDev *pxbdev;
> > +} PXBPCIEHost;
> >
> >   static int pxb_bus_num(PCIBus *bus)
> >   {
> > @@ -111,6 +132,35 @@ static const char *pxb_host_root_bus_path(PCIHostState 
> > *host_bridge,
> >   return bus->bus_path;
> >   }
> >
> > +/* Use a dedicated function for PCIe since pxb-host does
> > + * not have a domain_nr field */
> > +static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
> > +  PCIBus *rootbus)
> > +{
> > +if (!pci_bus_is_express(rootbus)) {
> > +/* pxb-pcie-host cannot reside on a PCI bus */
> > +return NULL;
> > +}
> > +PXBBus *bus = PXB_PCIE_BUS(rootbus);
> > +
> > +/* get the pointer to PXBDev */
> > +Object *obj = object_property_get_link(OBJECT(host_bridge),
> > +   PROP_PXB_PCIE_DEV, NULL);
>
> 

Re: [Qemu-devel] [RFC v4 0/6] pci_expander_brdige: Support pxb-pcie host bridge into separate pci domain

2018-08-09 Thread Zihan Yang
HI all,

Sorry about unthreaded messages, I forgot to add the in-reply-to field in
the email. Future
patches will be threaded, but as for this patch, you can refer to the
following links
[RFC 1/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01364.html
[RFC 2/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01365.html
[RFC 3/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01366.html
[RFC 4/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01367.html
[RFC 5/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01368.html
[RFC 6/6]
http://lists.nongnu.org/archive/html/qemu-devel/2018-08/msg01369.html

P.S. The "current issue" section of last email is resolved now, but there
are other issues.
I will see if I can work them out in the weekend and prepare for a v3 patch
of seabios (and
maybe v5 of qemu).

Thanks
Zihan


Re: [Qemu-devel] [RFC v4 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-09 Thread Zihan Yang
Eric Blake  于2018年8月9日周四 下午9:23写道:
>
> On 08/09/2018 01:33 AM, Zihan Yang wrote:
> > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> > change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe
>
> meta-comment:
>
> Your messages came through unthreaded (seven separate threads), rather
> than properly marked 'References:' and 'In-reply-to:' to the 0/6 cover
> letter <1533796115-15837-1-git-send-email-whois.zihan.y...@gmail.com>,
> which makes it a bit harder to keep track of the conversation when
> viewing mails sorted by threads with most recent activity.

My mistake, I manually added the cc of cover letter, which is not
covered by cccmd,
but I didn't add In-reply-to of remaining mails. I will directly add
an "cc: " field in cover
letter and send them all in later patches to avoid breaking them up.

As for this patch set, should I resend them or save it to v5, which I
will try working out
this weekend?



[Qemu-devel] [RFC v4 2/6] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-08-09 Thread Zihan Yang
Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
corresponding MCFG space for them. This allows user-defined pxb-pcie
host bridges to be placed in different pci domain than q35 host.

The pci_host_bridges list is changed to be tail list to ensure the q35 host
is always the first element when traversing the list, because q35 host is
inserted beofre pxb-pcie hosts

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 116 +++-
 hw/i386/pc.c|  14 +++-
 hw/pci-bridge/pci_expander_bridge.c |  57 ++
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 ++-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  11 +++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 169 insertions(+), 44 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e1ee8ae..c0fc2b4 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -55,6 +55,7 @@
 #include "hw/i386/ich9.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "hw/i386/x86-iommu.h"
 
 #include "hw/acpi/aml-build.h"
@@ -89,6 +90,9 @@
 typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
+uint32_t domain_nr;
+uint8_t bus_nr; // start bus number
+struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
 typedef struct AcpiPmInfo {
@@ -2431,14 +2435,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 {
 AcpiTableMcfg *mcfg;
 const char *sig;
-int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+int len, count = 0;
+AcpiMcfgInfo *cfg = info;
+
+while (cfg) {
+++count;
+cfg = cfg->next;
+}
+len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
 
 mcfg = acpi_data_push(table_data, len);
-mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-/* Only a single allocation so no need to play with segments */
-mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-mcfg->allocation[0].start_bus_number = 0;
-mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
 
 /* MCFG is used for ECAM which can be enabled or disabled by guest.
  * To avoid table size changes (which create migration issues),
@@ -2452,6 +2458,17 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 } else {
 sig = "MCFG";
 }
+
+count = 0;
+while (info) {
+mcfg[0].allocation[count].address = cpu_to_le64(info->mcfg_base);
+mcfg[0].allocation[count].pci_segment = cpu_to_le16(info->domain_nr);
+mcfg[0].allocation[count].start_bus_number = info->bus_nr;
+mcfg[0].allocation[count++].end_bus_number = info->bus_nr + \
+PCIE_MMCFG_BUS(info->mcfg_size - 1);
+info = info->next;
+}
+
 build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
 }
 
@@ -2606,26 +2623,83 @@ struct AcpiBuildState {
 MemoryRegion *linker_mr;
 } AcpiBuildState;
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+static inline void cleanup_mcfg(AcpiMcfgInfo *mcfg)
+{
+AcpiMcfgInfo *tmp;
+while (mcfg) {
+tmp = mcfg->next;
+g_free(mcfg);
+mcfg = tmp;
+}
+}
+
+static AcpiMcfgInfo *acpi_get_mcfg(void)
 {
 Object *pci_host;
 QObject *o;
+uint32_t domain_nr;
+AcpiMcfgInfo *head = NULL, *tail, *mcfg;
 
 pci_host = acpi_get_i386_pci_host();
 g_assert(pci_host);
 
-o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-if (!o) {
-return false;
+while (pci_host) {
+/* pxb-pcie-hosts does not have domain_nr property, but a link
+ * to PXBDev. We first try to get pxbdev property, if NULL,
+ * then it is q35 host, otherwise it is pxb-pcie-host */
+Object *obj = object_property_get_link(pci_host,
+   PROP_PXB_PCIE_DEV, NULL);
+if (!obj) {
+/* we are in q35 host */
+obj = pci_host;
+}
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+/* Skip bridges that reside in the same domain with q35 host.
+ * Q35 always stays in pci domain 0, and is the first element
+ * in the pci_host_bridges list */
+if (head && domain_nr == 0) {
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next)

[Qemu-devel] [RFC v4 4/6] pci_expander_bridge: Add config_read callback

2018-08-09 Thread Zihan Yang
This allows SeaBIOS to retrieve MCFG base and size when it initializes
pxb host bridges.

A backlink to PXBPCIEHost is added in PXBDev to achieve above goal

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 55 +
 include/hw/pci-bridge/pci_expander_bridge.h |  1 +
 2 files changed, 56 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index d28a64c..c685c75 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -49,11 +49,18 @@ typedef struct PXBBus {
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
+typedef struct PXBPCIEHost PXBPCIEHost;
+typedef struct PXBDev PXBDev;
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+/* backlink to PXBPCIEHost, this makes it easier to get
+ * mcfg properties in pxb-pcie-host bridge */
+PXBPCIEHost *pxbhost;
+
 uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
 uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
@@ -350,9 +357,15 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 if (pcie) {
 g_assert (pxb->max_bus >= pxb->bus_nr);
 ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
+/* attach it under /machine, so that we can resolve a valid path in
+ * object_property_set_link below */
+object_property_add_child(qdev_get_machine(), "pxb-pcie-host[*]", 
OBJECT(ds), NULL);
 
+/* set link and backlink between PXBPCIEHost and PXBDev */
 object_property_set_link(OBJECT(ds), OBJECT(pxb),
  PROP_PXB_PCIE_DEV, errp);
+object_property_set_link(OBJECT(pxb), OBJECT(ds),
+ PROP_PXB_PCIE_HOST, errp);
 
 /* will be overwritten by firmware, but kept for readability */
 qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
@@ -421,6 +434,36 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
 pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 }
 
+static uint32_t pxb_pcie_config_read(PCIDevice *d, uint32_t address, int len)
+{
+PXBDev *pxb = convert_to_pxb(d);
+uint32_t val;
+Object *host;
+
+   switch (address) {
+case MCH_HOST_BRIDGE_PCIEXBAR:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) & 
0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 4:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = (object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) >> 
32) & 0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 8:  // Fix me!
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_SIZE, NULL) & 
0x;
+break;
+default:
+val = pci_default_read_config(d, address, len);
+break;
+}
+
+return val;
+}
+
 static Property pxb_dev_properties[] = {
 /* Note: 0 is not a legal PXB bus number. */
 DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
@@ -455,6 +498,16 @@ static void pxb_dev_class_init(ObjectClass *klass, void 
*data)
 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
+static void pxb_pcie_dev_initfn(Object *obj)
+{
+PXBDev *pxb = PXB_PCIE_DEV(obj);
+
+/* Add backlink to pxb-pcie-host */
+object_property_add_link(obj, PROP_PXB_PCIE_HOST, TYPE_PXB_PCIE_HOST,
+ (Object **)>pxbhost,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
 static const TypeInfo pxb_dev_info = {
 .name  = TYPE_PXB_DEVICE,
 .parent= TYPE_PCI_DEVICE,
@@ -486,6 +539,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, 
void *data)
 
 k->realize = pxb_pcie_dev_realize;
 k->exit = pxb_dev_exitfn;
+k->config_read = pxb_pcie_config_read;
 k->vendor_id = PCI_VENDOR_ID_REDHAT;
 k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
 k->class_id = PCI_CLASS_BRIDGE_HOST;
@@ -500,6 +554,7 @@ static const TypeInfo pxb_pcie_dev_info = {
 .name  = TYPE_PXB_PCIE_DEVICE,
 .parent= TYPE_PCI_DEVICE,
 .instance_size = sizeof(PXBDev),
+.instance_init = pxb_pcie_dev_initfn,
 .class_init= pxb_pcie_dev_class_init,
 .interfaces = (InterfaceInfo[]) {
 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 870c4cd..1119210 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expa

[Qemu-devel] [RFC v4 6/6] i386/acpi-build: pxb-pcie start bus should always be 0 in separate pci domain

2018-08-09 Thread Zihan Yang
The bus_nr indicates the bus number of pxb-pcie under pcie.0, but since pxb
host can be put into different pci domain, the start bus should always be 0

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 14 ++
 hw/pci-bridge/pci_expander_bridge.c | 10 +-
 2 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a7d9af2..0911008 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -91,7 +91,6 @@ typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
 uint32_t domain_nr;
-uint8_t bus_nr; // start bus number
 struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
@@ -2470,8 +2469,8 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 while (info) {
 mcfg[0].allocation[count].address = cpu_to_le64(info->mcfg_base);
 mcfg[0].allocation[count].pci_segment = cpu_to_le16(info->domain_nr);
-mcfg[0].allocation[count].start_bus_number = info->bus_nr;
-mcfg[0].allocation[count++].end_bus_number = info->bus_nr + \
+mcfg[0].allocation[count].start_bus_number = 0;
+mcfg[0].allocation[count++].end_bus_number = \
 PCIE_MMCFG_BUS(info->mcfg_size - 1);
 info = info->next;
 }
@@ -2694,15 +2693,6 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
 mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 
-o = object_property_get_qobject(obj, PROP_PXB_BUS_NR, NULL);
-if (!o) {
-/* we are in q35 host again */
-mcfg->bus_nr = 0;
-} else {
-mcfg->bus_nr = qnum_get_uint(qobject_to(QNum, o));
-qobject_unref(o);
-}
-
 pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
 }
 
diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 686b026..53f5776 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -91,7 +91,7 @@ static int pxb_bus_num(PCIBus *bus)
 {
 PXBDev *pxb = convert_to_pxb(bus->parent_dev);
 
-return pxb->bus_nr;
+return pxb->domain_nr ? 0 : pxb->bus_nr;
 }
 
 static int pxb_domain_num(PCIBus *bus)
@@ -145,8 +145,8 @@ static void pxb_pcie_foreach(gpointer data, gpointer 
user_data)
 
 if (pxb->domain_nr > 0) {
 /* only reserve what users ask for to reduce memory cost. Plus one
- * as the interval [bus_nr, max_bus] has (max_bus-bus_nr+1) buses */
-pxb_mcfg_hole_size += ((pxb->max_bus - pxb->bus_nr + 1ULL) * MiB);
+ * as the interval [0, max_bus] has (max_bus+1) buses */
+pxb_mcfg_hole_size += ((pxb->max_bus + 1ULL) * MiB);
 }
 }
 
@@ -385,9 +385,9 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 /* will be overwritten by firmware, but kept for readability */
 qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
 pxb->domain_nr ? pxb_pcie_mcfg_base : 
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
-/* +1 because [bus_nr, max_bus] has (max_bus-bus_nr+1) buses */
+/* +1 because [0, max_bus] has (max_bus+1) buses */
 qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_SIZE,
-pxb->domain_nr ? (pxb->max_bus - pxb->bus_nr + 1ULL) * MiB : 0);
+pxb->domain_nr ? (pxb->max_bus + 1ULL) * MiB : 0);
 if (pxb->domain_nr)
 pxb_pcie_mcfg_base += ((pxb->max_bus + 1ULL) * MiB);
 
-- 
2.7.4




[Qemu-devel] [RFC v4 5/6] pci_expander_bridge: Add ioport for pxb host bus

2018-08-09 Thread Zihan Yang
This enables seabios to read config file in pxb host bus other than sysbus

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 15 +++
 include/hw/pci-bridge/pci_expander_bridge.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index c685c75..686b026 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -234,6 +234,20 @@ static void pxb_pcie_host_initfn(Object *obj)
  qdev_prop_allow_set_link_before_realize, 0, NULL);
 }
 
+static void pxb_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+// FIX ME! Use specific port number for pxb-pcie host bridge, not scalable!
+/* port layout is | pxb1_cmd | pxb1_data | pxb2_cmd | pxb2_data | ... | */
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE, >conf_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE, >data_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+}
+
 static Property pxb_pcie_host_props[] = {
 DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
 PCIE_BASE_ADDR_UNMAPPED),
@@ -262,6 +276,7 @@ static void pxb_pcie_host_class_init(ObjectClass *class, 
void *data)
 
 dc->fw_name = "pcie";
 dc->props = pxb_pcie_host_props;
+dc->realize = pxb_pcie_host_realize;
 /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself 
*/
 dc->user_creatable = false;
 sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 1119210..e6d3b67 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -7,6 +7,9 @@
 #define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
 #define PROP_PXB_BUS_NR "bus_nr"
 
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE 0x1000
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE 0x1004
+
 uint64_t pxb_pcie_mcfg_hole(void);
 
 #endif
-- 
2.7.4




[Qemu-devel] [RFC v4 3/6] i386/acpi-build: describe new pci domain in AML

2018-08-09 Thread Zihan Yang
Describe new pci segments of host bridges in AML as new pci devices,
with _SEG and _BBN to let them be in DSDT.

Besides, bus_nr indicates the bus number of pxb-pcie under pcie.0 bus,
but since we put it into separate domain, it should be zero, which is
equal to BBN.

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 63 -
 hw/pci-bridge/pci_expander_bridge.c |  8 +
 hw/pci/pci.c|  5 +++
 include/hw/pci/pci.h|  1 +
 include/hw/pci/pci_bus.h|  1 +
 5 files changed, 50 insertions(+), 28 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index c0fc2b4..a7d9af2 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -828,7 +828,7 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet 
*range_set)
 Aml *crs = aml_resource_template();
 CrsRangeSet temp_range_set;
 CrsRangeEntry *entry;
-uint8_t max_bus = pci_bus_num(host->bus);
+uint8_t max_bus = 0, host_bus = 0;
 uint8_t type;
 int devfn;
 int i;
@@ -967,10 +967,10 @@ static Aml *build_crs(PCIHostState *host, CrsRangeSet 
*range_set)
 aml_append(crs,
 aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
 0,
-pci_bus_num(host->bus),
+host_bus,
 max_bus,
 0,
-max_bus - pci_bus_num(host->bus) + 1));
+max_bus - host_bus + 1));
 
 return crs;
 }
@@ -1832,6 +1832,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 aml_append(dev, aml_name_decl("_UID", aml_int(1)));
 aml_append(dev, build_q35_osc_method());
 aml_append(sb_scope, dev);
+
 aml_append(dsdt, sb_scope);
 
 build_hpet_aml(dsdt);
@@ -1875,10 +1876,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 crs_range_set_init(_range_set);
 bus = PC_MACHINE(machine)->bus;
+i = 1; // PCI0 is q35 host, pxb starts from 1
 if (bus) {
 QLIST_FOREACH(bus, >child, sibling) {
 uint8_t bus_num = pci_bus_num(bus);
 uint8_t numa_node = pci_bus_numa_node(bus);
+int domain_nr = pci_domain_num(bus);
 
 /* look only for expander root buses */
 if (!pci_bus_is_root(bus)) {
@@ -1890,10 +1893,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 
 scope = aml_scope("\\_SB");
-dev = aml_device("PC%.02X", bus_num);
+dev = aml_device("PCI%d", i++);
 aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
 aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
-aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_ADR", aml_int(bus_num)));
+aml_append(dev, aml_name_decl("_SEG", aml_int(domain_nr)));
+aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
 if (pci_bus_is_express(bus)) {
 aml_append(dev, build_q35_osc_method());
 }
@@ -2126,35 +2131,37 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 {
 Object *pci_host;
 PCIBus *bus = NULL;
+int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
+while (pci_host) {
 bus = PCI_HOST_BRIDGE(pci_host)->bus;
-}
+if (bus) {
+Aml *scope = aml_scope("PCI%d", index);
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+/* Only add TPM once */
+if (index++ == 0 && TPM_IS_TIS(tpm_find())) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", 
aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, a

[Qemu-devel] [RFC v4 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-09 Thread Zihan Yang
The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 127 ++--
 1 file changed, 122 insertions(+), 5 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..6dd38de 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,10 +15,12 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
+#include "qapi/visitor.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
@@ -40,11 +42,20 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_PCIE_DEV "pxbdev"
+
+#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
+#define PROP_PXB_PCIE_MAX_BUS "max_bus"
+#define PROP_PXB_BUS_NR "bus_nr"
+#define PROP_PXB_NUMA_NODE "numa_node"
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
+uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
 uint16_t numa_node;
 } PXBDev;
@@ -58,6 +69,16 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
 static GList *pxb_dev_list;
 
 #define TYPE_PXB_HOST "pxb-host"
+#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
+#define PXB_PCIE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
+
+typedef struct PXBPCIEHost {
+PCIExpressHost parent_obj;
+
+/* pointers to PXBDev */
+PXBDev *pxbdev;
+} PXBPCIEHost;
 
 static int pxb_bus_num(PCIBus *bus)
 {
@@ -111,6 +132,35 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 return bus->bus_path;
 }
 
+/* Use a dedicated function for PCIe since pxb-host does
+ * not have a domain_nr field */
+static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
+  PCIBus *rootbus)
+{
+if (!pci_bus_is_express(rootbus)) {
+/* pxb-pcie-host cannot reside on a PCI bus */
+return NULL;
+}
+PXBBus *bus = PXB_PCIE_BUS(rootbus);
+
+/* get the pointer to PXBDev */
+Object *obj = object_property_get_link(OBJECT(host_bridge),
+   PROP_PXB_PCIE_DEV, NULL);
+
+snprintf(bus->bus_path, 8, "%04lx:%02x",
+ object_property_get_uint(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL),
+ pxb_bus_num(rootbus));
+return bus->bus_path;
+}
+
+static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 {
 const PCIHostState *pxb_host;
@@ -142,6 +192,31 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static void pxb_pcie_host_initfn(Object *obj)
+{
+PXBPCIEHost *s = PXB_PCIE_HOST_DEVICE(obj);
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4);
+memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
+  "pci-conf-data", 4);
+
+object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64",
+ pxb_pcie_host_get_mmcfg_size,
+ NULL, NULL, NULL, NULL);
+
+object_property_add_link(obj, PROP_PXB_PCIE_DEV, TYPE_PXB_PCIE_DEVICE,
+ (Object **)>pxbdev,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
+static Property pxb_pcie_host_props[] = {
+DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
+PCIE_BASE_ADDR_UNMAPPED),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pxb_host_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
@@ -155,12 +230,34 @@ static void pxb_host_class_init(ObjectClass *class, void 
*data)
 hc->root_bus_path = pxb_host_root_bus_path;
 }
 
+static void pxb_pcie_host_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+SysBusDeviceClass *sbc = SYS_BUS_DEVICE

[Qemu-devel] [RFC v4 0/6] pci_expander_brdige: Support pxb-pcie host bridge into separate pci domain

2018-08-09 Thread Zihan Yang
Currently only q35 host bridge is allocated an item in MCFG table, all pxb
host bridges stay within pci domain 0. This series of patches put each pxb
host bridge in separate pci domain, allocating a new MCFG table item for it.

Users can configure whether to put pxb host bridge into separate domain
by passing parameter domain_nr to pxb pcie device. start_bus property
indicates the Base Bus Number(BBN) of the pxb host bridge. Another property
max_bus specifies the maximum desired bus numbers to reduce MCFG space cost.
Example command is

-device pxb-pcie,id=br3,bus="pcie.0",start_bus=0,domain_nr=1,max_bus=15

Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
(15+1)=16 buses, which is much smaller than the default 256 buses.

The pxb host does not have an mch in it, as q35 host already has one. All
pxb host bridges just serve as expander bridges in QEMU, which makes them
a little simpler than q35 host bridge.

The corresponding seabios patch link is

https://mail.coreboot.org/pipermail/seabios/2018-August/012401.html

Current issues:
* seabios will still throw a PCI IO space out of range error, it seems the
  pcie_pci_bridge is not correctly recognized. I'm working on it.

v4 <- v3:
- Fix bug in setting mcfg table
- bus_nr is not used when pxb-pcie is in a new pci domain

v3 <- v2:
- Replace duplicate properties in pxb pcie host with link property to PXBDev
- Allow seabios to access config space and data space of expander bridge
  through a different ioport, because 0xcf8 is attached only to sysbus.
- Add a new property start_bus to indicate the BBN of pxb host bridge. The
  bus_nr property is used as the bus number of pxb-pcie device on pcie.0 bus

v2 <- v1:
- Allow user to configure whether to put pxb-pcie into seperate domain
- Add AML description part of each host bridge
- Modify the location of MCFG space to between RAM hotplug and pci hole64

Zihan Yang (6):
  pci_expander_bridge: add type TYPE_PXB_PCIE_HOST
  acpi-build: allocate mcfg for pxb-pcie host bridges
  i386/acpi-build: describe new pci domain in AML
  pci_expander_bridge: Add config_read callback
  pci_expander_bridge: Add ioport for pxb host bus
  i386/acpi-build: pxb-pcie start bus should always be 0 in separate pci
domain

 hw/i386/acpi-build.c| 169 ++--
 hw/i386/pc.c|  14 +-
 hw/pci-bridge/pci_expander_bridge.c | 230 +++-
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|  14 +-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  15 ++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci.h|   1 +
 include/hw/pci/pci_bus.h|   1 +
 include/hw/pci/pci_host.h   |   2 +-
 11 files changed, 389 insertions(+), 61 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




[Qemu-devel] [Bug 1785670] Re: Guest(ubuntu 18.04) crashes when trying uploading file

2018-08-07 Thread Zihan Yang
Glad to see such a quick fix, and ASAN looks like a great tool :)

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1785670

Title:
  Guest(ubuntu 18.04) crashes when trying uploading file

Status in QEMU:
  Confirmed

Bug description:
  I speficy slirp network, and I can open websites, git clone repos. But
  when I try to upload a file to slack, or try to do a git push, it
  crashes.

  My host is ubuntu 16.04 with kernel 4.15.0-29-generic, and qemu is
  latest source in git(commit 1fb57da72ae0886e). The command I use is

  ./x86_64-softmmu/qemu-system-x86_64 -machine q35,accel=kvm -m 2048
  -drive file=../qcow2/guest.qcow2  -netdev user,id=realnet0 -device
  e1000e,netdev=realnet0

  The trace is as follows

  *** Error in `./x86_64-softmmu/qemu-system-x86_64': free(): invalid next size 
(normal): 0x7f66d80b7300 ***
  === Backtrace: =
  /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f66fb7967e5]
  /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f66fb79f37a]
  /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f66fb7a353c]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a8549)[0x55dc10c7d549]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a99d4)[0x55dc10c7e9d4]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6ad09a)[0x55dc10c8209a]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a3feb)[0x55dc10c78feb]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a746e)[0x55dc10c7c46e]
  ./x86_64-softmmu/qemu-system-x86_64(+0x68fe2c)[0x55dc10c64e2c]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685b3b)[0x55dc10c5ab3b]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685bfd)[0x55dc10c5abfd]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6885a8)[0x55dc10c5d5a8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x688717)[0x55dc10c5d717]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685d27)[0x55dc10c5ad27]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685d54)[0x55dc10c5ad54]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586bb8)[0x55dc10b5bbb8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586d92)[0x55dc10b5bd92]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586ecd)[0x55dc10b5becd]
  ./x86_64-softmmu/qemu-system-x86_64(+0x593ea8)[0x55dc10b68ea8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x59419d)[0x55dc10b6919d]
  ./x86_64-softmmu/qemu-system-x86_64(+0x5947df)[0x55dc10b697df]
  ./x86_64-softmmu/qemu-system-x86_64(+0x597ddf)[0x55dc10b6cddf]
  ./x86_64-softmmu/qemu-system-x86_64(+0x5989e7)[0x55dc10b6d9e7]
  ./x86_64-softmmu/qemu-system-x86_64(+0x58ae11)[0x55dc10b5fe11]
  ./x86_64-softmmu/qemu-system-x86_64(+0x30d4f6)[0x55dc108e24f6]
  ./x86_64-softmmu/qemu-system-x86_64(+0x30d70e)[0x55dc108e270e]
  ./x86_64-softmmu/qemu-system-x86_64(+0x310336)[0x55dc108e5336]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac368)[0x55dc10881368]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac4b2)[0x55dc108814b2]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac7b8)[0x55dc108817b8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac809)[0x55dc10881809]
  ./x86_64-softmmu/qemu-system-x86_64(+0x32b673)[0x55dc10900673]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2f2875)[0x55dc108c7875]
  ./x86_64-softmmu/qemu-system-x86_64(+0x81b91c)[0x55dc10df091c]
  /lib/x86_64-linux-gnu/libpthread.so.0(+0x76ba)[0x7f66fbaf06ba]
  /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f66fb82641d]
  === Memory map: 
  55dc105d5000-55dc112a9000 r-xp  103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc114a9000-55dc115bd000 r--p 00cd4000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc115bd000-55dc11773000 rw-p 00de8000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc11773000-55dc117b5000 rw-p  00:00 0 
  55dc134d6000-55dc14e2 rw-p  00:00 0  
[heap]
  7f663400-7f6634021000 rw-p  00:00 0 
  7f6634021000-7f663800 ---p  00:00 0 
  7f663c00-7f663c021000 rw-p  00:00 0 
  7f663c021000-7f664000 ---p  00:00 0 
  7f664200-7f664400 rw-s  00:05 4882443
/SYSV (deleted)
  7f664400-7f6644021000 rw-p  00:00 0 
  7f6644021000-7f664800 ---p  00:00 0 
  7f66491cc000-7f66491cd000 ---p  00:00 0 
  7f66491cd000-7f66499cd000 rw-p  00:00 0 
  7f66499cd000-7f66499ce000 ---p  00:00 0 
  7f66499ce000-7f664a1ce000 rw-p  00:00 0 
  7f664a1ce000-7f664a1cf000 ---p  00:00 0 
  7f664a1cf000-7f664a9cf000 rw-p  00:00 0 
  7f664a9cf000-7f664a9d ---p  00:00 0 
  7f664a9d-7f664b1d rw-p  00:00 0 
  7f664b1d-7f664b1d1000 ---p  00:00 0 
  7f664b1d1000-7f664b9d1000 rw-p  00:00 0 
  7f664b9d1000-7f664b9d2000 ---p  00:00 0 
  7f664b9d2000-7f664bad2000 rw-p  00:00 0 
  7f664bad2000-7f664bad3000 ---p  00:00 0 
  7f664bad3000-7f664bbd3000 rw-p  00:00 0 
  

Re: [Qemu-devel] [RFC v3 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-06 Thread Zihan Yang
Marcel Apfelbaum  于2018年8月6日周一 下午7:46写道:
>
>
>
> On 08/02/2018 05:45 AM, Zihan Yang wrote:
> > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> > change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe
>
> After an offline conversation we decided to not review this version
> and wait for the next one, that will come with a SeaBIOS counterpart series.

Yes, there are also a few trivial bugs that I fix later. I'm preparing
for a new patch set,
and a patch set in seabios.

> Zihan, please be sure to add 'patch 0 ' to the series where we can discuss
> the series status.

There actually is a patch 0, but it seems the cccmd does not apply the
patch 0 automatically,
I will cc you the cover letter too next time.

Thanks,
Zihan



[Qemu-devel] [Bug 1785670] Re: Guest(ubuntu 18.04) crashes when trying uploading file

2018-08-06 Thread Zihan Yang
It's indeed e1000e specific, when I change e1000e to e1000, I can upload
file freely. Looks like there is an overflow somewhere in e1000e that
corrupted the heap chunk header.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1785670

Title:
  Guest(ubuntu 18.04) crashes when trying uploading file

Status in QEMU:
  Confirmed

Bug description:
  I speficy slirp network, and I can open websites, git clone repos. But
  when I try to upload a file to slack, or try to do a git push, it
  crashes.

  My host is ubuntu 16.04 with kernel 4.15.0-29-generic, and qemu is
  latest source in git(commit 1fb57da72ae0886e). The command I use is

  ./x86_64-softmmu/qemu-system-x86_64 -machine q35,accel=kvm -m 2048
  -drive file=../qcow2/guest.qcow2  -netdev user,id=realnet0 -device
  e1000e,netdev=realnet0

  The trace is as follows

  *** Error in `./x86_64-softmmu/qemu-system-x86_64': free(): invalid next size 
(normal): 0x7f66d80b7300 ***
  === Backtrace: =
  /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f66fb7967e5]
  /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f66fb79f37a]
  /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f66fb7a353c]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a8549)[0x55dc10c7d549]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a99d4)[0x55dc10c7e9d4]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6ad09a)[0x55dc10c8209a]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a3feb)[0x55dc10c78feb]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6a746e)[0x55dc10c7c46e]
  ./x86_64-softmmu/qemu-system-x86_64(+0x68fe2c)[0x55dc10c64e2c]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685b3b)[0x55dc10c5ab3b]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685bfd)[0x55dc10c5abfd]
  ./x86_64-softmmu/qemu-system-x86_64(+0x6885a8)[0x55dc10c5d5a8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x688717)[0x55dc10c5d717]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685d27)[0x55dc10c5ad27]
  ./x86_64-softmmu/qemu-system-x86_64(+0x685d54)[0x55dc10c5ad54]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586bb8)[0x55dc10b5bbb8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586d92)[0x55dc10b5bd92]
  ./x86_64-softmmu/qemu-system-x86_64(+0x586ecd)[0x55dc10b5becd]
  ./x86_64-softmmu/qemu-system-x86_64(+0x593ea8)[0x55dc10b68ea8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x59419d)[0x55dc10b6919d]
  ./x86_64-softmmu/qemu-system-x86_64(+0x5947df)[0x55dc10b697df]
  ./x86_64-softmmu/qemu-system-x86_64(+0x597ddf)[0x55dc10b6cddf]
  ./x86_64-softmmu/qemu-system-x86_64(+0x5989e7)[0x55dc10b6d9e7]
  ./x86_64-softmmu/qemu-system-x86_64(+0x58ae11)[0x55dc10b5fe11]
  ./x86_64-softmmu/qemu-system-x86_64(+0x30d4f6)[0x55dc108e24f6]
  ./x86_64-softmmu/qemu-system-x86_64(+0x30d70e)[0x55dc108e270e]
  ./x86_64-softmmu/qemu-system-x86_64(+0x310336)[0x55dc108e5336]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac368)[0x55dc10881368]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac4b2)[0x55dc108814b2]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac7b8)[0x55dc108817b8]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2ac809)[0x55dc10881809]
  ./x86_64-softmmu/qemu-system-x86_64(+0x32b673)[0x55dc10900673]
  ./x86_64-softmmu/qemu-system-x86_64(+0x2f2875)[0x55dc108c7875]
  ./x86_64-softmmu/qemu-system-x86_64(+0x81b91c)[0x55dc10df091c]
  /lib/x86_64-linux-gnu/libpthread.so.0(+0x76ba)[0x7f66fbaf06ba]
  /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f66fb82641d]
  === Memory map: 
  55dc105d5000-55dc112a9000 r-xp  103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc114a9000-55dc115bd000 r--p 00cd4000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc115bd000-55dc11773000 rw-p 00de8000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
  55dc11773000-55dc117b5000 rw-p  00:00 0 
  55dc134d6000-55dc14e2 rw-p  00:00 0  
[heap]
  7f663400-7f6634021000 rw-p  00:00 0 
  7f6634021000-7f663800 ---p  00:00 0 
  7f663c00-7f663c021000 rw-p  00:00 0 
  7f663c021000-7f664000 ---p  00:00 0 
  7f664200-7f664400 rw-s  00:05 4882443
/SYSV (deleted)
  7f664400-7f6644021000 rw-p  00:00 0 
  7f6644021000-7f664800 ---p  00:00 0 
  7f66491cc000-7f66491cd000 ---p  00:00 0 
  7f66491cd000-7f66499cd000 rw-p  00:00 0 
  7f66499cd000-7f66499ce000 ---p  00:00 0 
  7f66499ce000-7f664a1ce000 rw-p  00:00 0 
  7f664a1ce000-7f664a1cf000 ---p  00:00 0 
  7f664a1cf000-7f664a9cf000 rw-p  00:00 0 
  7f664a9cf000-7f664a9d ---p  00:00 0 
  7f664a9d-7f664b1d rw-p  00:00 0 
  7f664b1d-7f664b1d1000 ---p  00:00 0 
  7f664b1d1000-7f664b9d1000 rw-p  00:00 0 
  7f664b9d1000-7f664b9d2000 ---p  00:00 0 
  7f664b9d2000-7f664bad2000 rw-p  00:00 0 
  

[Qemu-devel] [Bug 1785670] [NEW] Guest(ubuntu 18.04) crashes when trying uploading file

2018-08-06 Thread Zihan Yang
Public bug reported:

I speficy slirp network, and I can open websites, git clone repos. But
when I try to upload a file to slack, or try to do a git push, it
crashes.

My host is ubuntu 16.04 with kernel 4.15.0-29-generic, and qemu is
latest source in git(commit 1fb57da72ae0886e). The command I use is

./x86_64-softmmu/qemu-system-x86_64 -machine q35,accel=kvm -m 2048
-drive file=../qcow2/guest.qcow2  -netdev user,id=realnet0 -device
e1000e,netdev=realnet0

The trace is as follows

*** Error in `./x86_64-softmmu/qemu-system-x86_64': free(): invalid next size 
(normal): 0x7f66d80b7300 ***
=== Backtrace: =
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f66fb7967e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f66fb79f37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f66fb7a353c]
./x86_64-softmmu/qemu-system-x86_64(+0x6a8549)[0x55dc10c7d549]
./x86_64-softmmu/qemu-system-x86_64(+0x6a99d4)[0x55dc10c7e9d4]
./x86_64-softmmu/qemu-system-x86_64(+0x6ad09a)[0x55dc10c8209a]
./x86_64-softmmu/qemu-system-x86_64(+0x6a3feb)[0x55dc10c78feb]
./x86_64-softmmu/qemu-system-x86_64(+0x6a746e)[0x55dc10c7c46e]
./x86_64-softmmu/qemu-system-x86_64(+0x68fe2c)[0x55dc10c64e2c]
./x86_64-softmmu/qemu-system-x86_64(+0x685b3b)[0x55dc10c5ab3b]
./x86_64-softmmu/qemu-system-x86_64(+0x685bfd)[0x55dc10c5abfd]
./x86_64-softmmu/qemu-system-x86_64(+0x6885a8)[0x55dc10c5d5a8]
./x86_64-softmmu/qemu-system-x86_64(+0x688717)[0x55dc10c5d717]
./x86_64-softmmu/qemu-system-x86_64(+0x685d27)[0x55dc10c5ad27]
./x86_64-softmmu/qemu-system-x86_64(+0x685d54)[0x55dc10c5ad54]
./x86_64-softmmu/qemu-system-x86_64(+0x586bb8)[0x55dc10b5bbb8]
./x86_64-softmmu/qemu-system-x86_64(+0x586d92)[0x55dc10b5bd92]
./x86_64-softmmu/qemu-system-x86_64(+0x586ecd)[0x55dc10b5becd]
./x86_64-softmmu/qemu-system-x86_64(+0x593ea8)[0x55dc10b68ea8]
./x86_64-softmmu/qemu-system-x86_64(+0x59419d)[0x55dc10b6919d]
./x86_64-softmmu/qemu-system-x86_64(+0x5947df)[0x55dc10b697df]
./x86_64-softmmu/qemu-system-x86_64(+0x597ddf)[0x55dc10b6cddf]
./x86_64-softmmu/qemu-system-x86_64(+0x5989e7)[0x55dc10b6d9e7]
./x86_64-softmmu/qemu-system-x86_64(+0x58ae11)[0x55dc10b5fe11]
./x86_64-softmmu/qemu-system-x86_64(+0x30d4f6)[0x55dc108e24f6]
./x86_64-softmmu/qemu-system-x86_64(+0x30d70e)[0x55dc108e270e]
./x86_64-softmmu/qemu-system-x86_64(+0x310336)[0x55dc108e5336]
./x86_64-softmmu/qemu-system-x86_64(+0x2ac368)[0x55dc10881368]
./x86_64-softmmu/qemu-system-x86_64(+0x2ac4b2)[0x55dc108814b2]
./x86_64-softmmu/qemu-system-x86_64(+0x2ac7b8)[0x55dc108817b8]
./x86_64-softmmu/qemu-system-x86_64(+0x2ac809)[0x55dc10881809]
./x86_64-softmmu/qemu-system-x86_64(+0x32b673)[0x55dc10900673]
./x86_64-softmmu/qemu-system-x86_64(+0x2f2875)[0x55dc108c7875]
./x86_64-softmmu/qemu-system-x86_64(+0x81b91c)[0x55dc10df091c]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x76ba)[0x7f66fbaf06ba]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f66fb82641d]
=== Memory map: 
55dc105d5000-55dc112a9000 r-xp  103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
55dc114a9000-55dc115bd000 r--p 00cd4000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
55dc115bd000-55dc11773000 rw-p 00de8000 103:02 5767220   
/home/biggerfish/src/qemu/x86_64-softmmu/qemu-system-x86_64
55dc11773000-55dc117b5000 rw-p  00:00 0 
55dc134d6000-55dc14e2 rw-p  00:00 0  [heap]
7f663400-7f6634021000 rw-p  00:00 0 
7f6634021000-7f663800 ---p  00:00 0 
7f663c00-7f663c021000 rw-p  00:00 0 
7f663c021000-7f664000 ---p  00:00 0 
7f664200-7f664400 rw-s  00:05 4882443
/SYSV (deleted)
7f664400-7f6644021000 rw-p  00:00 0 
7f6644021000-7f664800 ---p  00:00 0 
7f66491cc000-7f66491cd000 ---p  00:00 0 
7f66491cd000-7f66499cd000 rw-p  00:00 0 
7f66499cd000-7f66499ce000 ---p  00:00 0 
7f66499ce000-7f664a1ce000 rw-p  00:00 0 
7f664a1ce000-7f664a1cf000 ---p  00:00 0 
7f664a1cf000-7f664a9cf000 rw-p  00:00 0 
7f664a9cf000-7f664a9d ---p  00:00 0 
7f664a9d-7f664b1d rw-p  00:00 0 
7f664b1d-7f664b1d1000 ---p  00:00 0 
7f664b1d1000-7f664b9d1000 rw-p  00:00 0 
7f664b9d1000-7f664b9d2000 ---p  00:00 0 
7f664b9d2000-7f664bad2000 rw-p  00:00 0 
7f664bad2000-7f664bad3000 ---p  00:00 0 
7f664bad3000-7f664bbd3000 rw-p  00:00 0 
7f664bbd3000-7f664bbd4000 ---p  00:00 0 
7f664bbd4000-7f664bcd4000 rw-p  00:00 0 
7f664bcd4000-7f664bcd5000 ---p  00:00 0 
7f664bcd5000-7f664c4d5000 rw-p  00:00 0 
7f664c4d5000-7f664c4d6000 ---p  00:00 0 
7f664c4d6000-7f664c5d6000 rw-p  00:00 0 
7f664c5d6000-7f664c5d7000 ---p  00:00 0 
7f664c5d7000-7f664c6d7000 rw-p  00:00 0 
7f664c6d7000-7f664c6d8000 ---p  00:00 0 
7f664c6d8000-7f664c7d8000 rw-p 

[Qemu-devel] [RFC v3 6/6] pci_expander_bridge: add start_bus property

2018-08-01 Thread Zihan Yang
The former bus_nr property indicates the bus number of pxb-pcie device on
pcie.0 bus, not the Base Bus Number of pxb-pcie host bridge. Use start_bus
property to represent this BBN when building acpi table

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 22 +++---
 hw/pci-bridge/pci_expander_bridge.c | 25 ++---
 include/hw/pci-bridge/pci_expander_bridge.h |  2 +-
 3 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4b6ef78..874e0fa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -91,7 +91,7 @@ typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
 uint32_t domain_nr;
-uint8_t bus_nr; // start bus number
+uint8_t start_bus; // start bus number
 struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
@@ -2129,7 +2129,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 QObject *o;
 PCIBus *bus = NULL;
 uint32_t domain_nr;
-uint8_t bus_nr;
+uint8_t start_bus;
 int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
@@ -2145,12 +2145,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 domain_nr = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 
-o = object_property_get_qobject(pci_host, "bus_nr", NULL);
+o = object_property_get_qobject(pci_host, "start_bus", NULL);
 if (!o) {
 /* we are in q35 host */
-bus_nr = 0;
+start_bus = 0;
 } else {
-bus_nr = qnum_get_uint(qobject_to(QNum, o));
+start_bus = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 }
 
@@ -2158,7 +2158,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 if (bus) {
 Aml *scope = aml_scope("PCI%d", index);
 aml_append(scope, aml_name_decl("_SEG", aml_int(domain_nr)));
-aml_append(scope, aml_name_decl("_BBN", aml_int(bus_nr)));
+aml_append(scope, aml_name_decl("_BBN", aml_int(start_bus)));
 /* Scan all PCI buses. Generate tables to support hotplug. */
 build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
@@ -2486,8 +2486,8 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 while (info) {
 mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
 mcfg[count].allocation[0].pci_segment = cpu_to_le16(info->domain_nr);
-mcfg[count].allocation[0].start_bus_number = info->bus_nr;
-mcfg[count++].allocation[0].end_bus_number = info->bus_nr + \
+mcfg[count].allocation[0].start_bus_number = info->start_bus;
+mcfg[count++].allocation[0].end_bus_number = info->start_bus + \
 PCIE_MMCFG_BUS(info->mcfg_size - 1);
 info = info->next;
 }
@@ -2710,12 +2710,12 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
 mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 
-o = object_property_get_qobject(obj, PROP_PXB_BUS_NR, NULL);
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_START_BUS, NULL);
 if (!o) {
 /* we are in q35 host again */
-mcfg->bus_nr = 0;
+mcfg->start_bus = 0;
 } else {
-mcfg->bus_nr = qnum_get_uint(qobject_to(QNum, o));
+mcfg->start_bus = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 }
 
diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 38212db..85630ff 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -46,6 +46,7 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_BUS_NR "bus_nr"
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
@@ -62,8 +63,9 @@ typedef struct PXBDev {
 PXBPCIEHost *pxbhost;
 
 uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
+uint8_t start_bus;  /* indicates the BBN of pxb-pcie-host bridge */
 uint8_t max_bus;/* max bus number to use(including this one) */
-uint8_t bus_nr;
+uint8_t bus_nr; /* bus number of pxb-pcie device on pcei.0 bus */
 uint16_t numa_node;
 } PXBDev;
 
@@ -137,8 +139,8 @@ static void pxb_pcie_foreach(gpointer data, gpointer 
user_data)
 
 if (pxb->domain_nr > 0) {
 /* only reserve what users ask for to reduce memory cost. Plus one
- * as the interval [bus_nr, max_bus] has (max_bus-bus_nr+1) buses */
-

[Qemu-devel] [RFC v3 4/6] pci_expander_bridge: Add config_read callback

2018-08-01 Thread Zihan Yang
This allows SeaBIOS to retrieve MCFG base and size when it initializes
pxb host bridges.

A backlink to PXBPCIEHost is added in PXBDev to achieve above goal

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 55 +
 include/hw/pci-bridge/pci_expander_bridge.h |  1 +
 2 files changed, 56 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index f50938f..cdfdb90 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -49,11 +49,18 @@ typedef struct PXBBus {
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
+typedef struct PXBPCIEHost PXBPCIEHost;
+typedef struct PXBDev PXBDev;
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+/* backlink to PXBPCIEHost, this makes it easier to get
+ * mcfg properties in pxb-pcie-host bridge */
+PXBPCIEHost *pxbhost;
+
 uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
 uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
@@ -342,9 +349,15 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 if (pcie) {
 g_assert (pxb->max_bus >= pxb->bus_nr);
 ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
+/* attach it under /machine, so that we can resolve a valid path in
+ * object_property_set_link below */
+object_property_add_child(qdev_get_machine(), "pxb-pcie-host[*]", 
OBJECT(ds), NULL);
 
+/* set link and backlink between PXBPCIEHost and PXBDev */
 object_property_set_link(OBJECT(ds), OBJECT(pxb),
  PROP_PXB_PCIE_DEV, errp);
+object_property_set_link(OBJECT(pxb), OBJECT(ds),
+ PROP_PXB_PCIE_HOST, errp);
 
 /* will be overwritten by firmware, but kept for readability */
 qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
@@ -413,6 +426,36 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
 pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 }
 
+static uint32_t pxb_pcie_config_read(PCIDevice *d, uint32_t address, int len)
+{
+PXBDev *pxb = convert_to_pxb(d);
+uint32_t val;
+Object *host;
+
+   switch (address) {
+case MCH_HOST_BRIDGE_PCIEXBAR:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) & 
0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 4:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = (object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) >> 
32) & 0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 8:  // Fix me!
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_SIZE, NULL) & 
0x;
+break;
+default:
+val = pci_default_read_config(d, address, len);
+break;
+}
+
+return val;
+}
+
 static Property pxb_dev_properties[] = {
 /* Note: 0 is not a legal PXB bus number. */
 DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
@@ -447,6 +490,16 @@ static void pxb_dev_class_init(ObjectClass *klass, void 
*data)
 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
+static void pxb_pcie_dev_initfn(Object *obj)
+{
+PXBDev *pxb = PXB_PCIE_DEV(obj);
+
+/* Add backlink to pxb-pcie-host */
+object_property_add_link(obj, PROP_PXB_PCIE_HOST, TYPE_PXB_PCIE_HOST,
+ (Object **)>pxbhost,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
 static const TypeInfo pxb_dev_info = {
 .name  = TYPE_PXB_DEVICE,
 .parent= TYPE_PCI_DEVICE,
@@ -478,6 +531,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, 
void *data)
 
 k->realize = pxb_pcie_dev_realize;
 k->exit = pxb_dev_exitfn;
+k->config_read = pxb_pcie_config_read;
 k->vendor_id = PCI_VENDOR_ID_REDHAT;
 k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
 k->class_id = PCI_CLASS_BRIDGE_HOST;
@@ -492,6 +546,7 @@ static const TypeInfo pxb_pcie_dev_info = {
 .name  = TYPE_PXB_PCIE_DEVICE,
 .parent= TYPE_PCI_DEVICE,
 .instance_size = sizeof(PXBDev),
+.instance_init = pxb_pcie_dev_initfn,
 .class_init= pxb_pcie_dev_class_init,
 .interfaces = (InterfaceInfo[]) {
 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 870c4cd..1119210 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expa

[Qemu-devel] [RFC v3 2/6] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-08-01 Thread Zihan Yang
Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
corresponding MCFG space for them. This allows user-defined pxb-pcie
host bridges to be placed in different pci domain than q35 host.

The pci_host_bridges list is changed to be tail list to ensure the q35 host
is always the first element when traversing the list, because q35 host is
inserted beofre pxb-pcie hosts

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 115 +++-
 hw/i386/pc.c|  14 +++-
 hw/pci-bridge/pci_expander_bridge.c |  57 ++
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 ++-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  11 +++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 168 insertions(+), 44 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9e8350c..30bd0d5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -55,6 +55,7 @@
 #include "hw/i386/ich9.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "hw/i386/x86-iommu.h"
 
 #include "hw/acpi/aml-build.h"
@@ -89,6 +90,9 @@
 typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
+uint32_t domain_nr;
+uint8_t bus_nr; // start bus number
+struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
 typedef struct AcpiPmInfo {
@@ -2427,14 +2431,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 {
 AcpiTableMcfg *mcfg;
 const char *sig;
-int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+int len, count = 0;
+AcpiMcfgInfo *cfg = info;
+
+while (cfg) {
+++count;
+cfg = cfg->next;
+}
+len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
 
 mcfg = acpi_data_push(table_data, len);
-mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-/* Only a single allocation so no need to play with segments */
-mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-mcfg->allocation[0].start_bus_number = 0;
-mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
 
 /* MCFG is used for ECAM which can be enabled or disabled by guest.
  * To avoid table size changes (which create migration issues),
@@ -2448,6 +2454,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 } else {
 sig = "MCFG";
 }
+
+while (info) {
+mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
+mcfg[count].allocation[0].pci_segment = cpu_to_le16(info->domain_nr);
+mcfg[count].allocation[0].start_bus_number = info->bus_nr;
+mcfg[count++].allocation[0].end_bus_number = info->bus_nr + \
+PCIE_MMCFG_BUS(info->mcfg_size - 1);
+info = info->next;
+}
+
 build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
 }
 
@@ -2602,26 +2618,83 @@ struct AcpiBuildState {
 MemoryRegion *linker_mr;
 } AcpiBuildState;
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+static inline void cleanup_mcfg(AcpiMcfgInfo *mcfg)
+{
+AcpiMcfgInfo *tmp;
+while (mcfg) {
+tmp = mcfg->next;
+g_free(mcfg);
+mcfg = tmp;
+}
+}
+
+static AcpiMcfgInfo *acpi_get_mcfg(void)
 {
 Object *pci_host;
 QObject *o;
+uint32_t domain_nr;
+AcpiMcfgInfo *head = NULL, *tail, *mcfg;
 
 pci_host = acpi_get_i386_pci_host();
 g_assert(pci_host);
 
-o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-if (!o) {
-return false;
+while (pci_host) {
+/* pxb-pcie-hosts does not have domain_nr property, but a link
+ * to PXBDev. We first try to get pxbdev property, if NULL,
+ * then it is q35 host, otherwise it is pxb-pcie-host */
+Object *obj = object_property_get_link(pci_host,
+   PROP_PXB_PCIE_DEV, NULL);
+if (!obj) {
+/* we are in q35 host */
+obj = pci_host;
+}
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+/* Skip bridges that reside in the same domain with q35 host.
+ * Q35 always stays in pci domain 0, and is the first element
+ * in the pci_host_bridges list */
+if (head && domain_nr == 0) {
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
+conti

[Qemu-devel] [RFC v3 0/6] pci_expander_brdige: Put pxb-pcie host bridge into separate pci domain

2018-08-01 Thread Zihan Yang
(Forgot about the cc, repost it here)

NOTE: This patch set relies on seabios change. Unfortunately, I haven't got
it fully working in seabios, but I still post them here because patches
involve some port layout change to be reviewed, and it has been a long delay
since my last version. I'm trying to catch things up recently.

If you would like to see current status of seabios part, please refer to
https://mail.coreboot.org/pipermail/seabios/2018-August/012385.html

Currently only q35 host bridge is allocated an item in MCFG table, all pxb
host bridges stay within pci domain 0. This series of patches put each pxb
host bridge in separate pci domain, allocating a new MCFG table item for it.

Users can configure whether to put pxb host bridge into separate domain
by passing parameter domain_nr to pxb pcie device. start_bus property
indicates the Base Bus Number(BBN) of the pxb host bridge. Another property
max_bus specifies the maximum desired bus numbers to reduce MCFG space cost.
Example command is

-device pxb-pcie,id=br3,bus="pcie.0",start_bus=0,domain_nr=1,max_bus=15

Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
(15+1)=16 buses, which is much smaller than the default 256 buses.

The pxb host does not have an mch in it, as q35 host already has one. All
pxb host bridges just serve as expander bridges in QEMU, which makes them
a little simpler than q35 host bridge.

v3 <- v2:
- Replace duplicate properties in pxb pcie host with link property to PXBDev
- Allow seabios to access config space and data space of expander bridge
  through a different ioport, because 0xcf8 is attached only to sysbus.
- Add a new property start_bus to indicate the BBN of pxb host bridge. The
  bus_nr property is used as the bus number of pxb-pcie device on pcie.0 bus

v2 <- v1:
- Allow user to configure whether to put pxb-pcie into seperate domain
- Add AML description part of each host bridge
- Modify the location of MCFG space to between RAM hotplug and pci hole64



Zihan Yang (6):
  pci_expander_bridge: add type TYPE_PXB_PCIE_HOST
  acpi-build: allocate mcfg for pxb-pcie host bridges
  i386/acpi-build: describe new pci domain in AML
  pci_expander_bridge: Add config_read callback
  pci_expander_bridge: Add ioport for pxb host bus
  pci_expander_bridge: add start_bus property

 hw/i386/acpi-build.c| 193 +--
 hw/i386/pc.c|  14 +-
 hw/pci-bridge/pci_expander_bridge.c | 229 +++-
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 +-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  15 ++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 406 insertions(+), 60 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




[Qemu-devel] [RFC v3 5/6] pci_expander_bridge: Add ioport for pxb host bus

2018-08-01 Thread Zihan Yang
This enables seabios to read config file in pxb host bus other than sysbus

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 15 +++
 include/hw/pci-bridge/pci_expander_bridge.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index cdfdb90..38212db 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -226,6 +226,20 @@ static void pxb_pcie_host_initfn(Object *obj)
  qdev_prop_allow_set_link_before_realize, 0, NULL);
 }
 
+static void pxb_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+// FIX ME! Use specific port number for pxb-pcie host bridge, not scalable!
+/* port layout is | pxb1_cmd | pxb1_data | pxb2_cmd | pxb2_data | ... | */
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE, >conf_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE, >data_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+}
+
 static Property pxb_pcie_host_props[] = {
 DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
 PCIE_BASE_ADDR_UNMAPPED),
@@ -254,6 +268,7 @@ static void pxb_pcie_host_class_init(ObjectClass *class, 
void *data)
 
 dc->fw_name = "pcie";
 dc->props = pxb_pcie_host_props;
+dc->realize = pxb_pcie_host_realize;
 /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself 
*/
 dc->user_creatable = false;
 sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 1119210..e6d3b67 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -7,6 +7,9 @@
 #define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
 #define PROP_PXB_BUS_NR "bus_nr"
 
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE 0x1000
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE 0x1004
+
 uint64_t pxb_pcie_mcfg_hole(void);
 
 #endif
-- 
2.7.4




[Qemu-devel] [RFC v3 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-01 Thread Zihan Yang
The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 127 ++--
 1 file changed, 122 insertions(+), 5 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..6dd38de 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,10 +15,12 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
+#include "qapi/visitor.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
@@ -40,11 +42,20 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_PCIE_DEV "pxbdev"
+
+#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
+#define PROP_PXB_PCIE_MAX_BUS "max_bus"
+#define PROP_PXB_BUS_NR "bus_nr"
+#define PROP_PXB_NUMA_NODE "numa_node"
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
+uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
 uint16_t numa_node;
 } PXBDev;
@@ -58,6 +69,16 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
 static GList *pxb_dev_list;
 
 #define TYPE_PXB_HOST "pxb-host"
+#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
+#define PXB_PCIE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
+
+typedef struct PXBPCIEHost {
+PCIExpressHost parent_obj;
+
+/* pointers to PXBDev */
+PXBDev *pxbdev;
+} PXBPCIEHost;
 
 static int pxb_bus_num(PCIBus *bus)
 {
@@ -111,6 +132,35 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 return bus->bus_path;
 }
 
+/* Use a dedicated function for PCIe since pxb-host does
+ * not have a domain_nr field */
+static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
+  PCIBus *rootbus)
+{
+if (!pci_bus_is_express(rootbus)) {
+/* pxb-pcie-host cannot reside on a PCI bus */
+return NULL;
+}
+PXBBus *bus = PXB_PCIE_BUS(rootbus);
+
+/* get the pointer to PXBDev */
+Object *obj = object_property_get_link(OBJECT(host_bridge),
+   PROP_PXB_PCIE_DEV, NULL);
+
+snprintf(bus->bus_path, 8, "%04lx:%02x",
+ object_property_get_uint(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL),
+ pxb_bus_num(rootbus));
+return bus->bus_path;
+}
+
+static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 {
 const PCIHostState *pxb_host;
@@ -142,6 +192,31 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static void pxb_pcie_host_initfn(Object *obj)
+{
+PXBPCIEHost *s = PXB_PCIE_HOST_DEVICE(obj);
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4);
+memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
+  "pci-conf-data", 4);
+
+object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64",
+ pxb_pcie_host_get_mmcfg_size,
+ NULL, NULL, NULL, NULL);
+
+object_property_add_link(obj, PROP_PXB_PCIE_DEV, TYPE_PXB_PCIE_DEVICE,
+ (Object **)>pxbdev,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
+static Property pxb_pcie_host_props[] = {
+DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
+PCIE_BASE_ADDR_UNMAPPED),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pxb_host_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
@@ -155,12 +230,34 @@ static void pxb_host_class_init(ObjectClass *class, void 
*data)
 hc->root_bus_path = pxb_host_root_bus_path;
 }
 
+static void pxb_pcie_host_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+SysBusDeviceClass *sbc = SYS_BUS_DEVICE

[Qemu-devel] [RFC v3 6/6] pci_expander_bridge: add start_bus property

2018-08-01 Thread Zihan Yang
The former bus_nr property indicates the bus number of pxb-pcie device on
pcie.0 bus, not the Base Bus Number of pxb-pcie host bridge. Use start_bus
property to represent this BBN when building acpi table

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 22 +++---
 hw/pci-bridge/pci_expander_bridge.c | 25 ++---
 include/hw/pci-bridge/pci_expander_bridge.h |  2 +-
 3 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4b6ef78..874e0fa 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -91,7 +91,7 @@ typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
 uint32_t domain_nr;
-uint8_t bus_nr; // start bus number
+uint8_t start_bus; // start bus number
 struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
@@ -2129,7 +2129,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 QObject *o;
 PCIBus *bus = NULL;
 uint32_t domain_nr;
-uint8_t bus_nr;
+uint8_t start_bus;
 int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
@@ -2145,12 +2145,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 domain_nr = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 
-o = object_property_get_qobject(pci_host, "bus_nr", NULL);
+o = object_property_get_qobject(pci_host, "start_bus", NULL);
 if (!o) {
 /* we are in q35 host */
-bus_nr = 0;
+start_bus = 0;
 } else {
-bus_nr = qnum_get_uint(qobject_to(QNum, o));
+start_bus = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 }
 
@@ -2158,7 +2158,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 if (bus) {
 Aml *scope = aml_scope("PCI%d", index);
 aml_append(scope, aml_name_decl("_SEG", aml_int(domain_nr)));
-aml_append(scope, aml_name_decl("_BBN", aml_int(bus_nr)));
+aml_append(scope, aml_name_decl("_BBN", aml_int(start_bus)));
 /* Scan all PCI buses. Generate tables to support hotplug. */
 build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
@@ -2486,8 +2486,8 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 while (info) {
 mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
 mcfg[count].allocation[0].pci_segment = cpu_to_le16(info->domain_nr);
-mcfg[count].allocation[0].start_bus_number = info->bus_nr;
-mcfg[count++].allocation[0].end_bus_number = info->bus_nr + \
+mcfg[count].allocation[0].start_bus_number = info->start_bus;
+mcfg[count++].allocation[0].end_bus_number = info->start_bus + \
 PCIE_MMCFG_BUS(info->mcfg_size - 1);
 info = info->next;
 }
@@ -2710,12 +2710,12 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
 mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 
-o = object_property_get_qobject(obj, PROP_PXB_BUS_NR, NULL);
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_START_BUS, NULL);
 if (!o) {
 /* we are in q35 host again */
-mcfg->bus_nr = 0;
+mcfg->start_bus = 0;
 } else {
-mcfg->bus_nr = qnum_get_uint(qobject_to(QNum, o));
+mcfg->start_bus = qnum_get_uint(qobject_to(QNum, o));
 qobject_unref(o);
 }
 
diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index 38212db..85630ff 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -46,6 +46,7 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_BUS_NR "bus_nr"
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
@@ -62,8 +63,9 @@ typedef struct PXBDev {
 PXBPCIEHost *pxbhost;
 
 uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
+uint8_t start_bus;  /* indicates the BBN of pxb-pcie-host bridge */
 uint8_t max_bus;/* max bus number to use(including this one) */
-uint8_t bus_nr;
+uint8_t bus_nr; /* bus number of pxb-pcie device on pcei.0 bus */
 uint16_t numa_node;
 } PXBDev;
 
@@ -137,8 +139,8 @@ static void pxb_pcie_foreach(gpointer data, gpointer 
user_data)
 
 if (pxb->domain_nr > 0) {
 /* only reserve what users ask for to reduce memory cost. Plus one
- * as the interval [bus_nr, max_bus] has (max_bus-bus_nr+1) buses */
-

[Qemu-devel] [RFC v3 1/6] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-08-01 Thread Zihan Yang
The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
change it to a new type TYPE_PXB_PCIE_HOST to better utilize ECAM of PCIe

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 127 ++--
 1 file changed, 122 insertions(+), 5 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..6dd38de 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,10 +15,12 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
+#include "qapi/visitor.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
@@ -40,11 +42,20 @@ typedef struct PXBBus {
 #define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
 #define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
 
+#define PROP_PXB_PCIE_DEV "pxbdev"
+
+#define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
+#define PROP_PXB_PCIE_MAX_BUS "max_bus"
+#define PROP_PXB_BUS_NR "bus_nr"
+#define PROP_PXB_NUMA_NODE "numa_node"
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
+uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
 uint16_t numa_node;
 } PXBDev;
@@ -58,6 +69,16 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
 static GList *pxb_dev_list;
 
 #define TYPE_PXB_HOST "pxb-host"
+#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
+#define PXB_PCIE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
+
+typedef struct PXBPCIEHost {
+PCIExpressHost parent_obj;
+
+/* pointers to PXBDev */
+PXBDev *pxbdev;
+} PXBPCIEHost;
 
 static int pxb_bus_num(PCIBus *bus)
 {
@@ -111,6 +132,35 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 return bus->bus_path;
 }
 
+/* Use a dedicated function for PCIe since pxb-host does
+ * not have a domain_nr field */
+static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
+  PCIBus *rootbus)
+{
+if (!pci_bus_is_express(rootbus)) {
+/* pxb-pcie-host cannot reside on a PCI bus */
+return NULL;
+}
+PXBBus *bus = PXB_PCIE_BUS(rootbus);
+
+/* get the pointer to PXBDev */
+Object *obj = object_property_get_link(OBJECT(host_bridge),
+   PROP_PXB_PCIE_DEV, NULL);
+
+snprintf(bus->bus_path, 8, "%04lx:%02x",
+ object_property_get_uint(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL),
+ pxb_bus_num(rootbus));
+return bus->bus_path;
+}
+
+static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 {
 const PCIHostState *pxb_host;
@@ -142,6 +192,31 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static void pxb_pcie_host_initfn(Object *obj)
+{
+PXBPCIEHost *s = PXB_PCIE_HOST_DEVICE(obj);
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4);
+memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
+  "pci-conf-data", 4);
+
+object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64",
+ pxb_pcie_host_get_mmcfg_size,
+ NULL, NULL, NULL, NULL);
+
+object_property_add_link(obj, PROP_PXB_PCIE_DEV, TYPE_PXB_PCIE_DEVICE,
+ (Object **)>pxbdev,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
+static Property pxb_pcie_host_props[] = {
+DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
+PCIE_BASE_ADDR_UNMAPPED),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pxb_host_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
@@ -155,12 +230,34 @@ static void pxb_host_class_init(ObjectClass *class, void 
*data)
 hc->root_bus_path = pxb_host_root_bus_path;
 }
 
+static void pxb_pcie_host_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+SysBusDeviceClass *sbc = SYS_BUS_DEVICE

[Qemu-devel] [RFC v3 5/6] pci_expander_bridge: Add ioport for pxb host bus

2018-08-01 Thread Zihan Yang
This enables seabios to read config file in pxb host bus other than sysbus

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 15 +++
 include/hw/pci-bridge/pci_expander_bridge.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index cdfdb90..38212db 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -226,6 +226,20 @@ static void pxb_pcie_host_initfn(Object *obj)
  qdev_prop_allow_set_link_before_realize, 0, NULL);
 }
 
+static void pxb_pcie_host_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+// FIX ME! Use specific port number for pxb-pcie host bridge, not scalable!
+/* port layout is | pxb1_cmd | pxb1_data | pxb2_cmd | pxb2_data | ... | */
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE, >conf_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+
+sysbus_add_io(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE, >data_mem);
+sysbus_init_ioports(sbd, PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE + 
g_list_length(pxb_dev_list) * 8, 4);
+}
+
 static Property pxb_pcie_host_props[] = {
 DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
 PCIE_BASE_ADDR_UNMAPPED),
@@ -254,6 +268,7 @@ static void pxb_pcie_host_class_init(ObjectClass *class, 
void *data)
 
 dc->fw_name = "pcie";
 dc->props = pxb_pcie_host_props;
+dc->realize = pxb_pcie_host_realize;
 /* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself 
*/
 dc->user_creatable = false;
 sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 1119210..e6d3b67 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expander_bridge.h
@@ -7,6 +7,9 @@
 #define PROP_PXB_PCIE_DOMAIN_NR "domain_nr"
 #define PROP_PXB_BUS_NR "bus_nr"
 
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_ADDR_BASE 0x1000
+#define PXB_PCIE_HOST_BRIDGE_CONFIG_DATA_BASE 0x1004
+
 uint64_t pxb_pcie_mcfg_hole(void);
 
 #endif
-- 
2.7.4




[Qemu-devel] [RFC v3 4/6] pci_expander_bridge: Add config_read callback

2018-08-01 Thread Zihan Yang
This allows SeaBIOS to retrieve MCFG base and size when it initializes
pxb host bridges.

A backlink to PXBPCIEHost is added in PXBDev to achieve above goal

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 55 +
 include/hw/pci-bridge/pci_expander_bridge.h |  1 +
 2 files changed, 56 insertions(+)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index f50938f..cdfdb90 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -49,11 +49,18 @@ typedef struct PXBBus {
 #define PROP_PXB_PCIE_MAX_BUS "max_bus"
 #define PROP_PXB_NUMA_NODE "numa_node"
 
+typedef struct PXBPCIEHost PXBPCIEHost;
+typedef struct PXBDev PXBDev;
+
 typedef struct PXBDev {
 /*< private >*/
 PCIDevice parent_obj;
 /*< public >*/
 
+/* backlink to PXBPCIEHost, this makes it easier to get
+ * mcfg properties in pxb-pcie-host bridge */
+PXBPCIEHost *pxbhost;
+
 uint32_t domain_nr; /* PCI domain number, non-zero means separate domain */
 uint8_t max_bus;/* max bus number to use(including this one) */
 uint8_t bus_nr;
@@ -342,9 +349,15 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool 
pcie, Error **errp)
 if (pcie) {
 g_assert (pxb->max_bus >= pxb->bus_nr);
 ds = qdev_create(NULL, TYPE_PXB_PCIE_HOST);
+/* attach it under /machine, so that we can resolve a valid path in
+ * object_property_set_link below */
+object_property_add_child(qdev_get_machine(), "pxb-pcie-host[*]", 
OBJECT(ds), NULL);
 
+/* set link and backlink between PXBPCIEHost and PXBDev */
 object_property_set_link(OBJECT(ds), OBJECT(pxb),
  PROP_PXB_PCIE_DEV, errp);
+object_property_set_link(OBJECT(pxb), OBJECT(ds),
+ PROP_PXB_PCIE_HOST, errp);
 
 /* will be overwritten by firmware, but kept for readability */
 qdev_prop_set_uint64(ds, PCIE_HOST_MCFG_BASE,
@@ -413,6 +426,36 @@ static void pxb_dev_exitfn(PCIDevice *pci_dev)
 pxb_dev_list = g_list_remove(pxb_dev_list, pxb);
 }
 
+static uint32_t pxb_pcie_config_read(PCIDevice *d, uint32_t address, int len)
+{
+PXBDev *pxb = convert_to_pxb(d);
+uint32_t val;
+Object *host;
+
+   switch (address) {
+case MCH_HOST_BRIDGE_PCIEXBAR:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) & 
0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 4:
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = (object_property_get_uint(host, PCIE_HOST_MCFG_BASE, NULL) >> 
32) & 0x;
+break;
+case MCH_HOST_BRIDGE_PCIEXBAR + 8:  // Fix me!
+host = object_property_get_link(OBJECT(pxb), PROP_PXB_PCIE_HOST, NULL);
+assert(host);
+val = object_property_get_uint(host, PCIE_HOST_MCFG_SIZE, NULL) & 
0x;
+break;
+default:
+val = pci_default_read_config(d, address, len);
+break;
+}
+
+return val;
+}
+
 static Property pxb_dev_properties[] = {
 /* Note: 0 is not a legal PXB bus number. */
 DEFINE_PROP_UINT8(PROP_PXB_BUS_NR, PXBDev, bus_nr, 0),
@@ -447,6 +490,16 @@ static void pxb_dev_class_init(ObjectClass *klass, void 
*data)
 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
 }
 
+static void pxb_pcie_dev_initfn(Object *obj)
+{
+PXBDev *pxb = PXB_PCIE_DEV(obj);
+
+/* Add backlink to pxb-pcie-host */
+object_property_add_link(obj, PROP_PXB_PCIE_HOST, TYPE_PXB_PCIE_HOST,
+ (Object **)>pxbhost,
+ qdev_prop_allow_set_link_before_realize, 0, NULL);
+}
+
 static const TypeInfo pxb_dev_info = {
 .name  = TYPE_PXB_DEVICE,
 .parent= TYPE_PCI_DEVICE,
@@ -478,6 +531,7 @@ static void pxb_pcie_dev_class_init(ObjectClass *klass, 
void *data)
 
 k->realize = pxb_pcie_dev_realize;
 k->exit = pxb_dev_exitfn;
+k->config_read = pxb_pcie_config_read;
 k->vendor_id = PCI_VENDOR_ID_REDHAT;
 k->device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE;
 k->class_id = PCI_CLASS_BRIDGE_HOST;
@@ -492,6 +546,7 @@ static const TypeInfo pxb_pcie_dev_info = {
 .name  = TYPE_PXB_PCIE_DEVICE,
 .parent= TYPE_PCI_DEVICE,
 .instance_size = sizeof(PXBDev),
+.instance_init = pxb_pcie_dev_initfn,
 .class_init= pxb_pcie_dev_class_init,
 .interfaces = (InterfaceInfo[]) {
 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
diff --git a/include/hw/pci-bridge/pci_expander_bridge.h 
b/include/hw/pci-bridge/pci_expander_bridge.h
index 870c4cd..1119210 100644
--- a/include/hw/pci-bridge/pci_expander_bridge.h
+++ b/include/hw/pci-bridge/pci_expa

[Qemu-devel] [RFC v3 3/6] i386/acpi-build: describe new pci domain in AML

2018-08-01 Thread Zihan Yang
Describe new pci segments of host bridges in AML as new pci devices,
with _SEG and _BBN to let them be in DSDT

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c | 78 +++-
 1 file changed, 53 insertions(+), 25 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 30bd0d5..4b6ef78 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1832,6 +1832,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 aml_append(dev, aml_name_decl("_UID", aml_int(1)));
 aml_append(dev, build_q35_osc_method());
 aml_append(sb_scope, dev);
+
 aml_append(dsdt, sb_scope);
 
 build_hpet_aml(dsdt);
@@ -1875,6 +1876,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 crs_range_set_init(_range_set);
 bus = PC_MACHINE(machine)->bus;
+i = 1; // PCI0 is q35 host, pxb starts from 1
 if (bus) {
 QLIST_FOREACH(bus, >child, sibling) {
 uint8_t bus_num = pci_bus_num(bus);
@@ -1890,10 +1892,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 
 scope = aml_scope("\\_SB");
-dev = aml_device("PC%.02X", bus_num);
+dev = aml_device("PCI%d", i++);
 aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
 aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
-aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
 if (pci_bus_is_express(bus)) {
 aml_append(dev, build_q35_osc_method());
 }
@@ -2125,36 +2126,63 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 sb_scope = aml_scope("\\_SB");
 {
 Object *pci_host;
+QObject *o;
 PCIBus *bus = NULL;
+uint32_t domain_nr;
+uint8_t bus_nr;
+int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
+while (pci_host) {
+Object *obj = object_property_get_link(pci_host,
+   PROP_PXB_PCIE_DEV, NULL);
+if (!obj) {
+/* we are in q35 host */
+obj = pci_host;
+}
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_DOMAIN_NR, 
NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+o = object_property_get_qobject(pci_host, "bus_nr", NULL);
+if (!o) {
+/* we are in q35 host */
+bus_nr = 0;
+} else {
+bus_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+}
+
 bus = PCI_HOST_BRIDGE(pci_host)->bus;
-}
+if (bus) {
+Aml *scope = aml_scope("PCI%d", index);
+aml_append(scope, aml_name_decl("_SEG", aml_int(domain_nr)));
+aml_append(scope, aml_name_decl("_BBN", aml_int(bus_nr)));
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+/* Only add TPM once */
+if (index++ == 0 && TPM_IS_TIS(tpm_find())) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", 
aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+}
 
-if (TPM_IS_TIS(tpm_find())) {
-dev = aml_device("ISA.TPM");
-aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
-aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-   

[Qemu-devel] [RFC v3 3/6] i386/acpi-build: describe new pci domain in AML

2018-08-01 Thread Zihan Yang
Describe new pci segments of host bridges in AML as new pci devices,
with _SEG and _BBN to let them be in DSDT

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c | 78 +++-
 1 file changed, 53 insertions(+), 25 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 30bd0d5..4b6ef78 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1832,6 +1832,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 aml_append(dev, aml_name_decl("_UID", aml_int(1)));
 aml_append(dev, build_q35_osc_method());
 aml_append(sb_scope, dev);
+
 aml_append(dsdt, sb_scope);
 
 build_hpet_aml(dsdt);
@@ -1875,6 +1876,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 crs_range_set_init(_range_set);
 bus = PC_MACHINE(machine)->bus;
+i = 1; // PCI0 is q35 host, pxb starts from 1
 if (bus) {
 QLIST_FOREACH(bus, >child, sibling) {
 uint8_t bus_num = pci_bus_num(bus);
@@ -1890,10 +1892,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 
 scope = aml_scope("\\_SB");
-dev = aml_device("PC%.02X", bus_num);
+dev = aml_device("PCI%d", i++);
 aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
 aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
-aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
 if (pci_bus_is_express(bus)) {
 aml_append(dev, build_q35_osc_method());
 }
@@ -2125,36 +2126,63 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 sb_scope = aml_scope("\\_SB");
 {
 Object *pci_host;
+QObject *o;
 PCIBus *bus = NULL;
+uint32_t domain_nr;
+uint8_t bus_nr;
+int index = 0;
 
 pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
+while (pci_host) {
+Object *obj = object_property_get_link(pci_host,
+   PROP_PXB_PCIE_DEV, NULL);
+if (!obj) {
+/* we are in q35 host */
+obj = pci_host;
+}
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_DOMAIN_NR, 
NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+o = object_property_get_qobject(pci_host, "bus_nr", NULL);
+if (!o) {
+/* we are in q35 host */
+bus_nr = 0;
+} else {
+bus_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+}
+
 bus = PCI_HOST_BRIDGE(pci_host)->bus;
-}
+if (bus) {
+Aml *scope = aml_scope("PCI%d", index);
+aml_append(scope, aml_name_decl("_SEG", aml_int(domain_nr)));
+aml_append(scope, aml_name_decl("_BBN", aml_int(bus_nr)));
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+/* Only add TPM once */
+if (index++ == 0 && TPM_IS_TIS(tpm_find())) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", 
aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+}
 
-if (TPM_IS_TIS(tpm_find())) {
-dev = aml_device("ISA.TPM");
-aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
-aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-   

[Qemu-devel] [RFC v3 0/6] pci_expander_brdige: Put pxb-pcie host bridge into separate pci domain

2018-08-01 Thread Zihan Yang
NOTE: This patch set relies on seabios change. Unfortunately, I haven't got
it fully working in seabios, but I still post them here because patches
involve some port layout change to be reviewed, and it has been a long delay
since my last version. I'm trying to catch things up recently.

If you would like to see current status of seabios part, please refer to
https://mail.coreboot.org/pipermail/seabios/2018-August/012385.html

Currently only q35 host bridge is allocated an item in MCFG table, all pxb
host bridges stay within pci domain 0. This series of patches put each pxb
host bridge in separate pci domain, allocating a new MCFG table item for it.

Users can configure whether to put pxb host bridge into separate domain
by passing parameter domain_nr to pxb pcie device. start_bus property
indicates the Base Bus Number(BBN) of the pxb host bridge. Another property
max_bus specifies the maximum desired bus numbers to reduce MCFG space cost.
Example command is

-device pxb-pcie,id=br3,bus="pcie.0",start_bus=0,domain_nr=1,max_bus=15

Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
(15+1)=16 buses, which is much smaller than the default 256 buses.

The pxb host does not have an mch in it, as q35 host already has one. All
pxb host bridges just serve as expander bridges in QEMU, which makes them
a little simpler than q35 host bridge.

v3 <- v2:
- Replace duplicate properties in pxb pcie host with link property to PXBDev
- Allow seabios to access config space and data space of expander bridge
  through a different ioport, because 0xcf8 is attached only to sysbus.
- Add a new property start_bus to indicate the BBN of pxb host bridge. The
  bus_nr property is used as the bus number of pxb-pcie device on pcie.0 bus

v2 <- v1:
- Allow user to configure whether to put pxb-pcie into seperate domain
- Add AML description part of each host bridge
- Modify the location of MCFG space to between RAM hotplug and pci hole64



Zihan Yang (6):
  pci_expander_bridge: add type TYPE_PXB_PCIE_HOST
  acpi-build: allocate mcfg for pxb-pcie host bridges
  i386/acpi-build: describe new pci domain in AML
  pci_expander_bridge: Add config_read callback
  pci_expander_bridge: Add ioport for pxb host bus
  pci_expander_bridge: add start_bus property

 hw/i386/acpi-build.c| 193 +--
 hw/i386/pc.c|  14 +-
 hw/pci-bridge/pci_expander_bridge.c | 229 +++-
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 +-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  15 ++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 406 insertions(+), 60 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




[Qemu-devel] [RFC v3 2/6] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-08-01 Thread Zihan Yang
Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
corresponding MCFG space for them. This allows user-defined pxb-pcie
host bridges to be placed in different pci domain than q35 host.

The pci_host_bridges list is changed to be tail list to ensure the q35 host
is always the first element when traversing the list, because q35 host is
inserted beofre pxb-pcie hosts

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c| 115 +++-
 hw/i386/pc.c|  14 +++-
 hw/pci-bridge/pci_expander_bridge.c |  57 ++
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 ++-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |  11 +++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 168 insertions(+), 44 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9e8350c..30bd0d5 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -55,6 +55,7 @@
 #include "hw/i386/ich9.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "hw/i386/x86-iommu.h"
 
 #include "hw/acpi/aml-build.h"
@@ -89,6 +90,9 @@
 typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
+uint32_t domain_nr;
+uint8_t bus_nr; // start bus number
+struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
 typedef struct AcpiPmInfo {
@@ -2427,14 +2431,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 {
 AcpiTableMcfg *mcfg;
 const char *sig;
-int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+int len, count = 0;
+AcpiMcfgInfo *cfg = info;
+
+while (cfg) {
+++count;
+cfg = cfg->next;
+}
+len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
 
 mcfg = acpi_data_push(table_data, len);
-mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-/* Only a single allocation so no need to play with segments */
-mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-mcfg->allocation[0].start_bus_number = 0;
-mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
 
 /* MCFG is used for ECAM which can be enabled or disabled by guest.
  * To avoid table size changes (which create migration issues),
@@ -2448,6 +2454,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 } else {
 sig = "MCFG";
 }
+
+while (info) {
+mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
+mcfg[count].allocation[0].pci_segment = cpu_to_le16(info->domain_nr);
+mcfg[count].allocation[0].start_bus_number = info->bus_nr;
+mcfg[count++].allocation[0].end_bus_number = info->bus_nr + \
+PCIE_MMCFG_BUS(info->mcfg_size - 1);
+info = info->next;
+}
+
 build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
 }
 
@@ -2602,26 +2618,83 @@ struct AcpiBuildState {
 MemoryRegion *linker_mr;
 } AcpiBuildState;
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+static inline void cleanup_mcfg(AcpiMcfgInfo *mcfg)
+{
+AcpiMcfgInfo *tmp;
+while (mcfg) {
+tmp = mcfg->next;
+g_free(mcfg);
+mcfg = tmp;
+}
+}
+
+static AcpiMcfgInfo *acpi_get_mcfg(void)
 {
 Object *pci_host;
 QObject *o;
+uint32_t domain_nr;
+AcpiMcfgInfo *head = NULL, *tail, *mcfg;
 
 pci_host = acpi_get_i386_pci_host();
 g_assert(pci_host);
 
-o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-if (!o) {
-return false;
+while (pci_host) {
+/* pxb-pcie-hosts does not have domain_nr property, but a link
+ * to PXBDev. We first try to get pxbdev property, if NULL,
+ * then it is q35 host, otherwise it is pxb-pcie-host */
+Object *obj = object_property_get_link(pci_host,
+   PROP_PXB_PCIE_DEV, NULL);
+if (!obj) {
+/* we are in q35 host */
+obj = pci_host;
+}
+o = object_property_get_qobject(obj, PROP_PXB_PCIE_DOMAIN_NR, NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+/* Skip bridges that reside in the same domain with q35 host.
+ * Q35 always stays in pci domain 0, and is the first element
+ * in the pci_host_bridges list */
+if (head && domain_nr == 0) {
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
+conti

Re: [Qemu-devel] [RFC v2 3/3] acpi-build: describe new pci domain in AML

2018-06-21 Thread Zihan Yang
Marcel Apfelbaum  于2018年6月20日周三 下午3:46写道:
>
>
>
> On 06/12/2018 12:13 PM, Zihan Yang wrote:
> > Describe new pci segments of host bridges in AML. The host bridge list is
> > replaced by QTAILQ to let q35 host be processed first in every traverse
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/i386/acpi-build.c  | 69 
> > ++-
> >   hw/pci/pci.c  |  9 ---
> >   include/hw/pci/pci_host.h |  2 +-
> >   3 files changed, 50 insertions(+), 30 deletions(-)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 104e52d..a9f1503 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -2123,36 +2123,55 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   sb_scope = aml_scope("\\_SB");
> >   {
> >   Object *pci_host;
> > +QObject *o;
> >   PCIBus *bus = NULL;
> > +uint32_t domain_nr;
> > +bool q35host = true;
> >
> >   pci_host = acpi_get_i386_pci_host();
> > -if (pci_host) {
> > +while (pci_host) {
> > +o = object_property_get_qobject(pci_host, "domain_nr", NULL);
> > +assert(o);
> > +domain_nr = qnum_get_uint(qobject_to(QNum, o));
> > +qobject_unref(o);
> > +
> > +/* skip expander bridges that still reside in domain 0 */
> > +if (!q35host && domain_nr == 0) {
> > +pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), 
> > next));
>
> Why do you skip pci_hosts without domain? We still want to add them to
> the DSDT, right ?

I think I might misunderstand it. Currently QEMU seems to treat expander
host bridge as normal a PCIe device under main system bus. I thought we
want to preserve current behavior, so my purpose is to only add expander
bridges with a non-zero domain_nr into DSDT, and let the other bridges
be the PCIe devices of these bridges. Do you mean we should add every
host bridge no matter we want it to reside in a different domain or not?

> > +continue;
> > +}
> >   bus = PCI_HOST_BRIDGE(pci_host)->bus;
> > -}
> >
> > -if (bus) {
> > -Aml *scope = aml_scope("PCI0");
> > -/* Scan all PCI buses. Generate tables to support hotplug. */
> > -build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
> > +if (bus) {
> > +Aml *scope = aml_scope("PCI0");
> > +aml_append(scope, aml_name_decl("_SEG", 
> > aml_int(domain_nr)));
> > +/* For simplicity, base bus number starts from 0 */
> > +aml_append(scope, aml_name_decl("_BBN", aml_int(0)));
>
> Nice. _SEG and _BBN should be enough to let the guest know we have multiple
> PCI domains.
>
> > +/* Scan all PCI buses. Generate tables to support hotplug. 
> > */
> > +build_append_pci_bus_devices(scope, bus, 
> > pm->pcihp_bridge_en);
> >
> > -if (TPM_IS_TIS(tpm_find())) {
> > -dev = aml_device("ISA.TPM");
> > -aml_append(dev, aml_name_decl("_HID", 
> > aml_eisaid("PNP0C31")));
> > -aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > -crs = aml_resource_template();
> > -aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
> > -   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
> > -/*
> > -FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
> > -Rewrite to take IRQ from TPM device model and
> > -fix default IRQ value there to use some unused IRQ
> > - */
> > -/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
> > -aml_append(dev, aml_name_decl("_CRS", crs));
> > -aml_append(scope, dev);
> > +if (TPM_IS_TIS(tpm_find())) {
> > +dev = aml_device("ISA.TPM");
> > +aml_append(dev, aml_name_decl("_HID", 
> > aml_eisaid("PNP0C31")));
> > +aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > +crs = aml_resource_template();
> > +aml_append(crs, am

Re: [Qemu-devel] [RFC v2 2/3] acpi-build: allocate mcfg for pxb-pcie host bridges

2018-06-21 Thread Zihan Yang
Thanks for your review.

Marcel Apfelbaum  于2018年6月20日周三 下午3:41写道:
>
>
>
> On 06/12/2018 12:13 PM, Zihan Yang wrote:
> > Allocate new segment for pxb-pcie host bridges in MCFG table, and reserve
> > corresponding MCFG space for them. This allows user-defined pxb-pcie
> > host bridges to be placed in different pci domain than q35 host
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/i386/acpi-build.c| 97 
> > +++--
> >   hw/i386/pc.c| 14 -
> >   hw/pci-bridge/pci_expander_bridge.c | 52 +++-
> >   hw/pci-host/q35.c   |  2 +
> >   include/hw/i386/pc.h|  1 +
> >   include/hw/pci-bridge/pci_expander_bridge.h |  6 ++
> >   include/hw/pci-host/q35.h   |  1 +
> >   7 files changed, 137 insertions(+), 36 deletions(-)
> >   create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 9bc6d97..104e52d 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -89,6 +89,8 @@
> >   typedef struct AcpiMcfgInfo {
> >   uint64_t mcfg_base;
> >   uint32_t mcfg_size;
> > +uint32_t domain_nr;
> > +struct AcpiMcfgInfo *next;
> >   } AcpiMcfgInfo;
> >
> >   typedef struct AcpiPmInfo {
> > @@ -2427,14 +2429,16 @@ build_mcfg_q35(GArray *table_data, BIOSLinker 
> > *linker, AcpiMcfgInfo *info)
> >   {
> >   AcpiTableMcfg *mcfg;
> >   const char *sig;
> > -int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
> > +int len, count = 0;
> > +AcpiMcfgInfo *cfg = info;
> > +
> > +while (cfg) {
> > +++count;
> > +cfg = cfg->next;
> > +}
> > +len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
> >
> >   mcfg = acpi_data_push(table_data, len);
> > -mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
> > -/* Only a single allocation so no need to play with segments */
> > -mcfg->allocation[0].pci_segment = cpu_to_le16(0);
> > -mcfg->allocation[0].start_bus_number = 0;
> > -mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 
> > 1);
> >
> >   /* MCFG is used for ECAM which can be enabled or disabled by guest.
> >* To avoid table size changes (which create migration issues),
> > @@ -2448,6 +2452,15 @@ build_mcfg_q35(GArray *table_data, BIOSLinker 
> > *linker, AcpiMcfgInfo *info)
> >   } else {
> >   sig = "MCFG";
> >   }
> > +
> > +while (info) {
> > +mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
> > +mcfg[count].allocation[0].pci_segment = 
> > cpu_to_le16(info->domain_nr);
> > +mcfg[count].allocation[0].start_bus_number = 0;
> > +mcfg[count++].allocation[0].end_bus_number = 
> > PCIE_MMCFG_BUS(info->mcfg_size - 1);
>
> I think you want to use here max_bus property defined in the prev patch.

mcfg_size is calculated by the max_bus, but it does seems more readable
to use max_bus here.

> > +info = info->next;
> > +}
> > +
> >   build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, 
> > NULL);
> >   }
> >
> > @@ -2602,26 +2615,69 @@ struct AcpiBuildState {
> >   MemoryRegion *linker_mr;
> >   } AcpiBuildState;
> >
> > -static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> > +static inline void cleanup_mcfg(AcpiMcfgInfo *mcfg)
> > +{
> > +AcpiMcfgInfo *tmp;
> > +while (mcfg) {
> > +tmp = mcfg->next;
> > +g_free(mcfg);
> > +mcfg = tmp;
> > +}
> > +}
> > +
> > +static AcpiMcfgInfo *acpi_get_mcfg(void)
> >   {
> >   Object *pci_host;
> >   QObject *o;
> > +uint32_t domain_nr;
> > +AcpiMcfgInfo *head = NULL, *tail, *mcfg;
> >
> >   pci_host = acpi_get_i386_pci_host();
> >   g_assert(pci_host);
> >
> > -o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
> > -if (!o) {
> > -return false;
> > +while (pci_host) {
> > +o = object_property_get_qobject(pci_host, "domain_nr", NULL);
> > +if (!o) {
>
> If every pci_host is supposed to have a domain_nr is better to assert here.

OK, I get it.

> > +cleanup_mcfg(head);
&g

Re: [Qemu-devel] [RFC v2 1/3] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-06-21 Thread Zihan Yang
Marcel Apfelbaum  于2018年6月20日周三 下午2:38写道:
>
>
>
> On 06/12/2018 12:13 PM, Zihan Yang wrote:
> > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> > add a new type TYPE_PXB_PCIE_HOST to better utilize the ECAM of PCIe
> >
> > Signed-off-by: Zihan Yang 
> > ---
> >   hw/pci-bridge/pci_expander_bridge.c | 118 
> > ++--
> >   1 file changed, 114 insertions(+), 4 deletions(-)
> >
> > diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> > b/hw/pci-bridge/pci_expander_bridge.c
> > index e62de42..448b9fb 100644
> > --- a/hw/pci-bridge/pci_expander_bridge.c
> > +++ b/hw/pci-bridge/pci_expander_bridge.c
> > @@ -15,10 +15,12 @@
> >   #include "hw/pci/pci.h"
> >   #include "hw/pci/pci_bus.h"
> >   #include "hw/pci/pci_host.h"
> > +#include "hw/pci/pcie_host.h"
> >   #include "hw/pci/pci_bridge.h"
> >   #include "qemu/range.h"
> >   #include "qemu/error-report.h"
> >   #include "sysemu/numa.h"
> > +#include "qapi/visitor.h"
> >
> >   #define TYPE_PXB_BUS "pxb-bus"
> >   #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
> > @@ -45,7 +47,10 @@ typedef struct PXBDev {
> >   PCIDevice parent_obj;
> >   /*< public >*/
> >
> > -uint8_t bus_nr;
> > +bool sep_domain;/* whether it resides in separate PCI segment */
> > +uint32_t domain_nr; /* PCI domain(segment) number, should be 0 if 
> > sep_domain is false */
> > +uint8_t max_bus;/* max number of buses to use */
> > +uint8_t bus_nr; /* should be 0 when in separate domain */
> >   uint16_t numa_node;
> >   } PXBDev;
> >
> > @@ -58,6 +63,18 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
> >   static GList *pxb_dev_list;
> >
> >   #define TYPE_PXB_HOST "pxb-host"
> > +#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
> > +#define PXB_PCIE_HOST_DEVICE(obj) \
> > + OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
> > +
> > +typedef struct PXBPCIEHost {
> > +PCIExpressHost parent_obj;
> > +
> > +/* should only inherit from PXBDev */
> > +uint32_t domain_nr;
> > +uint8_t bus_nr;
> > +uint8_t max_bus;
>
> I don't think you need the above properties to be part of the
> PXBPCIEHost object.
>
> Please see if you can't get a pointer to the PxbDev.

OK, I'll try pointer then.

> > +} PXBPCIEHost;
> >
> >   static int pxb_bus_num(PCIBus *bus)
> >   {
> > @@ -111,6 +128,31 @@ static const char *pxb_host_root_bus_path(PCIHostState 
> > *host_bridge,
> >   return bus->bus_path;
> >   }
> >
> > +/* Use a dedicated function for PCIe since pxb-host does
> > + * not have a domain_nr field */
> > +static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
> > +  PCIBus *rootbus)
> > +{
> > +if (!pci_bus_is_express(rootbus)) {
> > +/* pxb-pcie-host cannot reside on a PCI bus */
> > +return NULL;
> > +}
> > +PXBBus *bus = PXB_PCIE_BUS(rootbus);
> > +
> > +snprintf(bus->bus_path, 8, "%04lx:%02x",
> > + object_property_get_uint((Object *)host_bridge, "domain_nr", 
> > NULL),
> > + pxb_bus_num(rootbus));
> > +return bus->bus_path;
> > +}
> > +
> > +static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const 
> > char *name,
> > +void *opaque, Error **errp)
> > +{
> > +PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
> > +
> > +visit_type_uint64(v, name, >size, errp);
> > +}
> > +
> >   static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
> >   {
> >   const PCIHostState *pxb_host;
> > @@ -142,6 +184,30 @@ static char *pxb_host_ofw_unit_address(const 
> > SysBusDevice *dev)
> >   return NULL;
> >   }
> >
> > +static void pxb_pcie_host_initfn(Object *obj)
> > +{
> > +PCIHostState *phb = PCI_HOST_BRIDGE(obj);
> > +
> > +memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
> > +  "pci-conf-idx", 4);
> > +memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
> > +  "pci-conf-data", 4);
> > +
> > +object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64&quo

Re: [Qemu-devel] [RFC v2 1/3] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-06-13 Thread Zihan Yang
Michael S. Tsirkin  于2018年6月13日周三 下午10:46写道:
>
> On Wed, Jun 13, 2018 at 04:23:40PM +0800, Zihan Yang wrote:
> > Michael S. Tsirkin  于2018年6月12日周二 下午9:43写道:
> > >
> > > On Tue, Jun 12, 2018 at 05:13:22PM +0800, Zihan Yang wrote:
> > > > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by 
> > > > default,
> > > > add a new type TYPE_PXB_PCIE_HOST to better utilize the ECAM of PCIe
> > > >
> > > > Signed-off-by: Zihan Yang 
> > >
> > > I have a concern that there are lots of new properties
> > > added here, I'm not sure how are upper layers supposed to
> > > manage them all.
> > >
> > > E.g. bus_nr supplied in several places, domain_nr for which
> > > it's not clear how it is supposed to be allocated, etc.
> >
> > Indeed they seem to double the properties, but the pxb host is
> > an internal structure of pxb-pcie device, created in pxb-pcie's
> > realization procedure, and acpi-build queries host bridges instead
> > of pxb-pcie devices. This means that users can not directly specify
> > the property of pxb host bridge, but must 'inherit' from pxb-pcie
> > devices. I had thought about changing the acpi-build process,
> > but that would require more modifications.
> > As for the properties, bus_nr means the start bus number
> > of this host bridge. It is used when pxb-pcie is in pci domain 0
> > with q35 host to avoid bus number confliction. When it is placed
> > in a separate pci domain, it is not used and should be 0.
> >
> > max_bus means how many buses the user desires, EACH bus in
> > PCIe requires 1MB configuration space, thus specifying it could
> > reduce the reserved memory in MMCFG as suggested by Marcel.
> > Typically, the user can specify
> >
> > -device pxb-pcie,id=br1,bus="pcie.0",sep_domain=on,domain_nr=1,max_bus=130
> >
> > this will place the buses under this pxb host bridge in pci domain
> > 1, and reserve (130 + 1) = 131 buses for it. The start bus number
> > is always 0 currently for simplicity.
> >
> > > Can the management interface be simplified?
> > > Ideally we wouldn't have to teach libvirt new tricks,
> > > just generalize pxb support slightly.
> >
> > We can delete 'sep_domain' property, I just find 'domain_nr'
> > already indicates domain number. But domain_nr and
> > max_bus seems unremovable, although they look 'redundant'
> > because they appear twice.
> >
> > I'm not familiar with libvirt, but from the perspective of user,
> > only 2 properties are added(domain_nr and max_bus, if we
> > delete sep_domain), though the internal structure actually has
> > changed.
>
> If you want a property for an internal purpose,
> you can have a property starting with "x-" this way
> we don't commit to maintaining it.

OK, I'll change that in pxb-pcie-host.

> --
> MST



Re: [Qemu-devel] [RFC v2 1/3] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-06-13 Thread Zihan Yang
Michael S. Tsirkin  于2018年6月12日周二 下午9:43写道:
>
> On Tue, Jun 12, 2018 at 05:13:22PM +0800, Zihan Yang wrote:
> > The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
> > add a new type TYPE_PXB_PCIE_HOST to better utilize the ECAM of PCIe
> >
> > Signed-off-by: Zihan Yang 
>
> I have a concern that there are lots of new properties
> added here, I'm not sure how are upper layers supposed to
> manage them all.
>
> E.g. bus_nr supplied in several places, domain_nr for which
> it's not clear how it is supposed to be allocated, etc.

Indeed they seem to double the properties, but the pxb host is
an internal structure of pxb-pcie device, created in pxb-pcie's
realization procedure, and acpi-build queries host bridges instead
of pxb-pcie devices. This means that users can not directly specify
the property of pxb host bridge, but must 'inherit' from pxb-pcie
devices. I had thought about changing the acpi-build process,
but that would require more modifications.

As for the properties, bus_nr means the start bus number
of this host bridge. It is used when pxb-pcie is in pci domain 0
with q35 host to avoid bus number confliction. When it is placed
in a separate pci domain, it is not used and should be 0.

max_bus means how many buses the user desires, EACH bus in
PCIe requires 1MB configuration space, thus specifying it could
reduce the reserved memory in MMCFG as suggested by Marcel.
Typically, the user can specify

-device pxb-pcie,id=br1,bus="pcie.0",sep_domain=on,domain_nr=1,max_bus=130

this will place the buses under this pxb host bridge in pci domain
1, and reserve (130 + 1) = 131 buses for it. The start bus number
is always 0 currently for simplicity.

> Can the management interface be simplified?
> Ideally we wouldn't have to teach libvirt new tricks,
> just generalize pxb support slightly.

We can delete 'sep_domain' property, I just find 'domain_nr'
already indicates domain number. But domain_nr and
max_bus seems unremovable, although they look 'redundant'
because they appear twice.

I'm not familiar with libvirt, but from the perspective of user,
only 2 properties are added(domain_nr and max_bus, if we
delete sep_domain), though the internal structure actually has
changed.



[Qemu-devel] [RFC v2 3/3] acpi-build: describe new pci domain in AML

2018-06-12 Thread Zihan Yang
Describe new pci segments of host bridges in AML. The host bridge list is
replaced by QTAILQ to let q35 host be processed first in every traverse

Signed-off-by: Zihan Yang 
---
 hw/i386/acpi-build.c  | 69 ++-
 hw/pci/pci.c  |  9 ---
 include/hw/pci/pci_host.h |  2 +-
 3 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 104e52d..a9f1503 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2123,36 +2123,55 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 sb_scope = aml_scope("\\_SB");
 {
 Object *pci_host;
+QObject *o;
 PCIBus *bus = NULL;
+uint32_t domain_nr;
+bool q35host = true;
 
 pci_host = acpi_get_i386_pci_host();
-if (pci_host) {
+while (pci_host) {
+o = object_property_get_qobject(pci_host, "domain_nr", NULL);
+assert(o);
+domain_nr = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+/* skip expander bridges that still reside in domain 0 */
+if (!q35host && domain_nr == 0) {
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), 
next));
+continue;
+}
 bus = PCI_HOST_BRIDGE(pci_host)->bus;
-}
 
-if (bus) {
-Aml *scope = aml_scope("PCI0");
-/* Scan all PCI buses. Generate tables to support hotplug. */
-build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
+if (bus) {
+Aml *scope = aml_scope("PCI0");
+aml_append(scope, aml_name_decl("_SEG", aml_int(domain_nr)));
+/* For simplicity, base bus number starts from 0 */
+aml_append(scope, aml_name_decl("_BBN", aml_int(0)));
+/* Scan all PCI buses. Generate tables to support hotplug. */
+build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
 
-if (TPM_IS_TIS(tpm_find())) {
-dev = aml_device("ISA.TPM");
-aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
-aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
-   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
-/*
-FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
-Rewrite to take IRQ from TPM device model and
-fix default IRQ value there to use some unused IRQ
- */
-/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
+if (TPM_IS_TIS(tpm_find())) {
+dev = aml_device("ISA.TPM");
+aml_append(dev, aml_name_decl("_HID", 
aml_eisaid("PNP0C31")));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
+   TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
+/*
+FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+Rewrite to take IRQ from TPM device model and
+fix default IRQ value there to use some unused IRQ
+ */
+/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
+aml_append(dev, aml_name_decl("_CRS", crs));
+aml_append(scope, dev);
+}
+
+aml_append(sb_scope, scope);
 }
-
-aml_append(sb_scope, scope);
+/* q35 host is the first one in the tail queue */
+q35host = false;
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
 }
 }
 
@@ -2645,7 +2664,7 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
 qobject_unref(o);
 /* skip q35 host and bridges that reside in the same domain with it */
 if (domain_nr == 0) {
-pci_host = OBJECT(QLIST_NEXT(PCI_HOST_BRIDGE(pci_host), next));
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
 continue;
 }
 
@@ -2674,7 +2693,7 @@ static AcpiMcfgInfo *acpi_get_mcfg(void)
 assert(o);
 mcfg->domain_nr = qnum_get_uint(qobject_to(QNum, o));
 
-pci_host = OBJECT(QLIST_NEXT(PCI_HOST_BRIDGE(pci_host), next));
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_ho

[Qemu-devel] [RFC v2 1/3] pci_expander_bridge: add type TYPE_PXB_PCIE_HOST

2018-06-12 Thread Zihan Yang
The inner host bridge created by pxb-pcie is TYPE_PXB_PCI_HOST by default,
add a new type TYPE_PXB_PCIE_HOST to better utilize the ECAM of PCIe

Signed-off-by: Zihan Yang 
---
 hw/pci-bridge/pci_expander_bridge.c | 118 ++--
 1 file changed, 114 insertions(+), 4 deletions(-)

diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..448b9fb 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -15,10 +15,12 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_host.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
+#include "qapi/visitor.h"
 
 #define TYPE_PXB_BUS "pxb-bus"
 #define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
@@ -45,7 +47,10 @@ typedef struct PXBDev {
 PCIDevice parent_obj;
 /*< public >*/
 
-uint8_t bus_nr;
+bool sep_domain;/* whether it resides in separate PCI segment */
+uint32_t domain_nr; /* PCI domain(segment) number, should be 0 if 
sep_domain is false */
+uint8_t max_bus;/* max number of buses to use */
+uint8_t bus_nr; /* should be 0 when in separate domain */
 uint16_t numa_node;
 } PXBDev;
 
@@ -58,6 +63,18 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
 static GList *pxb_dev_list;
 
 #define TYPE_PXB_HOST "pxb-host"
+#define TYPE_PXB_PCIE_HOST "pxb-pcie-host"
+#define PXB_PCIE_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIEHost, (obj), TYPE_PXB_PCIE_HOST)
+
+typedef struct PXBPCIEHost {
+PCIExpressHost parent_obj;
+
+/* should only inherit from PXBDev */
+uint32_t domain_nr;
+uint8_t bus_nr;
+uint8_t max_bus;
+} PXBPCIEHost;
 
 static int pxb_bus_num(PCIBus *bus)
 {
@@ -111,6 +128,31 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 return bus->bus_path;
 }
 
+/* Use a dedicated function for PCIe since pxb-host does
+ * not have a domain_nr field */
+static const char *pxb_pcie_host_root_bus_path(PCIHostState *host_bridge,
+  PCIBus *rootbus)
+{
+if (!pci_bus_is_express(rootbus)) {
+/* pxb-pcie-host cannot reside on a PCI bus */
+return NULL;
+}
+PXBBus *bus = PXB_PCIE_BUS(rootbus);
+
+snprintf(bus->bus_path, 8, "%04lx:%02x",
+ object_property_get_uint((Object *)host_bridge, "domain_nr", 
NULL),
+ pxb_bus_num(rootbus));
+return bus->bus_path;
+}
+
+static void pxb_pcie_host_get_mmcfg_size(Object *obj, Visitor *v, const char 
*name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 {
 const PCIHostState *pxb_host;
@@ -142,6 +184,30 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static void pxb_pcie_host_initfn(Object *obj)
+{
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4);
+memory_region_init_io(>data_mem, obj, _host_data_le_ops, phb,
+  "pci-conf-data", 4);
+
+object_property_add(obj, PCIE_HOST_MCFG_SIZE, "uint64",
+ pxb_pcie_host_get_mmcfg_size,
+ NULL, NULL, NULL, NULL);
+
+}
+
+static Property pxb_pcie_host_props[] = {
+DEFINE_PROP_UINT64(PCIE_HOST_MCFG_BASE, PXBPCIEHost, parent_obj.base_addr,
+PCIE_BASE_ADDR_UNMAPPED),
+DEFINE_PROP_UINT32("domain_nr", PXBPCIEHost, domain_nr, 0),
+DEFINE_PROP_UINT8("bus_nr", PXBPCIEHost, bus_nr, 0),
+DEFINE_PROP_UINT8("max_bus", PXBPCIEHost, max_bus, 255),
+DEFINE_PROP_END_OF_LIST(),
+};
+
 static void pxb_host_class_init(ObjectClass *class, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(class);
@@ -155,12 +221,34 @@ static void pxb_host_class_init(ObjectClass *class, void 
*data)
 hc->root_bus_path = pxb_host_root_bus_path;
 }
 
+static void pxb_pcie_host_class_init(ObjectClass *class, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(class);
+SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(class);
+PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(class);
+
+dc->fw_name = "pci";
+dc->props = pxb_pcie_host_props;
+/* Reason: Internal part of the pxb/pxb-pcie device, not usable by itself 
*/
+dc->user_creatable = false;
+sbc->explicit_ofw_unit_address = pxb_host_ofw_unit_address;
+hc->root_bus_path = pxb_pcie_host_root_bus_path;
+}
+
 static const TypeI

[Qemu-devel] [RFC v2 0/3] pci_expander_brdige: Put pxb-pcie host bridge into separate pci domain

2018-06-12 Thread Zihan Yang
Hi all, after some delay, here is the v2 version of putting pxb host bridge
into separate pci domain.

Currently only q35 host bridge is allocated an item in MCFG table, all pxb
host bridges stay within pci domain 0. This series of patches put each pxb
host bridge in separate pci domain, allocating a new MCFG table item for it.

Users can configure whether to put pxb host bridge into separate domain
or just leave it in pci domain 0 by passing parameter sep_domain(bool) and
domain_nr(uint32_t), they can also specify the maximum desired bus numbers
to reduce MCFG space cost, for example,

-device 
pxb-pcie,id=bridge3,bus="pcie.0",sep_domain=on,domain_nr=1,max_bus=130

Then this pxb-pcie host bridge is placed at pci domain 1, and only reserve
(130+1)=131 buses, which is much smaller than the default 256 buses.

The pxb host does not have an mch in it, as q35 host already has one. All
pxb host bridges just serve as expander bridges in QEMU, which makes them
a little simpler than q35 host bridge.

There are some things remaining TODO. For example, deal with the pci data
write to pxb host bridges, but that will need some work in SeaBIOS, which
I am starting soon. Also, we might need to limit the number of pci domains
in case it exceeds the bit limit of physical address when EPT is enabled.

v2 <- v1:
- Allow user to configure whether to put pxb-pcie into seperate domain
- Add AML description part of each host bridge
- Modify the location of MCFG space to between RAM hotplug and pci hole64


Zihan Yang (3):
  pci_expander_bridge: add type TYPE_PXB_PCIE_HOST
  acpi-build: allocate mcfg for pxb-pcie host bridges
  acpi-build: describe new pci domain in AML

 hw/i386/acpi-build.c| 162 
 hw/i386/pc.c|  14 ++-
 hw/pci-bridge/pci_expander_bridge.c | 142 +++-
 hw/pci-host/q35.c   |   2 +
 hw/pci/pci.c|   9 +-
 include/hw/i386/pc.h|   1 +
 include/hw/pci-bridge/pci_expander_bridge.h |   6 ++
 include/hw/pci-host/q35.h   |   1 +
 include/hw/pci/pci_host.h   |   2 +-
 9 files changed, 285 insertions(+), 54 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




Re: [Qemu-devel] QEMU: Multiple PCI domains for x86 PCI Express Machine (Q35)

2018-05-24 Thread Zihan Yang
2018-05-24 19:54 GMT+08:00 Marcel Apfelbaum <marcel.apfelb...@gmail.com>:
> Hi Aaron
>
> On 05/24/2018 12:31 PM, Wei, Aaron wrote:
>>
>>
>> Hi,  Marcel
>>
>> It's my pleasure to write to you on behalf of a team who is developing the
>> Intel VMD virtualization base on QEMU in Dell EMC.
>>
>> From https://www.outreachy.org. we find that you are working on the
>> Multiple PCI domain feature which we think may be  very helpful to our
>> current work.
>>
>
> We are glad you are considering using the project.
> The project got delayed for next "Outreachy/GSOC" round, however Zihan Yang
> <whois.zihan.y...@gmail.com>,
> a PhD student, graciously offered to try it in his private time.

Hi Marcel

Thank you for CCing and mentioning me in the email. I'm really glad to know
people are interested in the project. It is really a joy to contribute
to it. By the
way, I'm currently a master student but that doesn't matter here.

>> We’ll be grateful if you can share some information about,
>>
>> 1.What’s the present developing status?
>>
>
> An early RFC (not a working version) was posted here:
> https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg04664.html
> The mail thread includes an interesting discussion on issues and constrains.
>
>> 2.When would it possibly be ready? Or when could we get it from QEMU repo?
>>
>
> Since is currently developed as a side project we don't have a clear
> timeline,
> you are welcome to contribute with ideas, reviews, tests and patches :) .
> Any help is appreciated.

Hi Aaron

Thanks for your interest, I wish I could finish it as soon as
possible, but I'm afraid
I can't give any guarantee right now. As Marcel said, we don't have a
clear timeline
yet. The official project lasts 12 weeks, and I plan to finish it
before September.
The pace might be faster after June when all the exams are finished.

About the project itself, we actually just started yet. You might want
to look at the
initial patch set I submitted a few days ago, as posted by Marcel in
the last email.
These patches are just POC, asking for reviews and comments. The AML part in
QEMU and the firmware part are not implemented yet. I get many good reviews
from Marcel and other members, and am preparing for a v2 patch.

Actually, even if I finish all the work, there still might be some
time before the
patches are available in the upstream because there will be reviews
and comments,
and they are likely to go through many versions before they are merged.

>> We appreciate and  look forward to your reply.
>>
>
> I hope I helped.

I hope I helped too :)
Feel free to comment/review/email/contribute if you have any questions about
this project.

Thanks
Zihan



Re: [Qemu-devel] [RFC 3/3] acpi-build: allocate mcfg for multiple host bridges

2018-05-24 Thread Zihan Yang
2018-05-24 1:33 GMT+08:00 Marcel Apfelbaum :
>
>> * IOMMUs cannot span domains either, so bringing new domains introduces
>> the need
>>   to add a VT-d DHRD or vIOMMU per PCIe domain
>
>
> Not really, you may have PCI domains not associated to an vIOMMU. As a first
> step,
> you should not deal with it. The IOMMU can't span over multiple domains,
> yes.
>

OK, I'll leave IOMMU part at present.

>> * 64-bit space is crowded and there are no standards within QEMU for
>> placing per
>>   domain 64-bit MMIO and MMCFG ranges
>
>
> Yes, but we do have some layout for the "over 4G" area and we can continue
> building on it.

That sounds good.

>> * NUMA modeling seems to be a stronger motivation than the limitation of
>> 256 but
>>   nubmers, that each NUMA node holds its own PCI(e) sub-hierarchy
>
>
> No, the 256 devices limitation is the biggest issue we are trying to solve.

Great, the initial purpose still holds.

> You are on the right path, this discussion is meant to help you understand
> wider concerns
> and make you aware of different constrains we didn't think about.
>
> Good luck with the next version!

It is indeed very helpful. I'll try to deal with (at least most of) the issues
int v2. Thanks for your valuable reviews!

Zihan



Re: [Qemu-devel] [RFC 3/3] acpi-build: allocate mcfg for multiple host bridges

2018-05-24 Thread Zihan Yang
> > The original purpose was just to support multiple segments in Intel
> > Q35 archtecure for PCIe topology, which makes bus number a less scarce
> > resource. The patches are very primitive and many things are left for
> > firmware to finish(the initial plan was to implement it in SeaBIOS),
> > the AML part in QEMU is not finished either. I'm not familiar with
> > OVMF or edk2, so there is no plan to touch it yet, but it seems not
> > necessary since it already supports multi-segment in the end.
>
> That's incorrect. EDK2 stands for "EFI Development Kit II", and it is a
> collection of "universal" (= platform- and ISA-independent) modules
> (drivers and libraries), and platfor- and/or ISA-dependent modules
> (drivers and libraries). The OVMF firmware is built from a subset of
> these modules; the final firmware image includes modules from both
> categories -- universal modules, and modules specific to the i440fx and
> Q35 QEMU boards. The first category generally lives under MdePkg/,
> MdeModulePkg/, UefiCpuPkg/, NetworkPkg/, PcAtChipsetPkg, etc; while the
> second category lives under OvmfPkg/.
>
> (The exact same applies to the ArmVirtQemu firmware, with the second
> category consisting of ArmVirtPkg/ and OvmfPkg/ modules.)
>
> When we discuss anything PCI-related in edk2, it usually affects both
> categories:
>
> (a) the universal/core modules, such as
>
>   - the PCI host bridge / root bridge driver at
> "MdeModulePkg/Bus/Pci/PciHostBridgeDxe",
>
>   - the PCI bus driver at "MdeModulePkg/Bus/Pci/PciBusDxe",
>
> (b) and the platform-specific modules, such as
>
>   - "OvmfPkg/IncompatiblePciDeviceSupportDxe" which causes PciBusDxe to
> allocate 64-bit MMIO BARs above 4 GB, regardless of option ROM
> availability (as long as a CSM is not present), conserving 32-bit
> MMIO aperture for 32-bit BARs,
>
>   - "OvmfPkg/PciHotPlugInitDxe", which implements support for QEMU's
> resource reservation hints, so that we can avoid IO space exhaustion
> with many PCIe root ports, and so that we can reserve MMIO aperture
> for hot-plugging devices with large MMIO BARs,
>
>   - "OvmfPkg/Library/DxePciLibI440FxQ35", which is a low-level PCI
> config space access library, usable in the DXE and later phases,
> that plugs into several drivers, and uses 0xCF8/0xCFC on i440x, and
> ECAM on Q35,
>
>   - "OvmfPkg/Library/PciHostBridgeLib", which plugs into
> "PciHostBridgeDxe" above, exposing the various resource apertures to
> said host bridge / root bridge driver, and implementing support for
> the PXB / PXBe devices,
>
>   - "OvmfPkg/PlatformPei", which is an early (PEI phase) module with a
> grab-bag of platform support code; e.g. it informs
> "DxePciLibI440FxQ35" above about the QEMU board being Q35 vs.
> i440fx, it configures the ECAM (exbar) registers on Q35, it
> determines where the 32-bit and 64-bit PCI MMIO apertures should be;
>
>   - "ArmVirtPkg/Library/BaseCachingPciExpressLib", which is the
> aarch64/virt counterpart of "DxePciLibI440FxQ35" above,
>
>   - "ArmVirtPkg/Library/FdtPciHostBridgeLib", which is the aarch64/virt
> counterpart of "PciHostBridgeLib", consuming the DTB exposed by
> qemu-system-aarch64,
>
>   - "ArmVirtPkg/Library/FdtPciPcdProducerLib", which is an internal
> library that turns parts of the DTB that is exposed by
> qemu-system-aarch64 into various PCI-related, firmware-wide, scalar
> variables (called "PCDs"), upon which both
> "BaseCachingPciExpressLib" and "FdtPciHostBridgeLib" rely.
>
> The point is that any PCI feature in any edk2 platform firmware comes
> together from (a) core module support for the feature, and (b) platform
> integration between the core code and the QEMU board in question.
>
> If (a) is missing, that implies a very painful uphill battle, which is
> why I'd been loudly whining, initially, in this thread, until I realized
> that the core support was there in edk2, for PCIe segments.
>
> However, (b) is required as well -- i.e., platform integration under
> OvmfPkg/ and perhaps ArmVirtPkg/, between the QEMU boards and the core
> edk2 code --, and that definitely doesn't exist for the PCIe segments
> feature.
>
> If (a) exists and is flexible enough, then we at least have a chance at
> writing the platform support code (b) for it. So that's why I've stopped
> whining. Writing (b) is never easy -- in this case, a great many of the
> platform modules that I've listed above, under OvmfPkg/ pathnames, could
> be affected, or even be eligible for replacement -- but (b) is at least
> imaginable practice. Modules in category (a) are shipped *in* -- not
> "on" -- every single physical UEFI platform that you can buy today,
> which is one reason why it's hugely difficult to implement nontrivial
> changes for them.
>
> In brief: your statement is incorrect because category (b) is missing.
> And that requires dedicated QEMU support, similarly to how
> "OvmfPkg/PciHotPlugInitDxe" 

Re: [Qemu-devel] [RFC 3/3] acpi-build: allocate mcfg for multiple host bridges

2018-05-23 Thread Zihan Yang
Hi all,

Thanks for all your comments and suggestions, I wasn't expecting so many
professional
reviewers. Some of the things you mentioned are beyond my knowledge right
now.
Please correct me if I'm wrong below.

The original purpose was just to support multiple segments in Intel Q35
archtecure
for PCIe topology, which makes bus number a less scarce resource. The
patches are
very primitive and many things are left for firmware to finish(the initial
plan was
to implement it in SeaBIOS), the AML part in QEMU is not finished either.
I'm not
familiar with OVMF or edk2, so there is no plan to touch it yet, but it
seems not
necessary since it already supports multi-segment in the end.

Also, in this patch the assumption is one domain per host bridge, described
by '_SEG()'
in AML, which means a ECAM range per host bridge, but that should be
configurable
if the user prefers to staying in the same domain, I guess?

I'd like to list a few things you've discussed to confirm I don't get it
wrong

* ARI enlarges the number of functions, but they does not solve the
hot-pluggable issue.
  The multifunction PCIe endpoints cannot span PCIe domains
* IOMMUs cannot span domains either, so bringing new domains introduces the
need
  to add a VT-d DHRD or vIOMMU per PCIe domain
* 64-bit space is crowded and there are no standards within QEMU for
placing per
  domain 64-bit MMIO and MMCFG ranges
* NUMA modeling seems to be a stronger motivation than the limitation of
256 but
  nubmers, that each NUMA node holds its own PCI(e) sub-hierarchy
* We cannot put ECAM arbitrarily high because guest's PA width is limited
by host's
  when EPT is enabled.
* Compatibility issues in platforms that do not have MCFG table at all
(perhaps we limit
  it to only q35 at present in which MCFG is present).

Based on your discussions, I guess this proposal is still worth doing
overall, but it seems
many restrictions should be imposed to be compatible with some complicated
situations.

Please correct me if I get anything wrong or missing.

Thanks
Zihan


Re: [Qemu-devel] [RFC 0/3] pci_expander_brdige: Put pxb host bridge into separate pci domain

2018-05-22 Thread Zihan Yang
> Maybe we should add a parameter to the pxb-pci device specifying the PCI
domain
> instead of adding it on the fly. It will help ensuring the PCI domain
will not change over
> time due to code changes.In this case "bus sharing" should be off. For
the moment
> the pxb devices get the bus range from the same PCI domain.

That's good advice. I'll do that in v2.

Thanks,
Zihan


Re: [Qemu-devel] [RFC 3/3] acpi-build: allocate mcfg for multiple host bridges

2018-05-22 Thread Zihan Yang
> An interesting point is if we want to limit the MMFCG size for PXBs, as
we may not be
> interested to use all the buses in a specific domain.

OK, perhaps providing an option for the user to specify the desired bus
numbers?

> For each bus we require some address space that remains unused.

Does this mean we should reserve some slots in a bus, or reduce
the number of buses used in each domain?

> [Adding Laszlo for his insights]
> Looking forward to see the SeaBIOS patches :)

I appreciate your reviews, I'll write the rest part as soon as possible.

Thanks


Re: [Qemu-devel] [RFC 2/3] pci: Link pci_host_bridges with QTAILQ

2018-05-22 Thread Zihan Yang
>  have no objection here, we'll see later how the modification helps.

The purpose is to place the q35 host at the start of queue. In the original
QLIST,
when a new pxb host is added, q35 host will be bumped to the end end list.

By replacing it with QTAILQ, we can always get q35 host bridges first, so
that
we can make sure q35 host stays in pci domain 0. If there is no pxb host,
the code needs not change because the 'next' field will be NULL.

I'm not sure whether it is necessary to let q35 host reside in pci domain 0,
but I think I'd better reserve the original when I don't know the potential
impact.

Thanks
Zihan


Re: [Qemu-devel] [RFC 1/3] pci_expander_bridge: reserve enough mcfg space for pxb host

2018-05-21 Thread Zihan Yang
Hi Marcel,

Thanks a lot for your feedback.

> I don't think we should try to place the MMCFGs before 4G even if there
> is enough room. Is better to place them always after 4G.
>
> "above_4g_mem" PCI hole it is reserved for PCI devices hotplug. We cannot
use if for
> MMCFGs. What I think we can do is to "move" the 64 bit PCI hole after the
MMCFGs.
> So the layout of over 4G space will be:
>
> [RAM hotplug][MMCFGs][PCI hotplug]...

OK, I will reorganize the memory layout. Should the number of MMCFG be
limited,
as there might be insufficient memory above 4G?

> Do you need the  number of existing expander hosts? We have a
pxbdev_list, just query it.

Great, I think I missed that list.

> The above will need to change. We move the pci hole, not resize it.
> I am not sure this is the right place to handle it, maybe we add a new
property
> right beside pci_hole ones (extra-mmcfg?) and default it to 0.

That sounds good, so that we just need to check this range when setting
mcfg table instead of traversing the host bridge list.

> You cannot use the MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT as it is in use
> by the "main" root complex MMCFG. Actually I don't think we can come up
> with a valid default.

I see, I'll replcae it with unmapped then.

> Be aware this is used by both pxb and pxb-pcie devices, I think you
should split the type
>for each one and let the pxb's one as before.

OK, I had thought it would make codes simpler, as TYPE_PCIE_HOST_BRIDGE
is also the child of TYPE_PCI_HOST_BRIDGE, but I did forget about the pxb
devices. I'll split it in v2.

Thanks
Zihan


[Qemu-devel] [RFC 3/3] acpi-build: allocate mcfg for multiple host bridges

2018-05-20 Thread Zihan Yang
Currently only q35 host bridge us allocated space in MCFG table. To put pxb host
into sepratate pci domain, each of them should have its own configuration space
int MCFG table

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/i386/acpi-build.c | 83 +++-
 1 file changed, 62 insertions(+), 21 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9bc6d97..808d815 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -89,6 +89,7 @@
 typedef struct AcpiMcfgInfo {
 uint64_t mcfg_base;
 uint32_t mcfg_size;
+struct AcpiMcfgInfo *next;
 } AcpiMcfgInfo;
 
 typedef struct AcpiPmInfo {
@@ -2427,14 +2428,15 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 {
 AcpiTableMcfg *mcfg;
 const char *sig;
-int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
+int len, count = 0;
+AcpiMcfgInfo *cfg = info;
 
+while (cfg) {
+++count;
+cfg = cfg->next;
+}
+len = sizeof(*mcfg) + count * sizeof(mcfg->allocation[0]);
 mcfg = acpi_data_push(table_data, len);
-mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
-/* Only a single allocation so no need to play with segments */
-mcfg->allocation[0].pci_segment = cpu_to_le16(0);
-mcfg->allocation[0].start_bus_number = 0;
-mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
 
 /* MCFG is used for ECAM which can be enabled or disabled by guest.
  * To avoid table size changes (which create migration issues),
@@ -2448,6 +2450,17 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, 
AcpiMcfgInfo *info)
 } else {
 sig = "MCFG";
 }
+
+count = 0;
+while (info) {
+mcfg[count].allocation[0].address = cpu_to_le64(info->mcfg_base);
+/* Only a single allocation so no need to play with segments */
+mcfg[count].allocation[0].pci_segment = cpu_to_le16(count);
+mcfg[count].allocation[0].start_bus_number = 0;
+mcfg[count++].allocation[0].end_bus_number = 
PCIE_MMCFG_BUS(info->mcfg_size - 1);
+info = info->next;
+}
+
 build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
 }
 
@@ -2602,26 +2615,52 @@ struct AcpiBuildState {
 MemoryRegion *linker_mr;
 } AcpiBuildState;
 
-static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
+static inline void cleanup_mcfg(AcpiMcfgInfo *mcfg)
+{
+AcpiMcfgInfo *tmp;
+while (mcfg) {
+tmp = mcfg->next;
+g_free(mcfg);
+mcfg = tmp;
+}
+}
+
+static AcpiMcfgInfo *acpi_get_mcfg(void)
 {
 Object *pci_host;
 QObject *o;
+AcpiMcfgInfo *head = NULL, *tail, *mcfg;
 
 pci_host = acpi_get_i386_pci_host();
 g_assert(pci_host);
 
-o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
-if (!o) {
-return false;
+while (pci_host) {
+mcfg = g_new0(AcpiMcfgInfo, 1);
+mcfg->next = NULL;
+if (!head) {
+tail = head = mcfg;
+} else {
+tail->next = mcfg;
+tail = mcfg;
+}
+
+o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
+if (!o) {
+cleanup_mcfg(head);
+g_free(mcfg);
+return NULL;
+}
+mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
+assert(o);
+mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
+qobject_unref(o);
+
+pci_host = OBJECT(QTAILQ_NEXT(PCI_HOST_BRIDGE(pci_host), next));
 }
-mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
-qobject_unref(o);
-
-o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
-assert(o);
-mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
-qobject_unref(o);
-return true;
+return head;
 }
 
 static
@@ -2633,7 +2672,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 unsigned facs, dsdt, rsdt, fadt;
 AcpiPmInfo pm;
 AcpiMiscInfo misc;
-AcpiMcfgInfo mcfg;
+AcpiMcfgInfo *mcfg;
 Range pci_hole, pci_hole64;
 uint8_t *u;
 size_t aml_len = 0;
@@ -2714,10 +2753,12 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 build_slit(tables_blob, tables->linker);
 }
 }
-if (acpi_get_mcfg()) {
+if ((mcfg = acpi_get_mcfg()) != NULL) {
 acpi_add_table(table_offsets, tables_blob);
-build_mcfg_q35(tables_blob, tables->linker, );
+build_mcfg_q35(tables_blob, tables->linker, mcfg);
 }
+cleanup_mcfg(mcfg);
+
 if (x86_iommu_get_default()) {
 IommuType IOMMUType = x86_iommu_get_type();
 if (IOMMUType == TYPE_AMD) {
-- 
2.7.4




[Qemu-devel] [RFC 0/3] pci_expander_brdige: Put pxb host bridge into separate pci domain

2018-05-20 Thread Zihan Yang
Currently only q35 host bridge is allocated an item in MCFG table, all pxb
host bridges stay within pci domain 0. This series of patches put each pxb
host bridge in separate pci domain, allocating a new MCFG table item for it.

The pxb host does not have an mch in it, as q35 host already has one. All
pxb host bridges just serve as expander bridges in QEMU, which makes them
a little simpler than q35 host bridge.

NOTE: These patches are just initial proof of concept, asking for suggestions.
  The aml part and seabios part are not finished at all. This means it
  still behaves like before, that all pci expander bridges stay in the
  same pci domain as a35 host.

Zihan Yang (3):
  pci_expander_bridge: reserve enough mcfg space for pxb host
  pci: Link pci_host_bridges with QTAILQ
  acpi-build: allocate mcfg for multiple host bridges

 hw/i386/acpi-build.c| 83 ++---
 hw/i386/pc.c|  5 ++
 hw/pci-bridge/pci_expander_bridge.c | 96 -
 hw/pci/pci.c|  9 +--
 include/hw/pci-bridge/pci_expander_bridge.h |  7 +++
 include/hw/pci/pci_host.h   |  2 +-
 6 files changed, 175 insertions(+), 27 deletions(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

-- 
2.7.4




[Qemu-devel] [RFC 2/3] pci: Link pci_host_bridges with QTAILQ

2018-05-20 Thread Zihan Yang
QLIST will place the original q35 host bridge at the end of list because it is
added first. Replace it with QTAILQ to make q35 at the first of queue, which
makes it convinient and compatible when there are pxb hosts other than q35 hosts

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/pci/pci.c  | 9 +
 include/hw/pci/pci_host.h | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 80bc459..ddc27ba 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -196,7 +196,8 @@ static void pci_del_option_rom(PCIDevice *pdev);
 static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
 
-static QLIST_HEAD(, PCIHostState) pci_host_bridges;
+static QTAILQ_HEAD(, PCIHostState) pci_host_bridges =
+QTAILQ_HEAD_INITIALIZER(pci_host_bridges);
 
 int pci_bar(PCIDevice *d, int reg)
 {
@@ -330,7 +331,7 @@ static void pci_host_bus_register(DeviceState *host)
 {
 PCIHostState *host_bridge = PCI_HOST_BRIDGE(host);
 
-QLIST_INSERT_HEAD(_host_bridges, host_bridge, next);
+QTAILQ_INSERT_TAIL(_host_bridges, host_bridge, next);
 }
 
 PCIBus *pci_device_root_bus(const PCIDevice *d)
@@ -1798,7 +1799,7 @@ PciInfoList *qmp_query_pci(Error **errp)
 PciInfoList *info, *head = NULL, *cur_item = NULL;
 PCIHostState *host_bridge;
 
-QLIST_FOREACH(host_bridge, _host_bridges, next) {
+QTAILQ_FOREACH(host_bridge, _host_bridges, next) {
 info = g_malloc0(sizeof(*info));
 info->value = qmp_query_pci_bus(host_bridge->bus,
 pci_bus_num(host_bridge->bus));
@@ -2493,7 +2494,7 @@ int pci_qdev_find_device(const char *id, PCIDevice **pdev)
 PCIHostState *host_bridge;
 int rc = -ENODEV;
 
-QLIST_FOREACH(host_bridge, _host_bridges, next) {
+QTAILQ_FOREACH(host_bridge, _host_bridges, next) {
 int tmp = pci_qdev_find_recursive(host_bridge->bus, id, pdev);
 if (!tmp) {
 rc = 0;
diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h
index ba31595..a5617cf 100644
--- a/include/hw/pci/pci_host.h
+++ b/include/hw/pci/pci_host.h
@@ -47,7 +47,7 @@ struct PCIHostState {
 uint32_t config_reg;
 PCIBus *bus;
 
-QLIST_ENTRY(PCIHostState) next;
+QTAILQ_ENTRY(PCIHostState) next;
 };
 
 typedef struct PCIHostBridgeClass {
-- 
2.7.4




[Qemu-devel] [RFC 1/3] pci_expander_bridge: reserve enough mcfg space for pxb host

2018-05-20 Thread Zihan Yang
To put each pxb into separate pci domain, we need to reserve enough MCFG space
for each pxb host in the main memory. First try to put them under 4G, before
pci_hole_start, if there are too many hosts, try to put them into main memory
above 4G, before pci_hole64_start. We should check if there is enough memory
to reserve for them

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/i386/pc.c|  5 ++
 hw/pci-bridge/pci_expander_bridge.c | 96 -
 include/hw/pci-bridge/pci_expander_bridge.h |  7 +++
 3 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/pci-bridge/pci_expander_bridge.h

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d768930..98097fd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -34,6 +34,7 @@
 #include "hw/ide.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/timer/hpet.h"
 #include "hw/smbios/smbios.h"
@@ -1466,6 +1467,7 @@ uint64_t pc_pci_hole64_start(void)
 PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
 MachineState *ms = MACHINE(pcms);
 uint64_t hole64_start = 0;
+int pxb_hosts;
 
 if (pcmc->has_reserved_memory && ms->device_memory->base) {
 hole64_start = ms->device_memory->base;
@@ -1473,6 +1475,9 @@ uint64_t pc_pci_hole64_start(void)
 hole64_start += memory_region_size(>device_memory->mr);
 }
 } else {
+/* make sure enough space is left for pxb host, otherwise fail */
+pxb_hosts = pxb_get_expander_hosts();
+g_assert (pxb_hosts <= 0 || pcms->above_4g_mem_size >= (pxb_hosts << 
28ULL));
 hole64_start = 0x1ULL + pcms->above_4g_mem_size;
 }
 
diff --git a/hw/pci-bridge/pci_expander_bridge.c 
b/hw/pci-bridge/pci_expander_bridge.c
index e62de42..8409c87 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -12,10 +12,13 @@
 
 #include "qemu/osdep.h"
 #include "qapi/error.h"
+#include "qapi/visitor.h"
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
 #include "hw/pci/pci_bridge.h"
+#include "hw/pci-host/q35.h"
+#include "hw/pci-bridge/pci_expander_bridge.h"
 #include "qemu/range.h"
 #include "qemu/error-report.h"
 #include "sysemu/numa.h"
@@ -57,7 +60,13 @@ static PXBDev *convert_to_pxb(PCIDevice *dev)
 
 static GList *pxb_dev_list;
 
+typedef struct PXBPCIHost {
+PCIExpressHost parent_obj;
+} PXBPCIHost;
+
 #define TYPE_PXB_HOST "pxb-host"
+#define PXB_HOST_DEVICE(obj) \
+ OBJECT_CHECK(PXBPCIHost, (obj), TYPE_PXB_HOST)
 
 static int pxb_bus_num(PCIBus *bus)
 {
@@ -111,6 +120,14 @@ static const char *pxb_host_root_bus_path(PCIHostState 
*host_bridge,
 return bus->bus_path;
 }
 
+static void pxb_host_get_mmcfg_size(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+PCIExpressHost *e = PCIE_HOST_BRIDGE(obj);
+
+visit_type_uint64(v, name, >size, errp);
+}
+
 static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
 {
 const PCIHostState *pxb_host;
@@ -142,6 +159,80 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice 
*dev)
 return NULL;
 }
 
+static Object *pxb_get_i386_pci_host(void)
+{
+PCIHostState *host;
+
+host = OBJECT_CHECK(PCIHostState,
+object_resolve_path("/machine/i440fx", NULL),
+TYPE_PCI_HOST_BRIDGE);
+if (!host) {
+host = OBJECT_CHECK(PCIHostState,
+object_resolve_path("/machine/q35", NULL),
+TYPE_PCI_HOST_BRIDGE);
+}
+
+return OBJECT(host);
+}
+
+int pxhb_cnt = 0;
+
+/* -1 means to exclude q35 host */
+#define MCFG_IN_PCI_HOLE (((IO_APIC_DEFAULT_ADDRESS - 
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT) >> 28) - 1)
+
+int pxb_get_expander_hosts(void)
+{
+return pxhb_cnt - MCFG_IN_PCI_HOLE;
+}
+
+/* Dirty workaround */
+static void modify_q35_pci_hole(void)
+{
+Object *pci_host;
+Q35PCIHost *s;
+
+pci_host = pxb_get_i386_pci_host();
+g_assert(pci_host);
+s = Q35_HOST_DEVICE(pci_host);
+
+++pxhb_cnt;
+if (pxhb_cnt <= MCFG_IN_PCI_HOLE) {
+range_set_bounds(>mch.pci_hole,
+MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + ((1 + pxhb_cnt) << 28),
+IO_APIC_DEFAULT_ADDRESS - 1);
+}
+
+// leave pci hole64 to acpi build part
+}
+
+static void pxb_host_initfn(Object *obj)
+{
+PCIHostState *phb = PCI_HOST_BRIDGE(obj);
+
+memory_region_init_io(>conf_mem, obj, _host_conf_le_ops, phb,
+  "pci-conf-idx", 4)

[Qemu-devel] [PATCH v2] hw/pci-host/q35: Replace hardcoded value with macro

2018-04-25 Thread Zihan Yang
During smram region initialization some addresses are hardcoded,
replace them with macro to be more clear to readers.

Previous patch forgets about one value and exceeds the line
limit of 90 characters. The v2 breaks a few long lines

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/pci-host/q35.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index a36a119..02f9576 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -535,13 +535,15 @@ static void mch_realize(PCIDevice *d, Error **errp)
 
 /* if *disabled* show SMRAM to all CPUs */
 memory_region_init_alias(>smram_region, OBJECT(mch), "smram-region",
- mch->pci_address_space, 0xa, 0x2);
-memory_region_add_subregion_overlap(mch->system_memory, 0xa,
+ mch->pci_address_space, 
MCH_HOST_BRIDGE_SMRAM_C_BASE,
+ MCH_HOST_BRIDGE_SMRAM_C_SIZE);
+memory_region_add_subregion_overlap(mch->system_memory, 
MCH_HOST_BRIDGE_SMRAM_C_BASE,
 >smram_region, 1);
 memory_region_set_enabled(>smram_region, true);
 
 memory_region_init_alias(>open_high_smram, OBJECT(mch), 
"smram-open-high",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE,
+ MCH_HOST_BRIDGE_SMRAM_C_SIZE);
 memory_region_add_subregion_overlap(mch->system_memory, 0xfeda,
 >open_high_smram, 1);
 memory_region_set_enabled(>open_high_smram, false);
@@ -550,11 +552,14 @@ static void mch_realize(PCIDevice *d, Error **errp)
 memory_region_init(>smram, OBJECT(mch), "smram", 1ull << 32);
 memory_region_set_enabled(>smram, true);
 memory_region_init_alias(>low_smram, OBJECT(mch), "smram-low",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE,
+ MCH_HOST_BRIDGE_SMRAM_C_SIZE);
 memory_region_set_enabled(>low_smram, true);
-memory_region_add_subregion(>smram, 0xa, >low_smram);
+memory_region_add_subregion(>smram, MCH_HOST_BRIDGE_SMRAM_C_BASE,
+>low_smram);
 memory_region_init_alias(>high_smram, OBJECT(mch), "smram-high",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE,
+ MCH_HOST_BRIDGE_SMRAM_C_SIZE);
 memory_region_set_enabled(>high_smram, true);
 memory_region_add_subregion(>smram, 0xfeda, >high_smram);
 
-- 
2.7.4




[Qemu-devel] [PATCH] hw/pci-host/q35: Replace hardcoded value with macro

2018-04-25 Thread Zihan Yang
Currently part of mch_realize uses hardcoded value when initializing
smram regions. Use macro to be more clear to code readers

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/pci-host/q35.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index a36a119..49e4be4 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -535,13 +535,13 @@ static void mch_realize(PCIDevice *d, Error **errp)
 
 /* if *disabled* show SMRAM to all CPUs */
 memory_region_init_alias(>smram_region, OBJECT(mch), "smram-region",
- mch->pci_address_space, 0xa, 0x2);
-memory_region_add_subregion_overlap(mch->system_memory, 0xa,
+ mch->pci_address_space, 
MCH_HOST_BRIDGE_SMRAM_C_BASE, MCH_HOST_BRIDGE_SMRAM_C_SIZE);
+memory_region_add_subregion_overlap(mch->system_memory, 
MCH_HOST_BRIDGE_SMRAM_C_BASE,
 >smram_region, 1);
 memory_region_set_enabled(>smram_region, true);
 
 memory_region_init_alias(>open_high_smram, OBJECT(mch), 
"smram-open-high",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE, 
MCH_HOST_BRIDGE_SMRAM_C_SIZE);
 memory_region_add_subregion_overlap(mch->system_memory, 0xfeda,
 >open_high_smram, 1);
 memory_region_set_enabled(>open_high_smram, false);
@@ -550,11 +550,11 @@ static void mch_realize(PCIDevice *d, Error **errp)
 memory_region_init(>smram, OBJECT(mch), "smram", 1ull << 32);
 memory_region_set_enabled(>smram, true);
 memory_region_init_alias(>low_smram, OBJECT(mch), "smram-low",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE, 
0x2);
 memory_region_set_enabled(>low_smram, true);
-memory_region_add_subregion(>smram, 0xa, >low_smram);
+memory_region_add_subregion(>smram, MCH_HOST_BRIDGE_SMRAM_C_BASE, 
>low_smram);
 memory_region_init_alias(>high_smram, OBJECT(mch), "smram-high",
- mch->ram_memory, 0xa, 0x2);
+ mch->ram_memory, MCH_HOST_BRIDGE_SMRAM_C_BASE, 
MCH_HOST_BRIDGE_SMRAM_C_SIZE);
 memory_region_set_enabled(>high_smram, true);
 memory_region_add_subregion(>smram, 0xfeda, >high_smram);
 
-- 
2.7.4




Re: [Qemu-devel] [PATCH 0/2] vmmouse: convert qdev pointer property to QOM link relationship

2018-03-07 Thread Zihan Yang
 Hi Philippe,

Thanks for reviewing my patch. Yes I though about it, a specific header file
with only several lines seems not worth it, but otherwise I would have to
define redundant macro in vmmouse.c. Currently rebundant macro is ok
but if we need some more macros, we would end on creating a specific
header at last, although I'm not sure whether we will really need more
macros in the future.

P.S. I forgot to cc to qemu-devel, so I resend one. I apologize if two
identical
emails look confusing to you.

2018-03-08 4:27 GMT+08:00 Philippe Mathieu-Daudé <f4...@amsat.org>:

> Hi Zihan Yang,
>
> On 03/07/2018 01:55 PM, Zihan Yang wrote:
> >  Hi all, this is a bitesized patch from me a while ago, it seems a little
> > old but I wonder if there is any opinion about it? Is it still valid?
>
> For a single TYPE use, I'm not sure use a specific header is useful
> (patch #1).
> The 2nd patch looks valid to me but I'm not a QOM link expert.
>
> >
> > Thanks.
> >
> > 2018-02-04 15:28 GMT+08:00 Zihan Yang <whois.zihan.y...@gmail.com>:
> >
> >> The ps2_mouse property of vmmouse is still pointer type which
> >> is defined by DEFINE_PROP_PTR. But qdev pointer property should
> >> be avoided according to qdev-properties.h. Convert it to
> >> QOM link relationship.
> >>
> >> It involves two patches because it requires the TYPE_I8042
> >> macro which is defined in another file. The first patch put
> >> this macro into a single header file so that the macro can
> >> be used elsewhere. The second patch does the actual work.
> >>
> >> Zihan Yang (2):
> >>   hw/input/pckdb: put TYPE_I8042 into a single header file
> >>   vmmouse: change qdev pointer property to qom link
> >>
> >>  hw/i386/pc.c  |  2 +-
> >>  hw/i386/vmmouse.c | 19 ---
> >>  hw/input/pckbd.c  |  2 +-
> >>  hw/input/pckbd.h  |  6 ++
> >>  4 files changed, 20 insertions(+), 9 deletions(-)
> >>  create mode 100644 hw/input/pckbd.h
> >>
> >> --
> >> 2.7.4
> >>
> >>
>


Re: [Qemu-devel] [PATCH 0/2] vmmouse: convert qdev pointer property to QOM link relationship

2018-03-07 Thread Zihan Yang
 Hi all, this is a bitesized patch from me a while ago, it seems a little
old but I wonder if there is any opinion about it? Is it still valid?

Thanks.

2018-02-04 15:28 GMT+08:00 Zihan Yang <whois.zihan.y...@gmail.com>:

> The ps2_mouse property of vmmouse is still pointer type which
> is defined by DEFINE_PROP_PTR. But qdev pointer property should
> be avoided according to qdev-properties.h. Convert it to
> QOM link relationship.
>
> It involves two patches because it requires the TYPE_I8042
> macro which is defined in another file. The first patch put
> this macro into a single header file so that the macro can
> be used elsewhere. The second patch does the actual work.
>
> Zihan Yang (2):
>   hw/input/pckdb: put TYPE_I8042 into a single header file
>   vmmouse: change qdev pointer property to qom link
>
>  hw/i386/pc.c  |  2 +-
>  hw/i386/vmmouse.c | 19 ---
>  hw/input/pckbd.c  |  2 +-
>  hw/input/pckbd.h  |  6 ++
>  4 files changed, 20 insertions(+), 9 deletions(-)
>  create mode 100644 hw/input/pckbd.h
>
> --
> 2.7.4
>
>


Re: [Qemu-devel] [PATCH] RAMList: replace QemuMutex with CompatGMutex

2018-02-14 Thread Zihan Yang
> I'm not sure what is the advantage of this change.  QEMU is more or less
> uniformly using QemuMutex and QemuCond.

I see. QEMU uses some glib functions, like g_new, g_free, g_hash_table ,
g_assert and g_poll, so I thought there was a trend for making more use of
glib.
I get the point now.


2018-02-14 18:13 GMT+08:00 Paolo Bonzini <pbonz...@redhat.com>:

> On 14/02/2018 09:49, Zihan Yang wrote:
> > change the mutex member in RAMList structure from QemuMutex to
> CompatGMutex.
> > qemu_mutex_init() is just deleted instead of being replaced with
> g_mutex_init()
> > because there is no need to do initialize a mutex that is statically
> allocated.
> >
> > Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
>
> I'm not sure what is the advantage of this change.  QEMU is more or less
> uniformly using QemuMutex and QemuCond.
>
> Paolo
>
> > ---
> >  exec.c | 5 ++---
> >  include/exec/ramlist.h | 2 +-
> >  2 files changed, 3 insertions(+), 4 deletions(-)
> >
> > diff --git a/exec.c b/exec.c
> > index e8d7b33..90cdd05 100644
> > --- a/exec.c
> > +++ b/exec.c
> > @@ -1423,12 +1423,12 @@ void qemu_flush_coalesced_mmio_buffer(void)
> >
> >  void qemu_mutex_lock_ramlist(void)
> >  {
> > -qemu_mutex_lock(_list.mutex);
> > +g_mutex_lock(_list.mutex);
> >  }
> >
> >  void qemu_mutex_unlock_ramlist(void)
> >  {
> > -qemu_mutex_unlock(_list.mutex);
> > +g_mutex_unlock(_list.mutex);
> >  }
> >
> >  void ram_block_dump(Monitor *mon)
> > @@ -3331,7 +3331,6 @@ void cpu_register_map_client(QEMUBH *bh)
> >
> >  void cpu_exec_init_all(void)
> >  {
> > -qemu_mutex_init(_list.mutex);
> >  /* The data structures we set up here depend on knowing the page
> size,
> >   * so no more changes can be made after this point.
> >   * In an ideal world, nothing we did before we had finished the
> > diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
> > index 2e2ac6c..24be5e4 100644
> > --- a/include/exec/ramlist.h
> > +++ b/include/exec/ramlist.h
> > @@ -45,7 +45,7 @@ typedef struct {
> >  } DirtyMemoryBlocks;
> >
> >  typedef struct RAMList {
> > -QemuMutex mutex;
> > +CompatGMutex mutex;
> >  RAMBlock *mru_block;
> >  /* RCU-enabled, writes protected by the ramlist lock. */
> >  QLIST_HEAD(, RAMBlock) blocks;
> >
>
>


[Qemu-devel] [PATCH] RAMList: replace QemuMutex with CompatGMutex

2018-02-14 Thread Zihan Yang
change the mutex member in RAMList structure from QemuMutex to CompatGMutex.
qemu_mutex_init() is just deleted instead of being replaced with g_mutex_init()
because there is no need to do initialize a mutex that is statically allocated.

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 exec.c | 5 ++---
 include/exec/ramlist.h | 2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/exec.c b/exec.c
index e8d7b33..90cdd05 100644
--- a/exec.c
+++ b/exec.c
@@ -1423,12 +1423,12 @@ void qemu_flush_coalesced_mmio_buffer(void)
 
 void qemu_mutex_lock_ramlist(void)
 {
-qemu_mutex_lock(_list.mutex);
+g_mutex_lock(_list.mutex);
 }
 
 void qemu_mutex_unlock_ramlist(void)
 {
-qemu_mutex_unlock(_list.mutex);
+g_mutex_unlock(_list.mutex);
 }
 
 void ram_block_dump(Monitor *mon)
@@ -3331,7 +3331,6 @@ void cpu_register_map_client(QEMUBH *bh)
 
 void cpu_exec_init_all(void)
 {
-qemu_mutex_init(_list.mutex);
 /* The data structures we set up here depend on knowing the page size,
  * so no more changes can be made after this point.
  * In an ideal world, nothing we did before we had finished the
diff --git a/include/exec/ramlist.h b/include/exec/ramlist.h
index 2e2ac6c..24be5e4 100644
--- a/include/exec/ramlist.h
+++ b/include/exec/ramlist.h
@@ -45,7 +45,7 @@ typedef struct {
 } DirtyMemoryBlocks;
 
 typedef struct RAMList {
-QemuMutex mutex;
+CompatGMutex mutex;
 RAMBlock *mru_block;
 /* RCU-enabled, writes protected by the ramlist lock. */
 QLIST_HEAD(, RAMBlock) blocks;
-- 
2.7.4




[Qemu-devel] [PATCH 2/2] vmmouse: change qdev pointer property to qom link

2018-02-03 Thread Zihan Yang
The ps2_mouse property of vmmouse is still pointer type which
is defined by DEFINE_PROP_PTR. But qdev pointer property should
be avoided. Convert it into QOM link relationship

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/i386/pc.c  |  2 +-
 hw/i386/vmmouse.c | 19 ---
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ccc50ba..63f49b2 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1598,7 +1598,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 }
 if (vmmouse) {
 DeviceState *dev = DEVICE(vmmouse);
-qdev_prop_set_ptr(dev, "ps2_mouse", i8042);
+object_property_set_link(OBJECT(dev), OBJECT(i8042), "ps2_mouse", 
NULL);
 qdev_init_nofail(dev);
 }
 port92 = isa_create_simple(isa_bus, "port92");
diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c
index 65ef553..49d4170 100644
--- a/hw/i386/vmmouse.c
+++ b/hw/i386/vmmouse.c
@@ -26,6 +26,8 @@
 #include "ui/console.h"
 #include "hw/i386/pc.h"
 #include "hw/qdev.h"
+#include "hw/input/pckbd.h"
+#include "qapi/error.h"
 
 /* debug only vmmouse */
 //#define DEBUG_VMMOUSE
@@ -271,10 +273,15 @@ static void vmmouse_realizefn(DeviceState *dev, Error 
**errp)
 vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
 }
 
-static Property vmmouse_properties[] = {
-DEFINE_PROP_PTR("ps2_mouse", VMMouseState, ps2_mouse),
-DEFINE_PROP_END_OF_LIST(),
-};
+static void vmmouse_initfn(Object *obj)
+{
+VMMouseState *s = VMMOUSE(obj);
+
+object_property_add_link(obj, "ps2_mouse", TYPE_I8042,
+ (Object **)>ps2_mouse,
+ qdev_prop_allow_set_link_before_realize,
+ 0, _abort);
+}
 
 static void vmmouse_class_initfn(ObjectClass *klass, void *data)
 {
@@ -283,15 +290,13 @@ static void vmmouse_class_initfn(ObjectClass *klass, void 
*data)
 dc->realize = vmmouse_realizefn;
 dc->reset = vmmouse_reset;
 dc->vmsd = _vmmouse;
-dc->props = vmmouse_properties;
-/* Reason: pointer property "ps2_mouse" */
-dc->user_creatable = false;
 }
 
 static const TypeInfo vmmouse_info = {
 .name  = TYPE_VMMOUSE,
 .parent= TYPE_ISA_DEVICE,
 .instance_size = sizeof(VMMouseState),
+.instance_init = vmmouse_initfn,
 .class_init= vmmouse_class_initfn,
 };
 
-- 
2.7.4




[Qemu-devel] [PATCH 1/2] hw/input/pckdb: put TYPE_I8042 into a single header file

2018-02-03 Thread Zihan Yang
This allows the macro to be used elsewhere, for example,
when adding link property to vmmouse object.

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 hw/input/pckbd.c | 2 +-
 hw/input/pckbd.h | 6 ++
 2 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 hw/input/pckbd.h

diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index c479f82..d517938 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -27,6 +27,7 @@
 #include "hw/i386/pc.h"
 #include "hw/input/ps2.h"
 #include "sysemu/sysemu.h"
+#include "pckbd.h"
 
 /* debug PC keyboard */
 //#define DEBUG_KBD
@@ -480,7 +481,6 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
 qemu_register_reset(kbd_reset, s);
 }
 
-#define TYPE_I8042 "i8042"
 #define I8042(obj) OBJECT_CHECK(ISAKBDState, (obj), TYPE_I8042)
 
 typedef struct ISAKBDState {
diff --git a/hw/input/pckbd.h b/hw/input/pckbd.h
new file mode 100644
index 000..9cacd0a
--- /dev/null
+++ b/hw/input/pckbd.h
@@ -0,0 +1,6 @@
+#ifndef QEMU_PCKCD_H
+#define QEMU_PCKCD_H
+
+#define TYPE_I8042 "i8042"
+
+#endif
-- 
2.7.4




[Qemu-devel] [PATCH 0/2] vmmouse: convert qdev pointer property to QOM link relationship

2018-02-03 Thread Zihan Yang
The ps2_mouse property of vmmouse is still pointer type which
is defined by DEFINE_PROP_PTR. But qdev pointer property should
be avoided according to qdev-properties.h. Convert it to 
QOM link relationship.

It involves two patches because it requires the TYPE_I8042
macro which is defined in another file. The first patch put
this macro into a single header file so that the macro can
be used elsewhere. The second patch does the actual work.

Zihan Yang (2):
  hw/input/pckdb: put TYPE_I8042 into a single header file
  vmmouse: change qdev pointer property to qom link

 hw/i386/pc.c  |  2 +-
 hw/i386/vmmouse.c | 19 ---
 hw/input/pckbd.c  |  2 +-
 hw/input/pckbd.h  |  6 ++
 4 files changed, 20 insertions(+), 9 deletions(-)
 create mode 100644 hw/input/pckbd.h

-- 
2.7.4




[Qemu-devel] [PATCH] net/socket: change net_socket_listen_init to use qemu-socket functions

2018-02-01 Thread Zihan Yang
net_socket_listen_init directly uses parse_host_port, bind and listen,
change it to use functions in include/qemu/sockets.h

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 net/socket.c | 30 +-
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 6917fbc..e4b1f47 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -494,36 +494,24 @@ static int net_socket_listen_init(NetClientState *peer,
 {
 NetClientState *nc;
 NetSocketState *s;
-struct sockaddr_in saddr;
-int fd, ret;
+SocketAddress *saddr;
+Error *local_err = NULL;
+int fd;
 
-if (parse_host_port(, host_str, errp) < 0) {
+saddr = socket_parse(host_str, _err);
+if (NULL != local_err) {
+error_setg_errno(errp, errno, "socket_parse failed");
 return -1;
 }
 
-fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+fd = socket_listen(saddr, errp);
 if (fd < 0) {
-error_setg_errno(errp, errno, "can't create stream socket");
+error_setg_errno(errp, errno, "can't listen on address");
+qapi_free_SocketAddress(saddr);
 return -1;
 }
 qemu_set_nonblock(fd);
 
-socket_set_fast_reuse(fd);
-
-ret = bind(fd, (struct sockaddr *), sizeof(saddr));
-if (ret < 0) {
-error_setg_errno(errp, errno, "can't bind ip=%s to socket",
- inet_ntoa(saddr.sin_addr));
-closesocket(fd);
-return -1;
-}
-ret = listen(fd, 0);
-if (ret < 0) {
-error_setg_errno(errp, errno, "can't listen on socket");
-closesocket(fd);
-return -1;
-}
-
 nc = qemu_new_net_client(_socket_info, peer, model, name);
 s = DO_UPCAST(NetSocketState, nc, nc);
 s->fd = -1;
-- 
2.7.4




[Qemu-devel] Fwd: [RFC 2/4] qemu-socket: Allow custom socket options in socket_connect

2018-01-31 Thread Zihan Yang
Hi, Daniel

>You've added all this extra functionality to pass arbitrary
>options, but then not used it in any of the later patches.
>We've been trying to remove complexity from this code, so
>I'm not in favour of adding new functionality that is not
>even used.

You are right, unused functionality should not be added. I was thinking
about future usage, but that seems really unnecessary now.

>I'm not seeing the point of adding the support for the O_NONBLOCK
>in the listener socket either - that can easily be turned on after
>you have the listener socket created.

I don't quite understand how I can turn it on in socket_listen, because
socket_listen will create a listener socket inside it, then bind and listen.
Are there other ways than passing some kind of 'config parameter'?

>The O_NONBLOCK functionality makes more sense in this context
>but the implementation is really broken.

Well.. sorry for the broken implementation, I guess I need more practice.

>These functions do hostname lookups, so can never do non-blocking
>mode correctly as the hostname lookup itself does blocking I/O
>to the nameserver(s).  Ignoring that, the way you handle the
>connect() is wrong too. You're iterating over many addresses
>returned by getaddrinfo() and doing a non-blocking connect
>on each of them. These will essentially all fail with EAGAIN
>and you'll skip onto the next address which is wrong.

Why would the hostname lookup affect the listener socket
afterwards? The socket is created after the lookup procedure is done.
Therefore, the config should only affect the listener socket, not the
hostname lookup process. Would you explain in more detail? I'm not
an expert in socket programming, so I'm confused.

Also, connect() indeed could return EAGAIN, however, the continue
expression is inside the do-while loop of inet_connect_addr(),
rather than the for loop inside inet_connect_saddr(), which is the
caller of inet_connect_addr(). So it would just try to connect again
instead of skipping to next address.

I know this is not a well-written patch, but if you forget about the broken
implementation for a while, it actually won't fail them all. I did a little
test
by connecting two VMs through socket, and they can ping each other.
The docker test fails because I missed the NULL pointer check for sconf,
which I ignored in the ping test above, but it is irrelevant to the problem
here. After I fix it, the test passes.

>This code used to have support for O_NONBLOCK but it was removed
>because the DNS problem means that any code relying on it was
>already broken.  The rest of the QEMU codebase has been converted
>to use QIOChannelSocket instead which can handle non-blocking
>DNS properly

I didn't know this, thanks for clarifying it. Do you mean if I want to use
non-blocking socket, it's better to use QIOChannelSocket instead of
socket_listen/socket_connect? If I want to set some other
options, do I have to use the bind/listen/connect series functions
directly? That seems the way in some functions in net/socket.c.

Anyway, thanks for your comment, it helps clarify things. I had
intended to get start with this task, but it seems to have already been
fully explored before. I guess I need to review my patches throughly,

Regards
Zihan


[Qemu-devel] [RFC 2/4] qemu-socket: Allow custom socket options in socket_connect

2018-01-29 Thread Zihan Yang
Currently, socket_connect doesn't allow custom socket options,
which is inconvenient when the caller wants a different kind of
socket from that the socket_connect provides. This patch allows
custom config in socket_connect by providing an extra parameter.
Existing functions can just pass a NULL pointer.

Note the caller who wants a non-blocking socket should always
check the errno after socket_connect returns to see if the
connection is really established or still inprogress.

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 block/sheepdog.c   |  2 +-
 block/ssh.c|  2 +-
 include/qemu/sockets.h |  5 +--
 io/channel-socket.c|  2 +-
 util/qemu-sockets.c| 82 --
 5 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/block/sheepdog.c b/block/sheepdog.c
index f684477..f96e091 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -591,7 +591,7 @@ static int connect_to_sdog(BDRVSheepdogState *s, Error 
**errp)
 {
 int fd;
 
-fd = socket_connect(s->addr, errp);
+fd = socket_connect(s->addr, errp, NULL);
 
 if (s->addr->type == SOCKET_ADDRESS_TYPE_INET && fd >= 0) {
 int ret = socket_set_nodelay(fd);
diff --git a/block/ssh.c b/block/ssh.c
index b049a16..c9d00c8 100644
--- a/block/ssh.c
+++ b/block/ssh.c
@@ -678,7 +678,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
 }
 
 /* Open the socket and connect. */
-s->sock = inet_connect_saddr(s->inet, errp);
+s->sock = inet_connect_saddr(s->inet, errp, NULL);
 if (s->sock < 0) {
 ret = -EIO;
 goto err;
diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index ab06943..13d6716 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -46,7 +46,8 @@ int inet_ai_family_from_address(InetSocketAddress *addr,
 Error **errp);
 int inet_parse(InetSocketAddress *addr, const char *str, Error **errp);
 int inet_connect(const char *str, Error **errp);
-int inet_connect_saddr(InetSocketAddress *saddr, Error **errp);
+int inet_connect_saddr(InetSocketAddress *saddr, Error **errp,
+   QemuSocketConfig *sconf);
 
 NetworkAddressFamily inet_netfamily(int family);
 
@@ -54,7 +55,7 @@ int unix_listen(const char *path, Error **errp);
 int unix_connect(const char *path, Error **errp);
 
 SocketAddress *socket_parse(const char *str, Error **errp);
-int socket_connect(SocketAddress *addr, Error **errp);
+int socket_connect(SocketAddress *addr, Error **errp, QemuSocketConfig *sconf);
 int socket_listen(SocketAddress *addr, Error **errp, QemuSocketConfig *sconf);
 void socket_listen_cleanup(int fd, Error **errp);
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 9942cf0..f010a8e 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -140,7 +140,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
 int fd;
 
 trace_qio_channel_socket_connect_sync(ioc, addr);
-fd = socket_connect(addr, errp);
+fd = socket_connect(addr, errp, NULL);
 if (fd < 0) {
 trace_qio_channel_socket_connect_fail(ioc);
 return -1;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index b171f23..3a10206 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -372,9 +372,11 @@ listen_ok:
 ((rc) == -EINPROGRESS)
 #endif
 
-static int inet_connect_addr(struct addrinfo *addr, Error **errp);
+static int inet_connect_addr(struct addrinfo *addr, Error **errp,
+ QemuSocketConfig *sconf);
 
-static int inet_connect_addr(struct addrinfo *addr, Error **errp)
+static int inet_connect_addr(struct addrinfo *addr, Error **errp,
+ QemuSocketConfig *sconf)
 {
 int sock, rc;
 
@@ -385,12 +387,26 @@ static int inet_connect_addr(struct addrinfo *addr, Error 
**errp)
 }
 socket_set_fast_reuse(sock);
 
+if(parse_socket_options(sock, errp, sconf) < 0) {
+error_setg_errno(errp, errno, "Failed to set socket options");
+return -1;
+}
+
 /* connect to peer */
 do {
 rc = 0;
 if (connect(sock, addr->ai_addr, addr->ai_addrlen) < 0) {
 rc = -errno;
 }
+/* More judge for nonblocking socket, borrowed from 
net_socket_connect_init */
+if(sconf->nonblocking) {
+if(rc == -EWOULDBLOCK)
+continue;
+else if(rc == -EINPROGRESS ||
+rc == -EALREADY ||
+rc == -EINVAL)
+return sock; /* caller needs tp judge errno */
+}
 } while (rc == -EINTR);
 
 if (rc < 0) {
@@ -459,7 +475,8 @@ static struct addrinfo 
*inet_parse_connect_saddr(InetSocketAddress *saddr,
  *
  * Returns: -1 on error, file descriptor on success.
  */
-int inet

[Qemu-devel] [RFC 3/4] net/socket: change net_socket_listen_init to use functions in include/qemu/sockets.h

2018-01-29 Thread Zihan Yang
Some functions in net/socket.c still uses bind/connect/listen
directly. Change it to use functions in include/qemu/sockets.h

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 net/socket.c | 41 +
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 6917fbc..7b07223 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -494,35 +494,35 @@ static int net_socket_listen_init(NetClientState *peer,
 {
 NetClientState *nc;
 NetSocketState *s;
-struct sockaddr_in saddr;
-int fd, ret;
+SocketAddress *saddr;
+QemuSocketConfig *sconf;
+Error *local_err = NULL;
+int fd;
 
-if (parse_host_port(, host_str, errp) < 0) {
+saddr = socket_parse(host_str, _err);
+if(NULL != local_err) {
+error_setg_errno(errp, errno, "socket_parse failed");
 return -1;
 }
 
-fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
-if (fd < 0) {
-error_setg_errno(errp, errno, "can't create stream socket");
+/* Manually prepare config because socket_listen
++ * will not set O_NONBLOCKING */
+sconf = g_new0(QemuSocketConfig, 1);
+if(NULL == sconf) {
+qapi_free_SocketAddress(saddr);
+error_setg_errno(errp, errno, "out of memory");
 return -1;
 }
-qemu_set_nonblock(fd);
+sconf->nonblocking = true;
+sconf->options = NULL;
 
-socket_set_fast_reuse(fd);
-
-ret = bind(fd, (struct sockaddr *), sizeof(saddr));
-if (ret < 0) {
-error_setg_errno(errp, errno, "can't bind ip=%s to socket",
- inet_ntoa(saddr.sin_addr));
-closesocket(fd);
-return -1;
-}
-ret = listen(fd, 0);
-if (ret < 0) {
-error_setg_errno(errp, errno, "can't listen on socket");
-closesocket(fd);
+fd = socket_listen(saddr, errp, sconf);
+if(fd < 0) {
+error_setg_errno(errp, errno, "can't listen on address");
+qapi_free_SocketAddress(saddr);
 return -1;
 }
+g_free(sconf);
 
 nc = qemu_new_net_client(_socket_info, peer, model, name);
 s = DO_UPCAST(NetSocketState, nc, nc);
@@ -532,6 +532,7 @@ static int net_socket_listen_init(NetClientState *peer,
 net_socket_rs_init(>rs, net_socket_rs_finalize, false);
 
 qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s);
+qapi_free_SocketAddress(saddr);
 return 0;
 }
 
-- 
2.7.4




[Qemu-devel] [RFC 1/4] qemu-socket: Allow custom socket option in socket_listen

2018-01-29 Thread Zihan Yang
Currently, socket_listen does not allow caller to set custom
socket options, which is inconvenient when the caller wants
a non-blocking socket or wants to set TCP_NODELAY. Therefore,
two new structs are added and an extra parameter is provided
to socket_listen. Existing functions are unaffected by
providing a NULL pointer.

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 include/qemu/sockets.h | 17 +++-
 io/channel-socket.c|  2 +-
 qga/channel-posix.c|  2 +-
 util/qemu-sockets.c| 74 ++
 4 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h
index 8889bcb..ab06943 100644
--- a/include/qemu/sockets.h
+++ b/include/qemu/sockets.h
@@ -11,6 +11,21 @@ int inet_aton(const char *cp, struct in_addr *ia);
 
 #include "qapi-types.h"
 
+struct QemuSocketOption {
+int level;
+int optname;
+void *optval;
+socklen_t optlen;
+struct QemuSocketOption *next;
+};
+typedef struct QemuSocketOption QemuSocketOption;
+
+struct QemuSocketConfig {
+bool nonblocking;
+QemuSocketOption *options;
+};
+typedef struct QemuSocketConfig QemuSocketConfig;
+
 /* misc helpers */
 int qemu_socket(int domain, int type, int protocol);
 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
@@ -40,7 +55,7 @@ int unix_connect(const char *path, Error **errp);
 
 SocketAddress *socket_parse(const char *str, Error **errp);
 int socket_connect(SocketAddress *addr, Error **errp);
-int socket_listen(SocketAddress *addr, Error **errp);
+int socket_listen(SocketAddress *addr, Error **errp, QemuSocketConfig *sconf);
 void socket_listen_cleanup(int fd, Error **errp);
 int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
 
diff --git a/io/channel-socket.c b/io/channel-socket.c
index 563e297..9942cf0 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -198,7 +198,7 @@ int qio_channel_socket_listen_sync(QIOChannelSocket *ioc,
 int fd;
 
 trace_qio_channel_socket_listen_sync(ioc, addr);
-fd = socket_listen(addr, errp);
+fd = socket_listen(addr, errp, NULL);
 if (fd < 0) {
 trace_qio_channel_socket_listen_fail(ioc);
 return -1;
diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index b812bf4..16c8524 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -215,7 +215,7 @@ static gboolean ga_channel_open(GAChannel *c, const gchar 
*path,
 return false;
 }
 
-fd = socket_listen(addr, _err);
+fd = socket_listen(addr, _err, NULL);
 qapi_free_SocketAddress(addr);
 if (local_err != NULL) {
 g_critical("%s", error_get_pretty(local_err));
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index d6a1e17..b171f23 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -43,7 +43,6 @@
 # define AI_NUMERICSERV 0
 #endif
 
-
 static int inet_getport(struct addrinfo *e)
 {
 struct sockaddr_in *i4;
@@ -196,9 +195,40 @@ static int try_bind(int socket, InetSocketAddress *saddr, 
struct addrinfo *e)
 #endif
 }
 
+static int parse_socket_options(int fd,
+Error **errp,
+QemuSocketConfig *sconf)
+{
+QemuSocketOption *sopt;
+
+if(!sconf) {
+/* No extra socket options are defined */
+return fd;
+}
+
+if(sconf->nonblocking) {
+qemu_set_nonblock(fd);
+} 
+
+for(sopt = sconf->options; sopt; sopt = sopt->next) {
+if(sopt->level < IPPROTO_IP || sopt->optname < SO_DEBUG || 
+  !sopt->optval || sopt->optlen <= 0) {
+error_setg(errp, "Invalid socket option:\n"
+ "level=%d, optname=%d, optval=%p, optlen=%d\n",
+sopt->level, sopt->optname, sopt->optval, sopt->optlen);
+return -1;
+}
+qemu_setsockopt(fd, sopt->level, sopt->optname, 
+sopt->optval, sopt->optlen);
+}
+
+return fd;
+}
+
 static int inet_listen_saddr(InetSocketAddress *saddr,
  int port_offset,
- Error **errp)
+ Error **errp,
+ QemuSocketConfig *sconf)
 {
 struct addrinfo ai,*res,*e;
 char port[33];
@@ -287,6 +317,11 @@ static int inet_listen_saddr(InetSocketAddress *saddr,
 }
 socket_created = true;
 
+if(parse_socket_options(slisten, errp, sconf) < 0) {
+error_setg_errno(errp, errno, "Failed to set socket options");
+goto listen_failed;
+}
+
 rc = try_bind(slisten, saddr, e);
 if (rc < 0) {
 if (errno != EADDRINUSE) {
@@ -701,7 +736,8 @@ static int vsoc

[Qemu-devel] [RFC 0/4] Allow custom socket option in socket_listen and socket_connect

2018-01-29 Thread Zihan Yang
socket_listen and socket_connect do not allow custom socket option.
This would be inconvenient if the caller wants a non-blocking socket,
or wants to set TCP_NODELAY or other options.

This series of patches add specific config structures, QemuSocketConfig,
which contains QemuSocketOption. All the QemuSocketOption are formed
as a linked list.

The caller is reponsible for setting up the config structure. Passing
an NULL pointer would use the original socket_listen/socket_connect,
so existing functions are not affected.

Note that the caller needs to check errno after socket_connect when
using a non-blocking socket. It does not have to in other cases.

Zihan Yang (4):
  qemu-socket: Allow custom socket option in socket_listen
  qemu-socket: Allow custom socket options in socket_connect
  net/socket: change net_socket_listen_init to use functions in
include/qemu/sockets.h
  net/socket: change net_socket_connect_init to use functions in
sockets.h

 block/sheepdog.c   |   2 +-
 block/ssh.c|   2 +-
 include/qemu/sockets.h |  22 ++-
 io/channel-socket.c|   4 +-
 net/socket.c   |  93 ++---
 qga/channel-posix.c|   2 +-
 util/qemu-sockets.c| 156 -
 7 files changed, 197 insertions(+), 84 deletions(-)

-- 
2.7.4




[Qemu-devel] [RFC 4/4] net/socket: change net_socket_connect_init to use functions in sockets.h

2018-01-29 Thread Zihan Yang
net_socket_connect_init still uses parse_host_port() and connect()
directly. Convert it into functions in include/qemu/sockets.h

Signed-off-by: Zihan Yang <whois.zihan.y...@gmail.com>
---
 net/socket.c | 52 +++-
 1 file changed, 23 insertions(+), 29 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 7b07223..312b638 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -543,48 +543,42 @@ static int net_socket_connect_init(NetClientState *peer,
Error **errp)
 {
 NetSocketState *s;
-int fd, connected, ret;
-struct sockaddr_in saddr;
+int fd, connected;
+SocketAddress *saddr;
+QemuSocketConfig *sconf;
+Error *local_err = NULL;
 
-if (parse_host_port(, host_str, errp) < 0) {
+saddr = socket_parse(host_str, _err);
+if(NULL != local_err) {
+error_setg_errno(errp, errno, "socket_parse failed");
 return -1;
 }
 
-fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
-if (fd < 0) {
-error_setg_errno(errp, errno, "can't create stream socket");
-return -1;
-}
-qemu_set_nonblock(fd);
+sconf = g_new0(QemuSocketConfig, 1);
+sconf->nonblocking = true;
+sconf->options = NULL;
 
 connected = 0;
-for(;;) {
-ret = connect(fd, (struct sockaddr *), sizeof(saddr));
-if (ret < 0) {
-if (errno == EINTR || errno == EWOULDBLOCK) {
-/* continue */
-} else if (errno == EINPROGRESS ||
-   errno == EALREADY ||
-   errno == EINVAL) {
-break;
-} else {
-error_setg_errno(errp, errno, "can't connect socket");
-closesocket(fd);
-return -1;
-}
-} else {
-connected = 1;
-break;
-}
+fd = socket_connect(saddr, errp, sconf);
+if(fd < 0) {
+error_setg_errno(errp, errno, "socket_connect failed");
+g_free(sconf);
+qapi_free_SocketAddress(saddr);
+return -1;
+} else if(errno != EINPROGRESS && errno != EALREADY && errno != EINVAL) {
+connected = 1;
 }
+g_free(sconf);
+
 s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp);
 if (!s) {
 return -1;
 }
 
 snprintf(s->nc.info_str, sizeof(s->nc.info_str),
- "socket: connect to %s:%d",
- inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
+ "socket: connect to %s:%s",
+ saddr->u.inet.host, saddr->u.inet.port);
+qapi_free_SocketAddress(saddr);
 return 0;
 }
 
-- 
2.7.4




[Qemu-devel] [PATCH 3/3] hw/s390: replace exit with unrealize during class init of virtio-ccw

2017-04-28 Thread Zihan Yang
Currently the virtio_ccw_device_class_init function sets dc->exit, which is
the exit callback of DeviceClass. It should be converted to dc->unrealize
since exit callback of DeviceClass will be removed in the future.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/s390x/virtio-ccw.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 91b43ac..5c193a8 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1621,13 +1621,12 @@ static void virtio_ccw_busdev_realize(DeviceState *dev, 
Error **errp)
 virtio_ccw_device_realize(_dev, errp);
 }
 
-static int virtio_ccw_busdev_exit(DeviceState *dev)
+static void virtio_ccw_busdev_unrealize(DeviceState *dev, Error **errp)
 {
 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
 _info->exit(_dev);
-return 0;
 }
 
 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
@@ -1645,7 +1644,7 @@ static void virtio_ccw_device_class_init(ObjectClass 
*klass, void *data)
 
 k->unplug = virtio_ccw_busdev_unplug;
 dc->realize = virtio_ccw_busdev_realize;
-dc->exit = virtio_ccw_busdev_exit;
+dc->unrealize = virtio_ccw_busdev_unrealize;
 dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
 }
 
-- 
2.7.4




[Qemu-devel] [PATCH 2/3] hw/s390x: make virtio_ccw_exit function in virtio-ccw return void

2017-04-28 Thread Zihan Yang
Only virtio_ccw_exit and the exit callback in VirtIOCCWDeviceClass are
converted to void in this patch. 'virtio_ccw_busdev_exit' belongs to
DeviceClass so it still returns int, DeviceClass::exit will return
void in future patches.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/s390x/virtio-ccw.c | 6 +++---
 hw/s390x/virtio-ccw.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e7167e3..91b43ac 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -731,7 +731,7 @@ out_err:
 g_free(sch);
 }
 
-static int virtio_ccw_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_exit(VirtioCcwDevice *dev)
 {
 CcwDevice *ccw_dev = CCW_DEVICE(dev);
 SubchDev *sch = ccw_dev->sch;
@@ -744,7 +744,6 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
 release_indicator(>routes.adapter, dev->indicators);
 dev->indicators = NULL;
 }
-return 0;
 }
 
 static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
@@ -1627,7 +1626,8 @@ static int virtio_ccw_busdev_exit(DeviceState *dev)
 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
-return _info->exit(_dev);
+_info->exit(_dev);
+return 0;
 }
 
 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 41d4010..ce8baa3 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -74,7 +74,7 @@ typedef struct VirtioCcwDevice VirtioCcwDevice;
 typedef struct VirtIOCCWDeviceClass {
 CCWDeviceClass parent_class;
 void (*realize)(VirtioCcwDevice *dev, Error **errp);
-int (*exit)(VirtioCcwDevice *dev);
+void (*exit)(VirtioCcwDevice *dev);
 } VirtIOCCWDeviceClass;
 
 /* Performance improves when virtqueue kick processing is decoupled from the
-- 
2.7.4




[Qemu-devel] [PATCH 1/3] hw/char/sclp*: remove console_exit function in sclp

2017-04-28 Thread Zihan Yang
Currently the console_exit function in sclpconsole-lm.c and sclpconsole.c
does nothing, so remove them and convert the callback in SCLPEventClass to
void. Since there is a NULL check on the DeviceClass exit callback, it
should be ok to simply remove them.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/char/sclpconsole-lm.c  | 6 --
 hw/char/sclpconsole.c | 6 --
 hw/s390x/event-facility.c | 6 +-
 include/hw/s390x/event-facility.h | 2 +-
 4 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 07d6ebd..86ddda6 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -318,11 +318,6 @@ static int console_init(SCLPEvent *event)
 return 0;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static void console_reset(DeviceState *dev)
 {
SCLPEvent *event = SCLP_EVENT(dev);
@@ -349,7 +344,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclplmconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index b78f240..e916cac 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -246,11 +246,6 @@ static void console_reset(DeviceState *dev)
scon->notify = false;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static Property console_properties[] = {
 DEFINE_PROP_CHR("chardev", SCLPConsole, chr),
 DEFINE_PROP_END_OF_LIST(),
@@ -265,7 +260,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclpconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 34b2faf..f7c509c 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -413,11 +413,7 @@ static void event_unrealize(DeviceState *qdev, Error 
**errp)
 SCLPEvent *event = SCLP_EVENT(qdev);
 SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
 if (child->exit) {
-int rc = child->exit(event);
-if (rc < 0) {
-error_setg(errp, "SCLP event exit failed.");
-return;
-}
+child->exit(event);
 }
 }
 
diff --git a/include/hw/s390x/event-facility.h 
b/include/hw/s390x/event-facility.h
index def1bb0..1a32f3a 100644
--- a/include/hw/s390x/event-facility.h
+++ b/include/hw/s390x/event-facility.h
@@ -162,7 +162,7 @@ typedef struct SCLPEvent {
 typedef struct SCLPEventClass {
 DeviceClass parent_class;
 int (*init)(SCLPEvent *event);
-int (*exit)(SCLPEvent *event);
+void (*exit)(SCLPEvent *event);
 
 /* get SCLP's send mask */
 unsigned int (*get_send_mask)(void);
-- 
2.7.4




[Qemu-devel] [PATCH 0/3] hw: make *_exit return void/convert to unrealize in sclp/virtio-ccw

2017-04-28 Thread Zihan Yang
These first patch remove the console_exit function in sclp since it 
actually does nothing, the callback return type in SCLPEventClass is
changed to void. The second patch convert return type of *_exit function
 of virtio-ccw to void. The third patch replace the exit callback with
unrealize in the class init function of virtio-ccw, because the exit 
callback of DeviceClass will be removed in the future.

Zihan Yang (3):
  hw/char/sclp*: remove console_exit function in sclp
  hw/s390x: make virtio_ccw_exit function in virtio-ccw return void
  hw/s390: replace exit with unrealize during class init of virtio-ccw

 hw/char/sclpconsole-lm.c  | 6 --
 hw/char/sclpconsole.c | 6 --
 hw/s390x/event-facility.c | 6 +-
 hw/s390x/virtio-ccw.c | 9 -
 hw/s390x/virtio-ccw.h | 2 +-
 include/hw/s390x/event-facility.h | 2 +-
 6 files changed, 7 insertions(+), 24 deletions(-)

-- 
2.7.4




Re: [Qemu-devel] [PATCH 1/5] hw/char: remove console_exit function in sclp

2017-04-27 Thread Zihan Yang
OK, sorry for the confusion, I will give a new patch series. I'm not very
familiar with
the conventions so I wonder if someone could help clarify some principles
for me.
I'd like to replace all the init/exit callback of DeviceClass to
realize/unrealize,  and
convert return type of exit callback of some higher-level classes, like
HDACodecDeviceClass, to void.

My first question Is it a good idea to split these patches into two series?
For example,
one series to convert exit callback of these higher-level classes to void,
and then the
other to replace all the init/exit callback of DeviceClass to
realize/unrealize.

The second question is that should I always give separate patch for
different directories?
One  example is that in both hw/ide and hw/block, I need to replace the
init callback with
realize in some high-level classes, should I give two patches or just give
one patch for
the work?

Thanks


[Qemu-devel] [PATCH 2/5] hw/s390x: make virtio_ccw_exit function in virtio-ccw return void

2017-04-26 Thread Zihan Yang
Only virtio_ccw_exit and the callback in VirtIOCCWDeviceClass are
converted to void in this patch. 'virtio_ccw_busdev_exit' belongs to
DeviceClass so it still returns int at present, DeviceClass::exit
will return void in another patch.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/s390x/virtio-ccw.c | 6 +++---
 hw/s390x/virtio-ccw.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e7167e3..91b43ac 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -731,7 +731,7 @@ out_err:
 g_free(sch);
 }
 
-static int virtio_ccw_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_exit(VirtioCcwDevice *dev)
 {
 CcwDevice *ccw_dev = CCW_DEVICE(dev);
 SubchDev *sch = ccw_dev->sch;
@@ -744,7 +744,6 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
 release_indicator(>routes.adapter, dev->indicators);
 dev->indicators = NULL;
 }
-return 0;
 }
 
 static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
@@ -1627,7 +1626,8 @@ static int virtio_ccw_busdev_exit(DeviceState *dev)
 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
-return _info->exit(_dev);
+_info->exit(_dev);
+return 0;
 }
 
 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 41d4010..ce8baa3 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -74,7 +74,7 @@ typedef struct VirtioCcwDevice VirtioCcwDevice;
 typedef struct VirtIOCCWDeviceClass {
 CCWDeviceClass parent_class;
 void (*realize)(VirtioCcwDevice *dev, Error **errp);
-int (*exit)(VirtioCcwDevice *dev);
+void (*exit)(VirtioCcwDevice *dev);
 } VirtIOCCWDeviceClass;
 
 /* Performance improves when virtqueue kick processing is decoupled from the
-- 
2.7.4




[Qemu-devel] [PATCH 4/5] hw/audio: replace exit with unrealize in hda_codec_device_class_init

2017-04-26 Thread Zihan Yang
The exit callback of DeviceClass will be removed in the future, so
convert to unrealize in the init functioin

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/audio/intel-hda.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 537face..2c497eb 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -70,7 +70,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error 
**errp)
 }
 }
 
-static int hda_codec_dev_exit(DeviceState *qdev)
+static void hda_codec_dev_unrealize(DeviceState *qdev, Error **errp)
 {
 HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
 HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
@@ -78,7 +78,6 @@ static int hda_codec_dev_exit(DeviceState *qdev)
 if (cdc->exit) {
 cdc->exit(dev);
 }
-return 0;
 }
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
@@ -1318,7 +1317,7 @@ static void hda_codec_device_class_init(ObjectClass 
*klass, void *data)
 {
 DeviceClass *k = DEVICE_CLASS(klass);
 k->realize = hda_codec_dev_realize;
-k->exit = hda_codec_dev_exit;
+k->unrealize = hda_codec_dev_unrealize;
 set_bit(DEVICE_CATEGORY_SOUND, k->categories);
 k->bus_type = TYPE_HDA_BUS;
 k->props = hda_props;
-- 
2.7.4




[Qemu-devel] [PATCH 3/5] hw/s390: convert exit to unrealize in virtio_ccw_device_class_init

2017-04-26 Thread Zihan Yang
Currently the virtio_ccw_device_class_init function sets dc->exit, the
exit callback of DeviceClass. It should be converted to dc->unrealize
since exit callback of DeviceClass will be removed in the future.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/s390x/virtio-ccw.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 91b43ac..5c193a8 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1621,13 +1621,12 @@ static void virtio_ccw_busdev_realize(DeviceState *dev, 
Error **errp)
 virtio_ccw_device_realize(_dev, errp);
 }
 
-static int virtio_ccw_busdev_exit(DeviceState *dev)
+static void virtio_ccw_busdev_unrealize(DeviceState *dev, Error **errp)
 {
 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
 _info->exit(_dev);
-return 0;
 }
 
 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
@@ -1645,7 +1644,7 @@ static void virtio_ccw_device_class_init(ObjectClass 
*klass, void *data)
 
 k->unplug = virtio_ccw_busdev_unplug;
 dc->realize = virtio_ccw_busdev_realize;
-dc->exit = virtio_ccw_busdev_exit;
+dc->unrealize = virtio_ccw_busdev_unrealize;
 dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
 }
 
-- 
2.7.4




[Qemu-devel] [PATCH 5/5] hw/audio: convert exit callback in HDACodecDeviceClass to void

2017-04-26 Thread Zihan Yang
The exit callback always return 0, convert it to void

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/audio/hda-codec.c | 3 +--
 hw/audio/intel-hda.h | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index 52d4640..5402cd1 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -520,7 +520,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct 
desc_codec *desc)
 return 0;
 }
 
-static int hda_audio_exit(HDACodecDevice *hda)
+static void hda_audio_exit(HDACodecDevice *hda)
 {
 HDAAudioState *a = HDA_AUDIO(hda);
 HDAAudioStream *st;
@@ -539,7 +539,6 @@ static int hda_audio_exit(HDACodecDevice *hda)
 }
 }
 AUD_remove_card(>card);
-return 0;
 }
 
 static int hda_audio_post_load(void *opaque, int version)
diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h
index d784bcf..53b78da 100644
--- a/hw/audio/intel-hda.h
+++ b/hw/audio/intel-hda.h
@@ -38,7 +38,7 @@ typedef struct HDACodecDeviceClass
 DeviceClass parent_class;
 
 int (*init)(HDACodecDevice *dev);
-int (*exit)(HDACodecDevice *dev);
+void (*exit)(HDACodecDevice *dev);
 void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
 void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool 
output);
 } HDACodecDeviceClass;
-- 
2.7.4




[Qemu-devel] [PATCH 1/5] hw/char: remove console_exit function in sclp

2017-04-26 Thread Zihan Yang
Currently, the console_exit function in sclpconsole-lm.c and sclpconsole.c
does nothing, so remove them and convert the callback in SCLPEventClass to
void. Since there is a NULL check on the DeviceClass exit callback as
suggested by Frederic Konrad, it should be safe to remove them.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/char/sclpconsole-lm.c  | 6 --
 hw/char/sclpconsole.c | 6 --
 hw/s390x/event-facility.c | 6 +-
 include/hw/s390x/event-facility.h | 2 +-
 4 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 07d6ebd..86ddda6 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -318,11 +318,6 @@ static int console_init(SCLPEvent *event)
 return 0;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static void console_reset(DeviceState *dev)
 {
SCLPEvent *event = SCLP_EVENT(dev);
@@ -349,7 +344,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclplmconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index b78f240..e916cac 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -246,11 +246,6 @@ static void console_reset(DeviceState *dev)
scon->notify = false;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static Property console_properties[] = {
 DEFINE_PROP_CHR("chardev", SCLPConsole, chr),
 DEFINE_PROP_END_OF_LIST(),
@@ -265,7 +260,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclpconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 34b2faf..f7c509c 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -413,11 +413,7 @@ static void event_unrealize(DeviceState *qdev, Error 
**errp)
 SCLPEvent *event = SCLP_EVENT(qdev);
 SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
 if (child->exit) {
-int rc = child->exit(event);
-if (rc < 0) {
-error_setg(errp, "SCLP event exit failed.");
-return;
-}
+child->exit(event);
 }
 }
 
diff --git a/include/hw/s390x/event-facility.h 
b/include/hw/s390x/event-facility.h
index def1bb0..1a32f3a 100644
--- a/include/hw/s390x/event-facility.h
+++ b/include/hw/s390x/event-facility.h
@@ -162,7 +162,7 @@ typedef struct SCLPEvent {
 typedef struct SCLPEventClass {
 DeviceClass parent_class;
 int (*init)(SCLPEvent *event);
-int (*exit)(SCLPEvent *event);
+void (*exit)(SCLPEvent *event);
 
 /* get SCLP's send mask */
 unsigned int (*get_send_mask)(void);
-- 
2.7.4




Re: [Qemu-devel] [PATCH] hw: make *_exit functions return void

2017-04-20 Thread Zihan Yang
(I forgot to reply all in last email, so I resend the reply again)
I have resubmitted two split-out patches in https://lists.nongnu.org/
archive/html/qemu-devel/2017-04/msg03096.html, which change the exit
funtion of sclp and virtio-ccw. But the exit function of DeviceClass still
returns int after the patch because it involves other folders like hw/audio,
and as suggested by Markus Armbruster, the exit function of DeviceClass
should be converted to unrealize(), so I just leave `virtio_ccw_busdev_exit`
at present because it is an exit function of DeviceClass.


2017-04-19 0:15 GMT+08:00 Cornelia Huck <cornelia.h...@de.ibm.com>:

> On Sun, 16 Apr 2017 20:26:01 +0800
> Zihan Yang <tgny...@gmail.com> wrote:
>
> > According to the second suggestion listed on Dead code Removal
> > of BiteSizedTasks, I modify some *_exit functions to make them
> > return void. Some *_exit and *_exitfn functions that already
> > return void remain unchanged. Also, the checks for the callers
> > are deleted.
> >
> > Signed-off-by: Zihan Yang <tgny...@gmail.com>
> > ---
> >  hw/audio/hda-codec.c  | 3 +--
> >  hw/audio/intel-hda.c  | 3 +--
> >  hw/audio/intel-hda.h  | 2 +-
> >  hw/char/sclpconsole-lm.c  | 3 +--
> >  hw/char/sclpconsole.c | 3 +--
> >  hw/core/qdev.c| 6 +-
> >  hw/s390x/event-facility.c | 6 +-
> >  hw/s390x/virtio-ccw.c | 7 +++
> >  hw/s390x/virtio-ccw.h | 2 +-
> >  hw/usb/dev-smartcard-reader.c | 3 +--
> >  include/hw/qdev-core.h| 2 +-
> >  include/hw/s390x/event-facility.h | 2 +-
> >  12 files changed, 14 insertions(+), 28 deletions(-)
>
> Hm, I wondered why I had a deja vu... ah, here:
> https://marc.info/?t=14900329128=1=2
>
> The author of that patch did not follow up AFAICS, but some of the
> suggestions made in that thread apply to your patch as well.
>
> In particular:
>
>
> > diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
> > index 07d6ebd..6fa8922 100644
> > --- a/hw/char/sclpconsole-lm.c
> > +++ b/hw/char/sclpconsole-lm.c
> > @@ -318,9 +318,8 @@ static int console_init(SCLPEvent *event)
> >  return 0;
> >  }
> >
> > -static int console_exit(SCLPEvent *event)
> > +static void console_exit(SCLPEvent *event)
> >  {
> > -return 0;
> >  }
> >
> >  static void console_reset(DeviceState *dev)
> > diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
> > index b78f240..d9bbc5e 100644
> > --- a/hw/char/sclpconsole.c
> > +++ b/hw/char/sclpconsole.c
> > @@ -246,9 +246,8 @@ static void console_reset(DeviceState *dev)
> > scon->notify = false;
> >  }
> >
> > -static int console_exit(SCLPEvent *event)
> > +static void console_exit(SCLPEvent *event)
> >  {
> > -return 0;
> >  }
>
> These two now empty functions are not very useful; it is better to
> simply remove them.
>
> With that change, I'd take a split-out patch for sclp and virtio-ccw
> through my tree, or I'd ack a not-split-out version.
>
>


[Qemu-devel] [PATCH 2/2] hw/s390x: make virtio_ccw_exit function in virtio-ccw return void

2017-04-19 Thread Zihan Yang
Note that only the virtio_ccw_exit, which is the exit function
of VirtIOCCWDeviceClass, is modified to return void in this patch.
'virtio_ccw_busdev_exit' belongs to DeviceClass so it remains
unchanged for the moment to give a split-out patch, because
modifying it would involve some other folders like hw/audio.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/s390x/event-facility.c | 6 +-
 hw/s390x/virtio-ccw.c | 6 +++---
 hw/s390x/virtio-ccw.h | 2 +-
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 34b2faf..f7c509c 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -413,11 +413,7 @@ static void event_unrealize(DeviceState *qdev, Error 
**errp)
 SCLPEvent *event = SCLP_EVENT(qdev);
 SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
 if (child->exit) {
-int rc = child->exit(event);
-if (rc < 0) {
-error_setg(errp, "SCLP event exit failed.");
-return;
-}
+child->exit(event);
 }
 }
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 00b3bde..0dbd3ee 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -722,7 +722,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, 
Error **errp)
 }
 }
 
-static int virtio_ccw_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_exit(VirtioCcwDevice *dev)
 {
 CcwDevice *ccw_dev = CCW_DEVICE(dev);
 SubchDev *sch = ccw_dev->sch;
@@ -735,7 +735,6 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
 release_indicator(>routes.adapter, dev->indicators);
 dev->indicators = NULL;
 }
-return 0;
 }
 
 static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
@@ -1621,7 +1620,8 @@ static int virtio_ccw_busdev_exit(DeviceState *dev)
 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
 VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
 
-return _info->exit(_dev);
+_info->exit(_dev);
+return 0; /* TODO workaround, should remove once converted to unrealize */
 }
 
 static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 41d4010..ce8baa3 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -74,7 +74,7 @@ typedef struct VirtioCcwDevice VirtioCcwDevice;
 typedef struct VirtIOCCWDeviceClass {
 CCWDeviceClass parent_class;
 void (*realize)(VirtioCcwDevice *dev, Error **errp);
-int (*exit)(VirtioCcwDevice *dev);
+void (*exit)(VirtioCcwDevice *dev);
 } VirtIOCCWDeviceClass;
 
 /* Performance improves when virtqueue kick processing is decoupled from the
-- 
2.7.4




[Qemu-devel] [PATCH 1/2] hw/char: remove console_exit function in sclp

2017-04-19 Thread Zihan Yang
Currently, the console_exit function in sclpconsole-lm.c and
sclpconsole.c does nothing, just remove them. Since there is
a NULL check on the DeviceClass exit callback as suggested by
Frederic Konrad, it should be safe to simply remove them.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/char/sclpconsole-lm.c  | 6 --
 hw/char/sclpconsole.c | 6 --
 include/hw/s390x/event-facility.h | 2 +-
 3 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 07d6ebd..86ddda6 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -318,11 +318,6 @@ static int console_init(SCLPEvent *event)
 return 0;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static void console_reset(DeviceState *dev)
 {
SCLPEvent *event = SCLP_EVENT(dev);
@@ -349,7 +344,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclplmconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index b78f240..e916cac 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -246,11 +246,6 @@ static void console_reset(DeviceState *dev)
scon->notify = false;
 }
 
-static int console_exit(SCLPEvent *event)
-{
-return 0;
-}
-
 static Property console_properties[] = {
 DEFINE_PROP_CHR("chardev", SCLPConsole, chr),
 DEFINE_PROP_END_OF_LIST(),
@@ -265,7 +260,6 @@ static void console_class_init(ObjectClass *klass, void 
*data)
 dc->reset = console_reset;
 dc->vmsd = _sclpconsole;
 ec->init = console_init;
-ec->exit = console_exit;
 ec->get_send_mask = send_mask;
 ec->get_receive_mask = receive_mask;
 ec->can_handle_event = can_handle_event;
diff --git a/include/hw/s390x/event-facility.h 
b/include/hw/s390x/event-facility.h
index def1bb0..1a32f3a 100644
--- a/include/hw/s390x/event-facility.h
+++ b/include/hw/s390x/event-facility.h
@@ -162,7 +162,7 @@ typedef struct SCLPEvent {
 typedef struct SCLPEventClass {
 DeviceClass parent_class;
 int (*init)(SCLPEvent *event);
-int (*exit)(SCLPEvent *event);
+void (*exit)(SCLPEvent *event);
 
 /* get SCLP's send mask */
 unsigned int (*get_send_mask)(void);
-- 
2.7.4




[Qemu-devel] [PATCH] hw: make *_exit functions return void

2017-04-16 Thread Zihan Yang
According to the second suggestion listed on Dead code Removal
of BiteSizedTasks, I modify some *_exit functions to make them
return void. Some *_exit and *_exitfn functions that already
return void remain unchanged. Also, the checks for the callers
are deleted.

Signed-off-by: Zihan Yang <tgny...@gmail.com>
---
 hw/audio/hda-codec.c  | 3 +--
 hw/audio/intel-hda.c  | 3 +--
 hw/audio/intel-hda.h  | 2 +-
 hw/char/sclpconsole-lm.c  | 3 +--
 hw/char/sclpconsole.c | 3 +--
 hw/core/qdev.c| 6 +-
 hw/s390x/event-facility.c | 6 +-
 hw/s390x/virtio-ccw.c | 7 +++
 hw/s390x/virtio-ccw.h | 2 +-
 hw/usb/dev-smartcard-reader.c | 3 +--
 include/hw/qdev-core.h| 2 +-
 include/hw/s390x/event-facility.h | 2 +-
 12 files changed, 14 insertions(+), 28 deletions(-)

diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
index 52d4640..5402cd1 100644
--- a/hw/audio/hda-codec.c
+++ b/hw/audio/hda-codec.c
@@ -520,7 +520,7 @@ static int hda_audio_init(HDACodecDevice *hda, const struct 
desc_codec *desc)
 return 0;
 }
 
-static int hda_audio_exit(HDACodecDevice *hda)
+static void hda_audio_exit(HDACodecDevice *hda)
 {
 HDAAudioState *a = HDA_AUDIO(hda);
 HDAAudioStream *st;
@@ -539,7 +539,6 @@ static int hda_audio_exit(HDACodecDevice *hda)
 }
 }
 AUD_remove_card(>card);
-return 0;
 }
 
 static int hda_audio_post_load(void *opaque, int version)
diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c
index 537face..991c704 100644
--- a/hw/audio/intel-hda.c
+++ b/hw/audio/intel-hda.c
@@ -70,7 +70,7 @@ static void hda_codec_dev_realize(DeviceState *qdev, Error 
**errp)
 }
 }
 
-static int hda_codec_dev_exit(DeviceState *qdev)
+static void hda_codec_dev_exit(DeviceState *qdev)
 {
 HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
 HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
@@ -78,7 +78,6 @@ static int hda_codec_dev_exit(DeviceState *qdev)
 if (cdc->exit) {
 cdc->exit(dev);
 }
-return 0;
 }
 
 HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
diff --git a/hw/audio/intel-hda.h b/hw/audio/intel-hda.h
index d784bcf..53b78da 100644
--- a/hw/audio/intel-hda.h
+++ b/hw/audio/intel-hda.h
@@ -38,7 +38,7 @@ typedef struct HDACodecDeviceClass
 DeviceClass parent_class;
 
 int (*init)(HDACodecDevice *dev);
-int (*exit)(HDACodecDevice *dev);
+void (*exit)(HDACodecDevice *dev);
 void (*command)(HDACodecDevice *dev, uint32_t nid, uint32_t data);
 void (*stream)(HDACodecDevice *dev, uint32_t stnr, bool running, bool 
output);
 } HDACodecDeviceClass;
diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c
index 07d6ebd..6fa8922 100644
--- a/hw/char/sclpconsole-lm.c
+++ b/hw/char/sclpconsole-lm.c
@@ -318,9 +318,8 @@ static int console_init(SCLPEvent *event)
 return 0;
 }
 
-static int console_exit(SCLPEvent *event)
+static void console_exit(SCLPEvent *event)
 {
-return 0;
 }
 
 static void console_reset(DeviceState *dev)
diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c
index b78f240..d9bbc5e 100644
--- a/hw/char/sclpconsole.c
+++ b/hw/char/sclpconsole.c
@@ -246,9 +246,8 @@ static void console_reset(DeviceState *dev)
scon->notify = false;
 }
 
-static int console_exit(SCLPEvent *event)
+static void console_exit(SCLPEvent *event)
 {
-return 0;
 }
 
 static Property console_properties[] = {
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 1e7fb33..5415843 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -238,11 +238,7 @@ static void device_unrealize(DeviceState *dev, Error 
**errp)
 DeviceClass *dc = DEVICE_GET_CLASS(dev);
 
 if (dc->exit) {
-int rc = dc->exit(dev);
-if (rc < 0) {
-error_setg(errp, "Device exit failed.");
-return;
-}
+dc->exit(dev);
 }
 }
 
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 34b2faf..f7c509c 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -413,11 +413,7 @@ static void event_unrealize(DeviceState *qdev, Error 
**errp)
 SCLPEvent *event = SCLP_EVENT(qdev);
 SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
 if (child->exit) {
-int rc = child->exit(event);
-if (rc < 0) {
-error_setg(errp, "SCLP event exit failed.");
-return;
-}
+child->exit(event);
 }
 }
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 00b3bde..d1c4ff6 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -722,7 +722,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, 
Error **errp)
 }
 }
 
-static int virtio_ccw_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_exit(VirtioCcwDevice *dev)
 {
 CcwDevice *ccw_dev = CCW_DEVICE(dev);
 SubchDev *sch