From: Frank Blaschka <blaschka@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org, cornelia.huck@de.ibm.com,
borntraeger@de.ibm.com, agraf@suse.de, mst@redhat.com
Cc: MIHAJLOV@de.ibm.com, Frank Blaschka <blaschka@linux.vnet.ibm.com>,
fiuczy@linux.vnet.ibm.com
Subject: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
Date: Tue, 10 Mar 2015 14:03:34 +0100 [thread overview]
Message-ID: <1425992614-8938-3-git-send-email-blaschka@linux.vnet.ibm.com> (raw)
In-Reply-To: <1425992614-8938-1-git-send-email-blaschka@linux.vnet.ibm.com>
This patch changes the modeling of the s390 qemu pci infrastructure to
better match the actual pci architecture defined by the real hardware.
A pci host bridge like device (s390-pcihost) models the abstract view
of the bare pci function. It provides s390 specific configuration
attributes (fid and uid) for the attached pci device. The host bridge
restrict the pci bus to just hold one single pci device. Also we have
to make the s390 pci host bridge hot plugable. This is done by
implementing a s390 specific bus to attach this new host bridge like
devices.
Sample qemu configuration:
-device s390-pcihost,fid=16,uid=2216
-device e1000,bus=pci.0
-device s390-pcihost,fid=17,uid=2217,id=mydev
-device ne2k_pci,bus=mydev.0,addr=0
A pci device references the corresponding host bridge via pci bus name
(as usual). The pci device must be attached to slot 0 of the bus.
The fid and uid must be unique for the qemu instance. The design
allows to define (static and hotplug) multiple host bridges and support
a large number of pci devices.
Signed-off-by: Frank Blaschka <blaschka@linux.vnet.ibm.com>
---
hw/s390x/s390-pci-bus.c | 174 ++++++++++++++++++++++++++-------------------
hw/s390x/s390-pci-bus.h | 24 ++++++-
hw/s390x/s390-pci-inst.c | 2 +-
hw/s390x/s390-virtio-ccw.c | 4 +-
4 files changed, 128 insertions(+), 76 deletions(-)
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index dc455a2..6ad80d9 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -32,12 +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));
-
- if (!s) {
- return rc;
- }
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
sei_cont = QTAILQ_FIRST(&s->pending_sei);
if (sei_cont) {
@@ -71,31 +67,23 @@ 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));
-
- if (!s) {
- return 0;
- }
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
return !QTAILQ_EMPTY(&s->pending_sei);
}
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));
+ BusChild *kid;
+ S390pciState *state;
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_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)) {
- return pbdev;
+ QTAILQ_FOREACH(kid, &s->sbus.qbus.children, sibling) {
+ state = (S390pciState *)kid->child;
+ if ((state->pbdev[0].fh != 0) && (state->pbdev[0].fid == fid)) {
+ return &state->pbdev[0];
}
}
@@ -125,37 +113,23 @@ 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;
+ BusChild *kid;
int j = 0;
- S390pciState *s = S390_PCI_HOST_BRIDGE(
- object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL));
-
- if (!s) {
- return NULL;
- }
+ S390pciState *state;
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
+ QTAILQ_FOREACH(kid, &s->sbus.qbus.children, sibling) {
+ state = (S390pciState *)kid->child;
- if (pbdev->fh == 0) {
+ if (state->pbdev[0].fh == 0) {
continue;
}
if (j == idx) {
- return pbdev;
+ return &state->pbdev[0];
}
j++;
}
@@ -165,19 +139,19 @@ 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));
+ BusChild *kid;
+ S390pciState *state;
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
- if (!s || !fh) {
+ if (!fh) {
return NULL;
}
- for (i = 0; i < PCI_SLOT_MAX; i++) {
- pbdev = &s->pbdev[i];
- if (pbdev->fh == fh) {
- return pbdev;
+ QTAILQ_FOREACH(kid, &s->sbus.qbus.children, sibling) {
+ state = (S390pciState *)kid->child;
+ if (state->pbdev[0].fh == fh) {
+ return &state->pbdev[0];
}
}
@@ -188,12 +162,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));
-
- if (!s) {
- return;
- }
+ PCIFacility *s = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
sei_cont = g_malloc0(sizeof(SeiContainer));
sei_cont->fh = fh;
@@ -461,15 +431,29 @@ static void s390_pcihost_init_as(S390pciState *s)
address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci");
}
-static int s390_pcihost_init(SysBusDevice *dev)
+static void s390_pcihost_realize(DeviceState *dev, Error **errp)
{
PCIBus *b;
BusState *bus;
- PCIHostState *phb = PCI_HOST_BRIDGE(dev);
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
+ S390pciState *state;
+ BusChild *kid;
+ PCIFacility *fac = PCI_FACILITY(
+ object_resolve_path(TYPE_PCI_FACILITY, NULL));
DPRINTF("host_init\n");
+ QTAILQ_FOREACH(kid, &fac->sbus.qbus.children, sibling) {
+ state = (S390pciState *)kid->child;
+ if (state == s) {
+ continue;
+ }
+ if (state->fid == s->fid || state->uid == s->uid) {
+ error_setg(errp, "s390-pcihost needs unique fid and uid");
+ return;
+ }
+ }
+
b = pci_register_bus(DEVICE(dev), NULL,
s390_pci_set_irq, s390_pci_map_irq, NULL,
get_system_memory(), get_system_io(), 0, 64,
@@ -479,9 +463,6 @@ 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;
}
static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
@@ -520,12 +501,18 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pci_dev)
->qbus.parent);
+ if (PCI_SLOT(pci_dev->devfn) != 0) {
+ error_setg(errp, "s390-pcihost only slot 0 allowed.");
+ return;
+ }
+
pbdev = &s->pbdev[PCI_SLOT(pci_dev->devfn)];
- pbdev->fid = s390_pci_get_pfid(pci_dev);
+ pbdev->fid = s->fid;
+ pbdev->uid = s->uid;
pbdev->pdev = pci_dev;
pbdev->configured = true;
- pbdev->fh = s390_pci_get_pfh(pci_dev);
+ pbdev->fh = s->fid | FH_VIRT;
s390_pcihost_setup_msix(pbdev);
@@ -560,14 +547,20 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
object_unparent(OBJECT(pci_dev));
}
+static Property s390_pcihost_properties[] = {
+ DEFINE_PROP_UINT32("fid", S390pciState, fid, 0),
+ DEFINE_PROP_UINT32("uid", S390pciState, uid, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
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;
+ dc->props = s390_pcihost_properties;
+ dc->bus_type = TYPE_PCI_FACILITY_BUS;
+ dc->realize = s390_pcihost_realize;
hc->plug = s390_pcihost_hot_plug;
hc->unplug = s390_pcihost_hot_unplug;
msi_supported = true;
@@ -575,7 +568,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data)
static const TypeInfo s390_pcihost_info = {
.name = TYPE_S390_PCI_HOST_BRIDGE,
- .parent = TYPE_PCI_HOST_BRIDGE,
+ .parent = TYPE_DEVICE,
.instance_size = sizeof(S390pciState),
.class_init = s390_pcihost_class_init,
.interfaces = (InterfaceInfo[]) {
@@ -584,9 +577,46 @@ static const TypeInfo s390_pcihost_info = {
}
};
+static const TypeInfo pci_facility_bus_info = {
+ .name = TYPE_PCI_FACILITY_BUS,
+ .parent = TYPE_BUS,
+};
+
+static void pci_facility_realize(DeviceState *qdev, Error **errp)
+{
+ PCIFacility *facility = PCI_FACILITY(qdev);
+
+ qbus_create_inplace(&facility->sbus, sizeof(facility->sbus),
+ TYPE_PCI_FACILITY_BUS, qdev, NULL);
+
+ qbus_set_hotplug_handler(&facility->sbus.qbus, qdev, NULL);
+ QTAILQ_INIT(&facility->pending_sei);
+}
+
+static void pci_facility_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = pci_facility_realize;
+}
+
+static const TypeInfo pci_facility_info = {
+ .name = TYPE_PCI_FACILITY,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PCIFacility),
+ .class_init = pci_facility_class_init,
+ .class_size = sizeof(PCIFacilityClass),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_HOTPLUG_HANDLER },
+ { }
+ }
+};
+
static void s390_pci_register_types(void)
{
type_register_static(&s390_pcihost_info);
+ type_register_static(&pci_facility_info);
+ type_register_static(&pci_facility_bus_info);
}
type_init(s390_pci_register_types)
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 464a92e..78a5c83 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -220,6 +220,7 @@ typedef struct S390PCIBusDevice {
bool lgstg_blocked;
uint32_t fh;
uint32_t fid;
+ uint32_t uid;
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
@@ -238,7 +239,8 @@ typedef struct S390pciState {
S390PCIBusDevice pbdev[PCI_SLOT_MAX];
AddressSpace msix_notify_as;
MemoryRegion msix_notify_mr;
- QTAILQ_HEAD(, SeiContainer) pending_sei;
+ uint32_t fid;
+ uint32_t uid;
} S390pciState;
int chsc_sei_nt2_get_event(void *res);
@@ -248,4 +250,24 @@ 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);
+#define TYPE_PCI_FACILITY "pci-facility"
+#define TYPE_PCI_FACILITY_BUS "pci-facility-bus"
+
+#define PCI_FACILITY(obj) \
+ OBJECT_CHECK(PCIFacility, (obj), TYPE_PCI_FACILITY)
+
+typedef struct PCIFacilityBus {
+ BusState qbus;
+} PCIFacilityBus;
+
+typedef struct PCIFacility {
+ SysBusDevice parent_obj;
+ PCIFacilityBus sbus;
+ QTAILQ_HEAD(, SeiContainer) pending_sei;
+} PCIFacility;
+
+typedef struct PCIFacilityClass {
+ DeviceClass parent_class;
+ int (*init)(PCIFacility *pf);
+} PCIFacilityClass;
#endif
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 08d8aa6..d138b28 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -254,7 +254,7 @@ int clp_service_call(S390CPU *cpu, uint8_t r2)
stq_p(&resquery->edma, ZPCI_EDMA_ADDR);
stw_p(&resquery->pchid, 0);
stw_p(&resquery->ug, 1);
- stl_p(&resquery->uid, pbdev->fid);
+ stl_p(&resquery->uid, pbdev->uid);
stw_p(&resquery->hdr.rsp, CLP_RC_OK);
break;
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 8f0ae59..358b192 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -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_PCI_FACILITY);
+ object_property_add_child(qdev_get_machine(), TYPE_PCI_FACILITY,
OBJECT(dev), NULL);
qdev_init_nofail(dev);
--
2.1.4
next prev parent reply other threads:[~2015-03-10 13:03 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-10 13:03 [Qemu-devel] [PATCH 0/2 RFC] Extend s390 pci representation in qemu V2 Frank Blaschka
2015-03-10 13:03 ` [Qemu-devel] [PATCH 1/2 RFC] pci: detangle Sysbus PCI bridge from PCIBus Frank Blaschka
2015-03-10 13:03 ` Frank Blaschka [this message]
2015-03-10 14:26 ` [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling Michael S. Tsirkin
2015-03-11 14:38 ` Frank Blaschka
2015-03-11 14:57 ` Michael S. Tsirkin
2015-03-12 8:46 ` Frank Blaschka
2015-03-12 9:26 ` Michael S. Tsirkin
2015-03-11 17:42 ` Michael S. Tsirkin
2015-03-12 9:54 ` Frank Blaschka
2015-03-12 10:03 ` Michael S. Tsirkin
2015-03-12 10:50 ` Frank Blaschka
2015-03-12 13:16 ` Frank Blaschka
2015-03-12 14:59 ` Alexander Graf
2015-03-12 15:22 ` Michael S. Tsirkin
2015-03-17 7:11 ` Alexander Graf
2015-03-17 12:15 ` Frank Blaschka
2015-03-12 15:18 ` Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1425992614-8938-3-git-send-email-blaschka@linux.vnet.ibm.com \
--to=blaschka@linux.vnet.ibm.com \
--cc=MIHAJLOV@de.ibm.com \
--cc=agraf@suse.de \
--cc=borntraeger@de.ibm.com \
--cc=cornelia.huck@de.ibm.com \
--cc=fiuczy@linux.vnet.ibm.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).