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",
> > + 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 

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

2018-06-20 Thread Marcel Apfelbaum




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.

+} 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 TypeInfo pxb_host_info = {

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

2018-06-19 Thread Marcel Apfelbaum




On 06/13/2018 11:23 AM, 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.


The max_bus property is optional, you set the default to 255.
I am wondering if 255 is too much as a default for an extra bus,
I would use a smaller value, like 10.


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.


Agreed, please remove sep_domain property.

Thanks,



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.





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 Michael S. Tsirkin
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.

-- 
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.



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

2018-06-12 Thread Michael S. Tsirkin
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.

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

> ---
>  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 =