@@ -32,8 +32,8 @@ int chsc_sei_nt2_get_event(void *res)
PciCcdfErr *eccdf;
int rc = 1;
SeiContainer *sei_cont;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return rc;
@@ -72,8 +72,8 @@ int chsc_sei_nt2_get_event(void *res)
int chsc_sei_nt2_have_event(void)
{
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return 0;
@@ -82,20 +82,31 @@ int chsc_sei_nt2_have_event(void)
return !QTAILQ_EMPTY(&s->pending_sei);
}
+void s390_pci_device_enable(S390PCIBusDevice *zpci)
+{
+ zpci->fh = zpci->fh | 1 << ENABLE_BIT_OFFSET;
+}
+
+void s390_pci_device_disable(S390PCIBusDevice *zpci)
+{
+ zpci->fh = zpci->fh & ~(1 << ENABLE_BIT_OFFSET);
+ if (zpci->is_unplugged) {
+ object_unparent(OBJECT(zpci));
+ }
+}
+
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
{
S390PCIBusDevice *pbdev;
- int i;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
- if ((pbdev->fh != 0) && (pbdev->fid == fid)) {
+ QTAILQ_FOREACH(pbdev, &s->zpci_list, next) {
+ if (pbdev->fid == fid) {
return pbdev;
}
}
@@ -126,39 +137,24 @@ void s390_pci_sclp_configure(int configure, SCCB *sccb)
return;
}
-static uint32_t s390_pci_get_pfid(PCIDevice *pdev)
-{
- return PCI_SLOT(pdev->devfn);
-}
-
-static uint32_t s390_pci_get_pfh(PCIDevice *pdev)
-{
- return PCI_SLOT(pdev->devfn) | FH_VIRT;
-}
-
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
{
S390PCIBusDevice *pbdev;
- int i;
- int j = 0;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ int i = 0;
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
-
- if (pbdev->fh == 0) {
- continue;
- }
-
- if (j == idx) {
+ QTAILQ_FOREACH(pbdev, &s->zpci_list, next) {
+ if (i == idx) {
return pbdev;
}
- j++;
+ if (pbdev->configured) {
+ i++;
+ }
}
return NULL;
@@ -167,16 +163,14 @@ S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
{
S390PCIBusDevice *pbdev;
- int i;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s || !fh) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
+ QTAILQ_FOREACH(pbdev, &s->zpci_list, next) {
if (pbdev->fh == fh) {
return pbdev;
}
@@ -189,8 +183,8 @@ static void s390_pci_generate_event(uint8_t cc, uint16_t pec, uint32_t fh,
uint32_t fid, uint64_t faddr, uint32_t e)
{
SeiContainer *sei_cont;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
+ S390PCIFacility *s = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
if (!s) {
return;
@@ -308,7 +302,10 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
{
uint64_t pte;
uint32_t flags;
- S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, mr);
+ S390PCIDeviceConn *conn = container_of(iommu, S390PCIDeviceConn,
+ iommu_mr);
+ S390PCIBusDevice *pbdev = conn->zpci;
+
S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)
->qbus.parent);
IOMMUTLBEntry ret = {
@@ -319,8 +316,14 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
.perm = IOMMU_NONE,
};
+ if (!pbdev) {
+ return ret;
+ }
+
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
+ s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent);
+
/* s390 does not have an APIC mapped to main storage so we use
* a separate AddressSpace only for msix notifications
*/
@@ -382,7 +385,7 @@ static AddressSpace *s390_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
S390pciState *s = opaque;
- return &s->pbdev[PCI_SLOT(devfn)].as;
+ return &s->conn[PCI_SLOT(devfn)].iommu_as;
}
static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
@@ -455,9 +458,10 @@ static void s390_pcihost_init_as(S390pciState *s)
int i;
for (i = 0; i < PCI_SLOT_MAX; i++) {
- memory_region_init_iommu(&s->pbdev[i].mr, OBJECT(s),
+ memory_region_init_iommu(&s->conn[i].iommu_mr, OBJECT(s),
&s390_iommu_ops, "iommu-s390", UINT64_MAX);
- address_space_init(&s->pbdev[i].as, &s->pbdev[i].mr, "iommu-pci");
+ address_space_init(&s->conn[i].iommu_as, &s->conn[i].iommu_mr,
+ "iommu-pci");
}
memory_region_init_io(&s->msix_notify_mr, OBJECT(s),
@@ -484,7 +488,7 @@ static int s390_pcihost_init(SysBusDevice *dev)
bus = BUS(b);
qbus_set_hotplug_handler(bus, DEVICE(dev), NULL);
phb->bus = b;
- QTAILQ_INIT(&s->pending_sei);
+
return 0;
}
@@ -519,25 +523,35 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- PCIDevice *pci_dev = PCI_DEVICE(dev);
- S390PCIBusDevice *pbdev;
- S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev)
- ->qbus.parent);
+ PCIDevice *pdev = PCI_DEVICE(dev);
+ S390PCIBusDevice *zpci;
+ S390pciState *s;
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
- pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)];
+ QTAILQ_FOREACH(zpci, &f->zpci_list, next) {
+ if (!strcmp(zpci->pci_id, pdev->qdev.id)) {
+ break;
+ }
+ }
- pbdev->fid = s390_pci_get_pfid(pci_dev);
- pbdev->pdev = pci_dev;
- pbdev->configured = true;
- pbdev->fh = s390_pci_get_pfh(pci_dev);
+ if (!zpci) {
+ error_setg(errp, "zpci device %s not found", pdev->qdev.id);
+ return;
+ }
- s390_pcihost_setup_msix(pbdev);
+ s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pdev)->qbus.parent);
+ s->conn[PCI_SLOT(pdev->devfn)].zpci = zpci;
+ zpci->configured = true;
+ zpci->pdev = pdev;
+ zpci->fh = zpci->fid | FH_VIRT;
+ s390_pcihost_setup_msix(zpci);
if (dev->hotplugged) {
s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY,
- pbdev->fh, pbdev->fid);
+ zpci->fh, zpci->fid);
s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED,
- pbdev->fh, pbdev->fid);
+ zpci->fh, zpci->fid);
}
return;
}
@@ -546,31 +560,35 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCIDevice *pci_dev = PCI_DEVICE(dev);
- S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev)
- ->qbus.parent);
- S390PCIBusDevice *pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)];
+ S390PCIBusDevice *pbdev;
+ HotplugHandler *hotplug_ctrl;
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_GET_CLASS(f);
+ HotplugHandlerClass *hdc = HOTPLUG_HANDLER_CLASS(k);
+
+ /* unplug corresponding zpci device */
+ QTAILQ_FOREACH(pbdev, &f->zpci_list, next) {
+ if (!strcmp(pbdev->pci_id, pci_dev->qdev.id)) {
+ break;
+ }
+ }
- if (pbdev->configured) {
- pbdev->configured = false;
- s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
- pbdev->fh, pbdev->fid);
+ if (pbdev) {
+ hotplug_ctrl = pbdev->qdev.parent_bus->hotplug_handler;
+ if (hdc->unplug_request) {
+ hdc->unplug_request(hotplug_ctrl, &pbdev->qdev, errp);
+ }
}
- s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
- pbdev->fh, pbdev->fid);
- pbdev->fh = 0;
- pbdev->fid = 0;
- pbdev->pdev = NULL;
object_unparent(OBJECT(pci_dev));
}
static void s390_pcihost_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- DeviceClass *dc = DEVICE_CLASS(klass);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
- dc->cannot_instantiate_with_device_add_yet = true;
k->init = s390_pcihost_init;
hc->plug = s390_pcihost_hot_plug;
hc->unplug = s390_pcihost_hot_unplug;
@@ -588,9 +606,172 @@ static const TypeInfo s390_pcihost_info = {
}
};
+static void s390_pci_device_hot_plug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
+ S390PCIBusDevice *tmp;
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
+
+ QTAILQ_FOREACH(tmp, &f->zpci_list, next) {
+ /* for now, we use fid to sort the list, need to use uid instead
+ * when uid is ready.
+ */
+ if (tmp->fid > zpci->fid) {
+ break;
+ }
+ }
+
+ if (tmp) {
+ QTAILQ_INSERT_BEFORE(tmp, zpci, next);
+ } else {
+ QTAILQ_INSERT_TAIL(&f->zpci_list, zpci, next);
+ }
+ f->token_valid = false;
+}
+
+static void s390_pci_device_hot_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ int ret;
+ PCIDevice *pdev;
+ S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
+
+ ret = pci_qdev_find_device(zpci->pci_id, &pdev);
+ if (!ret) {
+ object_unparent(OBJECT(pdev));
+ }
+
+ zpci->is_unplugged = true;
+ f->token_valid = false;
+ if (zpci->configured) {
+ zpci->configured = false;
+ s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES,
+ zpci->fh, zpci->fid);
+ }
+
+ s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
+ zpci->fh, zpci->fid);
+}
+
+static const TypeInfo s390_pci_fac_bus_info = {
+ .name = TYPE_S390_PCI_FAC_BUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(S390PCIFacBus),
+};
+
+static int s390_pci_facility_init(SysBusDevice *dev)
+{
+ S390PCIFacility *f = S390_PCI_FACILITY(dev);
+ DeviceState *s = DEVICE(f);
+
+ QTAILQ_INIT(&f->zpci_list);
+ QTAILQ_INIT(&f->pending_sei);
+ msi_supported = true;
+ f->token_valid = true;
+ f->fbus = S390_PCI_FAC_BUS(qbus_create(TYPE_S390_PCI_FAC_BUS, s, NULL));
+ qbus_set_hotplug_handler(BUS(&f->fbus->qbus), DEVICE(s), NULL);
+
+ return 0;
+}
+
+static void s390_pci_facility_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(k);
+
+ k->init = s390_pci_facility_init;
+ hc->plug = s390_pci_device_hot_plug;
+ hc->unplug_request = s390_pci_device_hot_unplug_request;
+}
+
+static const TypeInfo s390_pci_facility_info = {
+ .name = TYPE_S390_PCI_FACILITY,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(S390PCIFacility),
+ .class_init = s390_pci_facility_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
+};
+
+static void s390_pci_device_realize(DeviceState *dev, Error **errp)
+{
+ S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
+ S390PCIBusDevice *tmp;
+ PCIDevice *pdev;
+ int ret;
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
+
+ ret = pci_qdev_find_device(zpci->pci_id, &pdev);
+ if (!ret) {
+ error_setg(errp, "there is already vfio pci device %s", zpci->pci_id);
+ return;
+ }
+
+ QTAILQ_FOREACH(tmp, &f->zpci_list, next) {
+ if (tmp->fid == zpci->fid || tmp->uid == zpci->uid ||
+ !strcmp(tmp->pci_id, zpci->pci_id)) {
+ error_setg(errp, "zpci needs unique fid, uid and pci_id");
+ return;
+ }
+ }
+}
+
+static void s390_pci_device_unrealize(DeviceState *dev, Error **errp)
+{
+ S390pciState *s;
+ S390PCIBusDevice *zpci = S390_PCI_DEVICE(dev);
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
+
+ if (zpci->pdev) {
+ s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(zpci->pdev)->qbus.parent);
+ s->conn[PCI_SLOT(zpci->pdev->devfn)].zpci = NULL;
+ }
+ QTAILQ_REMOVE(&f->zpci_list, zpci, next);
+ zpci->fh = 0;
+ zpci->fid = 0;
+ zpci->pdev = NULL;
+}
+
+static Property s390_pci_device_properties[] = {
+ DEFINE_PROP_UINT32("fid", S390PCIBusDevice, fid, 0),
+ DEFINE_PROP_UINT32("uid", S390PCIBusDevice, uid, 0),
+ DEFINE_PROP_STRING("pci_id", S390PCIBusDevice, pci_id),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void s390_pci_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "s390 pci device";
+ dc->bus_type = TYPE_S390_PCI_FAC_BUS;
+ dc->realize = s390_pci_device_realize;
+ dc->unrealize = s390_pci_device_unrealize;
+ dc->props = s390_pci_device_properties;
+}
+
+static const TypeInfo s390_pci_device_type_info = {
+ .name = TYPE_S390_PCI_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(S390PCIBusDevice),
+ .class_init = s390_pci_device_class_init,
+};
+
static void s390_pci_register_types(void)
{
+
type_register_static(&s390_pcihost_info);
+ type_register_static(&s390_pci_facility_info);
+ type_register_static(&s390_pci_fac_bus_info);
+ type_register_static(&s390_pci_device_type_info);
}
type_init(s390_pci_register_types)
@@ -149,6 +149,17 @@ enum ZpciIoatDtype {
#define ZPCI_TABLE_VALID_MASK 0x20
#define ZPCI_TABLE_PROT_MASK 0x200
+#define TYPE_S390_PCI_FACILITY "s390-pci-facility"
+#define TYPE_S390_PCI_FAC_BUS "s390-pci-fac-bus"
+#define TYPE_S390_PCI_DEVICE "zpci"
+
+#define S390_PCI_FACILITY(obj) \
+ OBJECT_CHECK(S390PCIFacility, (obj), TYPE_S390_PCI_FACILITY)
+#define S390_PCI_FAC_BUS(obj) \
+ OBJECT_CHECK(S390PCIFacBus, (obj), TYPE_S390_PCI_FAC_BUS)
+#define S390_PCI_DEVICE(obj) \
+ OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
+
typedef struct SeiContainer {
QTAILQ_ENTRY(SeiContainer) link;
uint32_t fid;
@@ -214,12 +225,16 @@ typedef struct S390MsixInfo {
} S390MsixInfo;
typedef struct S390PCIBusDevice {
+ DeviceState qdev;
PCIDevice *pdev;
bool configured;
+ bool is_unplugged;
bool error_state;
bool lgstg_blocked;
uint32_t fh;
uint32_t fid;
+ uint32_t uid;
+ char *pci_id;
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
@@ -229,21 +244,39 @@ typedef struct S390PCIBusDevice {
uint8_t sum;
S390MsixInfo msix;
AdapterRoutes routes;
- AddressSpace as;
- MemoryRegion mr;
+ QTAILQ_ENTRY(S390PCIBusDevice) next;
} S390PCIBusDevice;
+typedef struct S390PCIDeviceConn {
+ S390PCIBusDevice *zpci;
+ AddressSpace iommu_as;
+ MemoryRegion iommu_mr;
+} S390PCIDeviceConn;
+
typedef struct S390pciState {
PCIHostState parent_obj;
- S390PCIBusDevice pbdev[PCI_SLOT_MAX];
+ S390PCIDeviceConn conn[PCI_SLOT_MAX];
AddressSpace msix_notify_as;
MemoryRegion msix_notify_mr;
- QTAILQ_HEAD(, SeiContainer) pending_sei;
} S390pciState;
+typedef struct S390PCIFacBus {
+ BusState qbus;
+} S390PCIFacBus;
+
+typedef struct S390PCIFacility {
+ SysBusDevice parent_obj;
+ S390PCIFacBus *fbus;
+ bool token_valid;
+ QTAILQ_HEAD(, S390PCIBusDevice) zpci_list;
+ QTAILQ_HEAD(, SeiContainer) pending_sei;
+} S390PCIFacility;
+
int chsc_sei_nt2_get_event(void *res);
int chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(int configure, SCCB *sccb);
+void s390_pci_device_enable(S390PCIBusDevice *zpci);
+void s390_pci_device_disable(S390PCIBusDevice *zpci);
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
@@ -38,6 +38,8 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
uint32_t res_code, initial_l2, g_l2, finish;
int rc, idx;
uint64_t resume_token;
+ S390PCIFacility *f = S390_PCI_FACILITY(
+ object_resolve_path(TYPE_S390_PCI_FACILITY, NULL));
rc = 0;
if (lduw_p(&rrb->request.hdr.len) != 32) {
@@ -63,6 +65,11 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
resume_token = ldq_p(&rrb->request.resume_token);
if (resume_token) {
+ if (!f->token_valid) {
+ res_code = CLP_RC_LISTPCI_BADRT;
+ rc = -EINVAL;
+ goto out;
+ }
pbdev = s390_pci_find_dev_by_idx(resume_token);
if (!pbdev) {
res_code = CLP_RC_LISTPCI_BADRT;
@@ -71,6 +78,7 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc)
}
}
+ f->token_valid = true;
if (lduw_p(&rrb->response.hdr.len) < 48) {
res_code = CLP_RC_8K;
rc = -EINVAL;
@@ -208,12 +216,12 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
switch (reqsetpci->oc) {
case CLP_SET_ENABLE_PCI_FN:
- pbdev->fh = pbdev->fh | 1 << ENABLE_BIT_OFFSET;
+ s390_pci_device_enable(pbdev);
stl_p(&ressetpci->fh, pbdev->fh);
stw_p(&ressetpci->hdr.rsp, CLP_RC_OK);
break;
case CLP_SET_DISABLE_PCI_FN:
- pbdev->fh = pbdev->fh & ~(1 << ENABLE_BIT_OFFSET);
+ s390_pci_device_disable(pbdev);
pbdev->error_state = false;
pbdev->lgstg_blocked = false;
stl_p(&ressetpci->fh, pbdev->fh);
@@ -129,8 +129,8 @@ static void ccw_init(MachineState *machine)
machine->initrd_filename, "s390-ccw.img", true);
s390_flic_init();
- dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
- object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
+ dev = qdev_create(NULL, TYPE_S390_PCI_FACILITY);
+ object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_FACILITY,
OBJECT(dev), NULL);
qdev_init_nofail(dev);
@@ -173,6 +173,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
mc->use_sclp = 1;
mc->max_cpus = 255;
mc->hot_add_cpu = ccw_hot_add_cpu;
+ mc->has_dynamic_sysbus = true;
nc->nmi_monitor_handler = s390_nmi;
}