Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Tue, Mar 17, 2015 at 08:11:14AM +0100, Alexander Graf wrote: On 12.03.15 16:22, Michael S. Tsirkin wrote: On Thu, Mar 12, 2015 at 09:59:59AM -0500, Alexander Graf wrote: On 12.03.15 08:16, Frank Blaschka wrote: On Thu, Mar 12, 2015 at 11:50:02AM +0100, Frank Blaschka wrote: On Thu, Mar 12, 2015 at 11:03:50AM +0100, Michael S. Tsirkin wrote: On Thu, Mar 12, 2015 at 10:54:24AM +0100, Frank Blaschka wrote: On Wed, Mar 11, 2015 at 06:42:34PM +0100, Michael S. Tsirkin wrote: On Wed, Mar 11, 2015 at 03:38:44PM +0100, Frank Blaschka wrote: On Tue, Mar 10, 2015 at 03:26:23PM +0100, Michael S. Tsirkin wrote: On Tue, Mar 10, 2015 at 02:03:34PM +0100, Frank Blaschka wrote: 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 requirement is really because of the 1 device per bus limitation, isn't it? If you supported many devices per bus, you could use hotplug there and there won't be need to support hotplug of the host bridge. Absolutely yes. Have you seen my first proposal? It basically exploits the normal pci bridge/bus/slot mechanism but need a place to store s390 specific configuration attributes. The idea of a host bridge having this attributes and limit the bus to one slot was an alternate design approach suggested by Alex. I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw 2) It does not create an somehow artifical pci topology I'll have to re-read but here's a thought: use your patch but remove host bridge hotplug support code. Stick a standard bridge with shpc support in the single slot behind your host bridge (existing pci-bridge-dev should do the trick, though not many people use it, so you might run into bugs, but fixing them is a good idea anyway). You can instanciate it automatically like Marcel's patches do for PXB. Still don't undertsand so I try to summarize in my words please corrent me if I got something wrong - create a standard host bridge - change the s390-pcihost to be a pci 2 pci bridge Actually I suggested simply adding a pci 2 pci bridge behind s390-pcihost. - now we can hotplug the s390-pcihost + hotplug a pci device to this s390-pcihost using standard pci hotplug mechanism My idea was to just hotplug a pci device behind the standard pci 2 pci bridge. don't support hotplugging bridge itself or s390-pcihost itself. - we keep the 1 slot limit on the s390-pcihost. We need a place to store fid and uid information (see mail thread from my 1 proposal) Yes. - If we need more than 32 pci functions we have to extend the primary pci bus via standart pci 2 pci bridges or add another standart host bridge Is this your suggestion? Almost, clarifications above. OK, got your idea. Have to think about it and may do some prototyping. THX! hm, after thinking more about this I realized this is not working for us. Remember we need a place to store the fid and uid attributes. This place must be: 1) uid/fid per pci device 2) uid/fid in a hotplugable device I have the feeling we are at the beginning again. Although I liked Alex's idea (host bridge containing uid/fid and having only 1 slot on the bus), it looks like we end up at my first proposal. This does not require any modification in base pci/bus code. Thx to all of you for the discussion and suggestions. I disagree with the assessment. The reason mst was opposed to do the one-phb-per-device implementation (which is the closest we can get to model things like real hardware FWIW) was that hotplug would work on the s390 level rather than pci. I don't see how your first proposal fixes that. Also Michael, PCI on s390 is very very special. Yes, I'm trying to wrap my head around it all. And is there hotplug support there on real hardware? I quite frankly don't know. Frank? yes there is, but it might be different than you expect from traditional PCI :-) You can't plug in anything that does not come from IBM. There are no PCIe connectors - instead you have IBM proprietary slots that only work with IBM approved devices. So things like we can plug in a PCI bridge simply don't work as well in that world. Alex But interestingly, the usage example that Frank gave actually shows e1000 and other non-IBM cards apparently working? This kind of confuses me. Sorry, I just use e1000 to give an example everybody can follow. Here is the actual
Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Wed, Mar 11, 2015 at 03:57:05PM +0100, Michael S. Tsirkin wrote: On Wed, Mar 11, 2015 at 03:38:44PM +0100, Frank Blaschka wrote: I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw why do you say this? does real hw has this one device per bridge limit? Actually we don't know. HW does not expose this information. All we know is each pci function is completely separated. So it is a good assumption to have a separate bridge/bus for each pci function. By the way the Linux kernel for s390 makes the same assumption by creating a new pci domain for each function. You may want to read the cover letter again to get more technical details on this.
Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Thu, Mar 12, 2015 at 11:03:50AM +0100, Michael S. Tsirkin wrote: On Thu, Mar 12, 2015 at 10:54:24AM +0100, Frank Blaschka wrote: On Wed, Mar 11, 2015 at 06:42:34PM +0100, Michael S. Tsirkin wrote: On Wed, Mar 11, 2015 at 03:38:44PM +0100, Frank Blaschka wrote: On Tue, Mar 10, 2015 at 03:26:23PM +0100, Michael S. Tsirkin wrote: On Tue, Mar 10, 2015 at 02:03:34PM +0100, Frank Blaschka wrote: 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 requirement is really because of the 1 device per bus limitation, isn't it? If you supported many devices per bus, you could use hotplug there and there won't be need to support hotplug of the host bridge. Absolutely yes. Have you seen my first proposal? It basically exploits the normal pci bridge/bus/slot mechanism but need a place to store s390 specific configuration attributes. The idea of a host bridge having this attributes and limit the bus to one slot was an alternate design approach suggested by Alex. I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw 2) It does not create an somehow artifical pci topology I'll have to re-read but here's a thought: use your patch but remove host bridge hotplug support code. Stick a standard bridge with shpc support in the single slot behind your host bridge (existing pci-bridge-dev should do the trick, though not many people use it, so you might run into bugs, but fixing them is a good idea anyway). You can instanciate it automatically like Marcel's patches do for PXB. Still don't undertsand so I try to summarize in my words please corrent me if I got something wrong - create a standard host bridge - change the s390-pcihost to be a pci 2 pci bridge Actually I suggested simply adding a pci 2 pci bridge behind s390-pcihost. - now we can hotplug the s390-pcihost + hotplug a pci device to this s390-pcihost using standard pci hotplug mechanism My idea was to just hotplug a pci device behind the standard pci 2 pci bridge. don't support hotplugging bridge itself or s390-pcihost itself. - we keep the 1 slot limit on the s390-pcihost. We need a place to store fid and uid information (see mail thread from my 1 proposal) Yes. - If we need more than 32 pci functions we have to extend the primary pci bus via standart pci 2 pci bridges or add another standart host bridge Is this your suggestion? Almost, clarifications above. OK, got your idea. Have to think about it and may do some prototyping. THX! You get hotplug + multiple devices for free. And the resulting topology is clearly something that *can* exist on bare-metal, since no one can prevent users sticking a pci bridge device in a pci slot. Again on bar s390 metal we do not have bridge bus slot at all. OS does not have any knowledge about it. So anything we try to model is somehow artificial. So I wonder: what does guest see if you do it like the above in QEMU? Do s390 guests even have ability to enumerate pci to pci bridges? I think the answer is no. All a s390 guest can do is call a s390 instruction to get a list of pci functions. There is no further information about the function. The fact there might be a bridge/bus/slot is completely abstracted in hw and not exposed to the OS. I think the fact, the hw guaranties a pci function is completetly independent, made the kernel folks to decide to enumarate the domain. Looking at a pci address on the guest (or in general on s390 kernel) you will never see a bus or slot != 0 (:00:00.0) Anyhow what we are doing do model pci in qemu, the guest will only see a list of pci functions and enumerate the domain to create a pci address and that's it Why do I prefer pci hotplug to s390 hotplug? s390 hotplug is really surprise removal. There's no way Don't understand this neither. s390 linux kernel is well prepared to receive s390 specific events to signal a pci function is going away. Anyhow we end up I can generate this events to get ack from guest. Linux isn't very well equipped to handle that, we might be able to fix it with time but current virtio drivers aren't very happy. This is done by implementing a s390 specific bus to attach this new host bridge like devices. Sample qemu configuration
Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Wed, Mar 11, 2015 at 06:42:34PM +0100, Michael S. Tsirkin wrote: On Wed, Mar 11, 2015 at 03:38:44PM +0100, Frank Blaschka wrote: On Tue, Mar 10, 2015 at 03:26:23PM +0100, Michael S. Tsirkin wrote: On Tue, Mar 10, 2015 at 02:03:34PM +0100, Frank Blaschka wrote: 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 requirement is really because of the 1 device per bus limitation, isn't it? If you supported many devices per bus, you could use hotplug there and there won't be need to support hotplug of the host bridge. Absolutely yes. Have you seen my first proposal? It basically exploits the normal pci bridge/bus/slot mechanism but need a place to store s390 specific configuration attributes. The idea of a host bridge having this attributes and limit the bus to one slot was an alternate design approach suggested by Alex. I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw 2) It does not create an somehow artifical pci topology I'll have to re-read but here's a thought: use your patch but remove host bridge hotplug support code. Stick a standard bridge with shpc support in the single slot behind your host bridge (existing pci-bridge-dev should do the trick, though not many people use it, so you might run into bugs, but fixing them is a good idea anyway). You can instanciate it automatically like Marcel's patches do for PXB. Still don't undertsand so I try to summarize in my words please corrent me if I got something wrong - create a standard host bridge - change the s390-pcihost to be a pci 2 pci bridge - now we can hotplug the s390-pcihost + hotplug a pci device to this s390-pcihost using standard pci hotplug mechanism - we keep the 1 slot limit on the s390-pcihost. We need a place to store fid and uid information (see mail thread from my 1 proposal) - If we need more than 32 pci functions we have to extend the primary pci bus via standart pci 2 pci bridges or add another standart host bridge Is this your suggestion? You get hotplug + multiple devices for free. And the resulting topology is clearly something that *can* exist on bare-metal, since no one can prevent users sticking a pci bridge device in a pci slot. Again on bar s390 metal we do not have bridge bus slot at all. OS does not have any knowledge about it. So anything we try to model is somehow artificial. Why do I prefer pci hotplug to s390 hotplug? s390 hotplug is really surprise removal. There's no way Don't understand this neither. s390 linux kernel is well prepared to receive s390 specific events to signal a pci function is going away. Anyhow we end up I can generate this events to get ack from guest. Linux isn't very well equipped to handle that, we might be able to fix it with time but current virtio drivers aren't very happy. 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. How about sticking a pci to pci bridge behind the host bridge? You could also support hotplug using shpc, all this without writing code. Hm, I don't understand this in detail, can you elaborate a little bit more on this? For me it looks like this has the same issues like my first proposal. We build a complete artifical pci topology in qemu, which has nothing to do with the real hw. If we include pci 2 pci bridges this makes configuration even more a nightmare for users. Do you think detangle pci bus from bridge breaks some fundamental design? If so, I would rather go with my first proposal than adding even more complexity to implementation and configuration. Thx, Frank Signed-off-by: Frank Blaschka blasc...@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
Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Thu, Mar 12, 2015 at 11:50:02AM +0100, Frank Blaschka wrote: On Thu, Mar 12, 2015 at 11:03:50AM +0100, Michael S. Tsirkin wrote: On Thu, Mar 12, 2015 at 10:54:24AM +0100, Frank Blaschka wrote: On Wed, Mar 11, 2015 at 06:42:34PM +0100, Michael S. Tsirkin wrote: On Wed, Mar 11, 2015 at 03:38:44PM +0100, Frank Blaschka wrote: On Tue, Mar 10, 2015 at 03:26:23PM +0100, Michael S. Tsirkin wrote: On Tue, Mar 10, 2015 at 02:03:34PM +0100, Frank Blaschka wrote: 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 requirement is really because of the 1 device per bus limitation, isn't it? If you supported many devices per bus, you could use hotplug there and there won't be need to support hotplug of the host bridge. Absolutely yes. Have you seen my first proposal? It basically exploits the normal pci bridge/bus/slot mechanism but need a place to store s390 specific configuration attributes. The idea of a host bridge having this attributes and limit the bus to one slot was an alternate design approach suggested by Alex. I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw 2) It does not create an somehow artifical pci topology I'll have to re-read but here's a thought: use your patch but remove host bridge hotplug support code. Stick a standard bridge with shpc support in the single slot behind your host bridge (existing pci-bridge-dev should do the trick, though not many people use it, so you might run into bugs, but fixing them is a good idea anyway). You can instanciate it automatically like Marcel's patches do for PXB. Still don't undertsand so I try to summarize in my words please corrent me if I got something wrong - create a standard host bridge - change the s390-pcihost to be a pci 2 pci bridge Actually I suggested simply adding a pci 2 pci bridge behind s390-pcihost. - now we can hotplug the s390-pcihost + hotplug a pci device to this s390-pcihost using standard pci hotplug mechanism My idea was to just hotplug a pci device behind the standard pci 2 pci bridge. don't support hotplugging bridge itself or s390-pcihost itself. - we keep the 1 slot limit on the s390-pcihost. We need a place to store fid and uid information (see mail thread from my 1 proposal) Yes. - If we need more than 32 pci functions we have to extend the primary pci bus via standart pci 2 pci bridges or add another standart host bridge Is this your suggestion? Almost, clarifications above. OK, got your idea. Have to think about it and may do some prototyping. THX! hm, after thinking more about this I realized this is not working for us. Remember we need a place to store the fid and uid attributes. This place must be: 1) uid/fid per pci device 2) uid/fid in a hotplugable device I have the feeling we are at the beginning again. Although I liked Alex's idea (host bridge containing uid/fid and having only 1 slot on the bus), it looks like we end up at my first proposal. This does not require any modification in base pci/bus code. Thx to all of you for the discussion and suggestions. You get hotplug + multiple devices for free. And the resulting topology is clearly something that *can* exist on bare-metal, since no one can prevent users sticking a pci bridge device in a pci slot. Again on bar s390 metal we do not have bridge bus slot at all. OS does not have any knowledge about it. So anything we try to model is somehow artificial. So I wonder: what does guest see if you do it like the above in QEMU? Do s390 guests even have ability to enumerate pci to pci bridges? I think the answer is no. All a s390 guest can do is call a s390 instruction to get a list of pci functions. There is no further information about the function. The fact there might be a bridge/bus/slot is completely abstracted in hw and not exposed to the OS. I think the fact, the hw guaranties a pci function is completetly independent, made the kernel folks to decide to enumarate the domain. Looking at a pci address on the guest (or in general on s390 kernel) you will never see a bus or slot != 0 (:00:00.0) Anyhow what we are doing do model pci in qemu, the guest will only see a list of pci functions
Re: [Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
On Tue, Mar 10, 2015 at 03:26:23PM +0100, Michael S. Tsirkin wrote: On Tue, Mar 10, 2015 at 02:03:34PM +0100, Frank Blaschka wrote: 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 requirement is really because of the 1 device per bus limitation, isn't it? If you supported many devices per bus, you could use hotplug there and there won't be need to support hotplug of the host bridge. Absolutely yes. Have you seen my first proposal? It basically exploits the normal pci bridge/bus/slot mechanism but need a place to store s390 specific configuration attributes. The idea of a host bridge having this attributes and limit the bus to one slot was an alternate design approach suggested by Alex. I like Alex's idea because: 1) It reflects pretty well the actual nature of the pci system in real s390 hw 2) It does not create an somehow artifical pci topology 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. How about sticking a pci to pci bridge behind the host bridge? You could also support hotplug using shpc, all this without writing code. Hm, I don't understand this in detail, can you elaborate a little bit more on this? For me it looks like this has the same issues like my first proposal. We build a complete artifical pci topology in qemu, which has nothing to do with the real hw. If we include pci 2 pci bridges this makes configuration even more a nightmare for users. Do you think detangle pci bus from bridge breaks some fundamental design? If so, I would rather go with my first proposal than adding even more complexity to implementation and configuration. Thx, Frank Signed-off-by: Frank Blaschka blasc...@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
[Qemu-devel] [PATCH 2/2 RFC] s390x/pci: rework pci infrastructure modeling
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 blasc...@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
[Qemu-devel] [PATCH 1/2 RFC] pci: detangle Sysbus PCI bridge from PCIBus
This patch detangle Sysbus PCI bridge from PCIBus. The pci host bridge is derived from sysbus device and therefore it is not possible to hotplug a host bridge. This change makes it possible to develop hotplugable devices creating a pci bus on the fly. Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/pci/pci.c | 24 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index cc5d946..553a130 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -253,9 +253,11 @@ static void pcibus_reset(BusState *qbus) static void pci_host_bus_register(PCIBus *bus, DeviceState *parent) { -PCIHostState *host_bridge = PCI_HOST_BRIDGE(parent); - -QLIST_INSERT_HEAD(pci_host_bridges, host_bridge, next); +PCIHostState *host_bridge = (PCIHostState *)object_dynamic_cast( +OBJECT(parent), TYPE_PCI_HOST_BRIDGE); +if (host_bridge) { +QLIST_INSERT_HEAD(pci_host_bridges, host_bridge, next); +} } PCIBus *pci_find_primary_bus(void) @@ -288,14 +290,20 @@ PCIBus *pci_device_root_bus(const PCIDevice *d) const char *pci_root_bus_path(PCIDevice *dev) { PCIBus *rootbus = pci_device_root_bus(dev); -PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus-qbus.parent); -PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge); +PCIHostState *host_bridge; +PCIHostBridgeClass *hc; + +host_bridge = (PCIHostState *)object_dynamic_cast( + OBJECT(rootbus-qbus.parent), TYPE_PCI_HOST_BRIDGE); assert(!rootbus-parent_dev); -assert(host_bridge-bus == rootbus); -if (hc-root_bus_path) { -return (*hc-root_bus_path)(host_bridge, rootbus); +if (host_bridge) { +assert(host_bridge-bus == rootbus); +hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge); +if (hc-root_bus_path) { +return (*hc-root_bus_path)(host_bridge, rootbus); +} } return rootbus-qbus.name; -- 2.1.4
[Qemu-devel] [PATCH 0/2 RFC] Extend s390 pci representation in qemu V2
For a better understanding of the following patch here is some general information about how PCI is implemented on the s390 platform. The physical structure of the pci system (bridge, bus, slot) is not shown to the OS. Instead a firmware and I/O configuration layer abstracts each PCI card to a bare PCI function. In essence, the fw layer provides a simple enumeration of the individual devices, which the s390 pci implementation in the Linux kernel translates into individual pci domains. HW layer | FW layer | Linux kernel | | (opaque) | function 1 | 0001:00:00.0 | function 2 | 0002:00:00.0 | function 3 | 0003:00:00.0 In qemu we have following problems: (1) We have to represent this s390 specific topology information, respectively the lack thereof (2) We have/want to use common qemu PCI infrastructure The initial implementation did not honor (1) much and tried to derive s390 specific configuration attributes from attributes of qemu pci devices. It turns out that this is not flexible enough and is not sufficient to support s390 specific configurations. Here is some nice characterization about the nature of the s390 host bridge (by Alexander Graf). Conceptually your PCI bridge is not a sysbus device, since it doesn't live on a flat MMIO + legacy IRQ routing bus. Instead, it lives on its own thing that handles MMIO and IRQs via special backdoor interfaces. The proposed solution is an outcome of a previous discussion here on the qemu-devel mailing list. The s390 patch tries to better model the pci infrastructure by extending the s390 pci host bridge. Major changes are: 1) add configuration attributes (in reality provided by firmware layer) to the host bridge. 2) restrict pci bus of the bridge to just one slot 3) make a s390 host bridge hot plugable Frank Blaschka (2): pci: detangle Sysbus PCI bridge from PCIBus s390x/pci: rework pci infrastructure modeling hw/pci/pci.c | 24 --- 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 +- 5 files changed, 144 insertions(+), 84 deletions(-) -- 2.1.4
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Wed, Mar 04, 2015 at 04:58:25PM +0100, Frank Blaschka wrote: On Wed, Mar 04, 2015 at 04:25:07PM +0100, Alexander Graf wrote: On 04.03.15 16:07, Frank Blaschka wrote: On Wed, Mar 04, 2015 at 03:49:15PM +0100, Alexander Graf wrote: On 04.03.15 14:44, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 09:38:37PM +0100, Alexander Graf wrote: On 03.03.15 14:25, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 10:33:05AM +0100, Alexander Graf wrote: Am 03.03.2015 um 09:06 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. So they are arbitrary numbers? What uniqueness constraints do we have on them? fid and uid must be unique within the same qemu. At a first look the numbers are arbitrary but our configuration folks want explicitly define a particular fid and uid to better support migration and pass-through scenarios. Well, at the end of the day you want to make sure they're identical on both sides, yes. IIUC you can only have a single pcie device behind a virtual bus anyway, so what if we just calculate uid and fid from the bus id? I think this similar to the current implementation. We use the slot (idea for the future was bus + slot) to generate uid and fid. But this is not flexible enough. As I said, our configuration folks want to be able to specify fid and uid for the device. I don't see how this is different from what PPC does with its LIOBN which is a property of the PHB. Alex I played arround with the idea of having multiple host bridges and this worked well at least for static (non hotplug) configuration. In case I want to hotplug a host bridge I got following error: (qemu) device_add s390-pcihost,fid=8,uid=9 Bus 'main-system-bus' does not support hotplugging Is there anything I have to enable to support this? I have: has_dynamic_sysbus = 1 and cannot_instantiate_with_device_add_yet = false but this seems not to help for the hotplug case. Having s390 devices reside on sysbus is probably a bad idea. Instead, they should be on an s390 specific bus which then can implement hotplug easily. Alex Hm now I get lost ... Do you suggest we should implement a s390 specific device (which is not derived from TYPE_PCI_HOST_BRIDGE) but implements a pci bus so we can attach a pci device to this device? Ugh, PCI_HOST_BRIDGE is a sysbus device. Awesome. Conceptually your PCI bridge is not a sysbus device, since it doesn't live on a flat MMIO + legacy IRQ routing bus. Instead, it lives on its own thing that handles MMIO and IRQs via special backdoor interfaces. well spoken :-) How much of the PCI_HOST_BRIDGE device are you actually using? Would it be a lot of effort to have another s390 specific device
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Wed, Mar 04, 2015 at 04:25:07PM +0100, Alexander Graf wrote: On 04.03.15 16:07, Frank Blaschka wrote: On Wed, Mar 04, 2015 at 03:49:15PM +0100, Alexander Graf wrote: On 04.03.15 14:44, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 09:38:37PM +0100, Alexander Graf wrote: On 03.03.15 14:25, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 10:33:05AM +0100, Alexander Graf wrote: Am 03.03.2015 um 09:06 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. So they are arbitrary numbers? What uniqueness constraints do we have on them? fid and uid must be unique within the same qemu. At a first look the numbers are arbitrary but our configuration folks want explicitly define a particular fid and uid to better support migration and pass-through scenarios. Well, at the end of the day you want to make sure they're identical on both sides, yes. IIUC you can only have a single pcie device behind a virtual bus anyway, so what if we just calculate uid and fid from the bus id? I think this similar to the current implementation. We use the slot (idea for the future was bus + slot) to generate uid and fid. But this is not flexible enough. As I said, our configuration folks want to be able to specify fid and uid for the device. I don't see how this is different from what PPC does with its LIOBN which is a property of the PHB. Alex I played arround with the idea of having multiple host bridges and this worked well at least for static (non hotplug) configuration. In case I want to hotplug a host bridge I got following error: (qemu) device_add s390-pcihost,fid=8,uid=9 Bus 'main-system-bus' does not support hotplugging Is there anything I have to enable to support this? I have: has_dynamic_sysbus = 1 and cannot_instantiate_with_device_add_yet = false but this seems not to help for the hotplug case. Having s390 devices reside on sysbus is probably a bad idea. Instead, they should be on an s390 specific bus which then can implement hotplug easily. Alex Hm now I get lost ... Do you suggest we should implement a s390 specific device (which is not derived from TYPE_PCI_HOST_BRIDGE) but implements a pci bus so we can attach a pci device to this device? Ugh, PCI_HOST_BRIDGE is a sysbus device. Awesome. Conceptually your PCI bridge is not a sysbus device, since it doesn't live on a flat MMIO + legacy IRQ routing bus. Instead, it lives on its own thing that handles MMIO and IRQs via special backdoor interfaces. well spoken :-) How much of the PCI_HOST_BRIDGE device are you actually using? Would it be a lot of effort to have another s390 specific device that exposes a PCIBus, but is not of type PCI_HOST_BRIDGE (and thus sysbus)? I do not use much functionality of the PCI_HOST_BRIDGE but I was not able to put a pci bus on a device != PCI_HOST_BRIDGE. If I recall
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Tue, Mar 03, 2015 at 09:38:37PM +0100, Alexander Graf wrote: On 03.03.15 14:25, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 10:33:05AM +0100, Alexander Graf wrote: Am 03.03.2015 um 09:06 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. So they are arbitrary numbers? What uniqueness constraints do we have on them? fid and uid must be unique within the same qemu. At a first look the numbers are arbitrary but our configuration folks want explicitly define a particular fid and uid to better support migration and pass-through scenarios. Well, at the end of the day you want to make sure they're identical on both sides, yes. IIUC you can only have a single pcie device behind a virtual bus anyway, so what if we just calculate uid and fid from the bus id? I think this similar to the current implementation. We use the slot (idea for the future was bus + slot) to generate uid and fid. But this is not flexible enough. As I said, our configuration folks want to be able to specify fid and uid for the device. I don't see how this is different from what PPC does with its LIOBN which is a property of the PHB. Alex I played arround with the idea of having multiple host bridges and this worked well at least for static (non hotplug) configuration. In case I want to hotplug a host bridge I got following error: (qemu) device_add s390-pcihost,fid=8,uid=9 Bus 'main-system-bus' does not support hotplugging Is there anything I have to enable to support this? I have: has_dynamic_sysbus = 1 and cannot_instantiate_with_device_add_yet = false but this seems not to help for the hotplug case. Frank
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Wed, Mar 04, 2015 at 03:49:15PM +0100, Alexander Graf wrote: On 04.03.15 14:44, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 09:38:37PM +0100, Alexander Graf wrote: On 03.03.15 14:25, Frank Blaschka wrote: On Tue, Mar 03, 2015 at 10:33:05AM +0100, Alexander Graf wrote: Am 03.03.2015 um 09:06 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. So they are arbitrary numbers? What uniqueness constraints do we have on them? fid and uid must be unique within the same qemu. At a first look the numbers are arbitrary but our configuration folks want explicitly define a particular fid and uid to better support migration and pass-through scenarios. Well, at the end of the day you want to make sure they're identical on both sides, yes. IIUC you can only have a single pcie device behind a virtual bus anyway, so what if we just calculate uid and fid from the bus id? I think this similar to the current implementation. We use the slot (idea for the future was bus + slot) to generate uid and fid. But this is not flexible enough. As I said, our configuration folks want to be able to specify fid and uid for the device. I don't see how this is different from what PPC does with its LIOBN which is a property of the PHB. Alex I played arround with the idea of having multiple host bridges and this worked well at least for static (non hotplug) configuration. In case I want to hotplug a host bridge I got following error: (qemu) device_add s390-pcihost,fid=8,uid=9 Bus 'main-system-bus' does not support hotplugging Is there anything I have to enable to support this? I have: has_dynamic_sysbus = 1 and cannot_instantiate_with_device_add_yet = false but this seems not to help for the hotplug case. Having s390 devices reside on sysbus is probably a bad idea. Instead, they should be on an s390 specific bus which then can implement hotplug easily. Alex Hm now I get lost ... Do you suggest we should implement a s390 specific device (which is not derived from TYPE_PCI_HOST_BRIDGE) but implements a pci bus so we can attach a pci device to this device?
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. You can read them out via s390 specific device attributes e.g. # cat /sys/bus/pci/devices/\:00\:00.0/function_id 0x0016 # cat /sys/bus/pci/devices/\:00\:00.0/uid 0x25 Since there is no regular pci address (as explained earlier) I think this is a mechanism to unique identify a pci function. We discussed both options how to model this in qemu, but maybe you have another even better idea how to bring this additional attributes to a qemu pci device. Thx for any help and new ideas ... Frank Alex
Re: [Qemu-devel] [PATCH RFC 1/1] s390x/pci: Extend pci representation by new zpci device
On Tue, Mar 03, 2015 at 10:33:05AM +0100, Alexander Graf wrote: Am 03.03.2015 um 09:06 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Thu, Feb 26, 2015 at 04:34:06PM +0100, Alexander Graf wrote: On 26.02.15 16:27, Frank Blaschka wrote: On Thu, Feb 26, 2015 at 03:39:15PM +0100, Alexander Graf wrote: On 26.02.15 12:59, Frank Blaschka wrote: This patch extends the current s390 pci implementation to provide more flexibility in configuration of s390 specific device handling. For this we had to introduce a new facility (and bus) to hold devices representing information actually provided by s390 firmware and I/O configuration. On s390 the physical structure of the pci system (bridge, bus, slot) in not shown to the OS. For this the pci bridge and bus created in qemu can also not be shown to the guest. The new zpci device class represents this abstract view on the bare pci function and allows to provide s390 specific configuration attributes for it. Sample qemu configuration: -device e1000,id=zpci1 -device ne2k_pci,id=zpci2 -device zpci,fid=2,uid=1248,pci_id=zpci1 -device zpci,fid=17,uid=2244,pci_id=zpci2 A zpci device references the corresponding PCI device via device id. The new design allows to define multiple host bridges and support more pci devices. Isn't this reverse? Shouldn't it rather be -device zpci,...,id=zpci1 -device e1000,bus=zpci1.0 with a limit on each virtual zpci bus to only support one device? Do you mean something like having multiple host bridges (providing a pci bus each) and limit the bus to just one device? -device s390-pcihost,fid=16,uid=1234 -device s390-pcihost,fid=17,uid=5678 -device e1000,bus=pci.0 -device ne2k_pci,bus=pci.1 We also discussed this option but we don't like the idea to put attributes belong to the pci device to the host bridge. I guess I'm not grasping something obvious here :). What exactly are the attributes again? Sorry for the late response, I was on vacation the last couple days. The fid and uid values are provided by microcode/io layer on the real hardware. So they are arbitrary numbers? What uniqueness constraints do we have on them? fid and uid must be unique within the same qemu. At a first look the numbers are arbitrary but our configuration folks want explicitly define a particular fid and uid to better support migration and pass-through scenarios. IIUC you can only have a single pcie device behind a virtual bus anyway, so what if we just calculate uid and fid from the bus id? I think this similar to the current implementation. We use the slot (idea for the future was bus + slot) to generate uid and fid. But this is not flexible enough. As I said, our configuration folks want to be able to specify fid and uid for the device. Alex You can read them out via s390 specific device attributes e.g. # cat /sys/bus/pci/devices/\:00\:00.0/function_id 0x0016 # cat /sys/bus/pci/devices/\:00\:00.0/uid 0x25 Since there is no regular pci address (as explained earlier) I think this is a mechanism to unique identify a pci function. We discussed both options how to model this in qemu, but maybe you have another even better idea how to bring this additional attributes to a qemu pci device. Thx for any help and new ideas ... Frank Alex
[Qemu-devel] [PATCH RFC 0/1] Extend s390 pci representation in qemu
For a better understanding of the following patch here is some general information about how PCI is implemented on the s390 platform. The physical structure of the pci system (bridge, bus, slot) is not shown to the OS. Instead a firmware and I/O configuration layer abstracts each PCI card to a bare PCI function. In essence, the fw layer provides a simple enumeration of the individual devices, which the s390 pci implementation in the Linux kernel translates into individual pci domains. HW layer | FW layer | Linux kernel | | (opaque) | function 1 | 0001:00:00.0 | function 2 | 0002:00:00.0 | function 3 | 0003:00:00.0 In qemu we have following problems: (1) We have to represent this s390 specific topology information, respectively the lack thereof (2) We have/want to use common qemu PCI infrastructure The initial implementation did not honor (1) much and tried to derive s390 specific configuration attributes from attributes of qemu pci devices. It turns out that this is not flexible enough and is not sufficient to support s390 specific configurations. The following patch introduces a new zPCI device that kind of represents the fw layer on real hardware and provides the s390 specific information needed by guest operating systems. We keep the pci devices the same as in the general case and just hook them up with the corresponding zPCI device. Frank Blaschka (1): s390x/pci: Extend pci representation by new zpci device hw/s390x/s390-pci-bus.c| 253 - hw/s390x/s390-pci-bus.h| 38 ++- hw/s390x/s390-pci-inst.c | 2 +- hw/s390x/s390-virtio-ccw.c | 8 +- 4 files changed, 227 insertions(+), 74 deletions(-) -- 2.1.4
[Qemu-devel] [PATCH V2] s390x/pci: avoid sign extension in stpcifc
this patch avoids sign extension and fixes a data conversion bug in stpcifc. Both issues where found by Coverity. Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/s390x/s390-pci-inst.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 5ea13e5..c269184 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -784,10 +784,10 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) stq_p(fib.aisb, pbdev-routes.adapter.summary_addr); stq_p(fib.fmb_addr, pbdev-fmb_addr); -data = (pbdev-isc 28) | (pbdev-noi 16) | - (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | - pbdev-routes.adapter.summary_offset; -stw_p(fib.data, data); +data = ((uint32_t)pbdev-isc 28) | ((uint32_t)pbdev-noi 16) | + ((uint32_t)pbdev-routes.adapter.ind_offset 8) | + ((uint32_t)pbdev-sum 7) | pbdev-routes.adapter.summary_offset; +stl_p(fib.data, data); if (pbdev-fh ENABLE_BIT_OFFSET) { fib.fc |= 0x80; -- 2.1.4
[Qemu-devel] [PATCH] s390x/pci: avoid sign extension in stpcifc
this patch avoids sign extension and fixes a data conversion bug in stpcifc. Both issues where found by Coverity. Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/s390x/s390-pci-inst.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 5ea13e5..4d4015c 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -785,9 +785,9 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) stq_p(fib.fmb_addr, pbdev-fmb_addr); data = (pbdev-isc 28) | (pbdev-noi 16) | - (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | - pbdev-routes.adapter.summary_offset; -stw_p(fib.data, data); + ((uint32_t)pbdev-routes.adapter.ind_offset 8) | + (pbdev-sum 7) | pbdev-routes.adapter.summary_offset; +stl_p(fib.data, data); if (pbdev-fh ENABLE_BIT_OFFSET) { fib.fc |= 0x80; -- 2.1.4
Re: [Qemu-devel] [PATCH 2/3 V3] s390: implement pci instructions
On Tue, Jan 20, 2015 at 01:56:09PM +0100, Markus Armbruster wrote: Markus Armbruster arm...@redhat.com writes: Cornelia Huck cornelia.h...@de.ibm.com writes: On Tue, 20 Jan 2015 10:45:41 +0100 Markus Armbruster arm...@redhat.com wrote: This patch makes Coverity unhappy: *** CID 1264326: Unintended sign extension (SIGN_EXTENSION) /hw/s390x/s390-pci-inst.c: 787 in stpcifc_service_call() 781 stq_p(fib.pal, pbdev-pal); 782 stq_p(fib.iota, pbdev-g_iota); 783 stq_p(fib.aibv, pbdev-routes.adapter.ind_addr); 784 stq_p(fib.aisb, pbdev-routes.adapter.summary_addr); 785 stq_p(fib.fmb_addr, pbdev-fmb_addr); 786 CID 1264326: Unintended sign extension (SIGN_EXTENSION) Suspicious implicit sign extension: pbdev-isc with type unsigned char (8 bits, unsigned) is promoted in (pbdev-isc 28) | (pbdev-noi 16) to type int (32 bits, signed), then sign-extended to type unsigned long (64 bits, unsigned). If (pbdev-isc 28) | (pbdev-noi 16) is greater than 0x7FFF, the upper bits of the result will all be 1. 787 data = (pbdev-isc 28) | (pbdev-noi 16) | 788 (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | 789pbdev-routes.adapter.summary_offset; 790 stw_p(fib.data, data); 791 792 if (pbdev-fh ENABLE_BIT_OFFSET) { There's a fix for this (and the memory leak): http://marc.info/?l=qemu-develm=142124886620078w=2 The patch is sitting in my queue, will send with the next pile of s390x updates. I can't see how @@ -787,7 +787,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) data = (pbdev-isc 28) | (pbdev-noi 16) | (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | pbdev-routes.adapter.summary_offset; -stw_p(fib.data, data); +stl_p(fib.data, data); if (pbdev-fh ENABLE_BIT_OFFSET) { fib.fc |= 0x80; fixes the implicit sign extension within the assignment preceding it. Let me explain it again real slow: 1. pbdev-isc gets promoted from uint8_t to int as operand of binary (usual arithmetic conversions ISO/IEC 9899:1999 6.3.1.8) 2. The int result is shifted left 28 bits. This can set the MSB. 3. Likewise: pbdev-noi gets promoted from uint64_t to int, and shifted left 16 bits. uint16_t to int 4. The two shift results stay int and get ored. 5. pbdev-routes.adapter.ind_offset stays uint64_t, and is shifted left 8 bits. 6. The next or's left operand is the int result of 4 and the right operant is the uint64_t result of 5. Therefore, the left operand is *sign-extended* from int to uint64_t. This copies bit#7 of pbdev-isc to bits#31..63. Whoops. I neglected to say: we don't currently use the upper 32 bits, and as long as we do that, the sign extension is harmless. I'd recommend to avoid it all the same, for robustness, and to hush up Coverity. Hi Markus, thx for your explanation. I did not see a problem since ISC is not bigger than 0x7 so MSB is never set. But the time I wrote the code I was not aware of ind_offset is uint64_t since zpci defines only a 6 bit field for this value. How can I avoid the sign extension and make Coverity happy? Regarding the leak, I prefer my patch, because it avoids the free on error. But you're the maintainer. This is fine for me as well ... Thx, Frank
[Qemu-devel] [PATCH] s390x/pci: fix 2 bugs found by coverity
Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/s390x/s390-pci-bus.c | 1 + hw/s390x/s390-pci-inst.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 1201b8d..546dcf1 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -192,6 +192,7 @@ static void s390_pci_generate_event(uint8_t cc, uint16_t pec, uint32_t fh, object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE, NULL)); if (!s) { +g_free(sei_cont); return; } diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 5ea13e5..5596679 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -787,7 +787,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) data = (pbdev-isc 28) | (pbdev-noi 16) | (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | pbdev-routes.adapter.summary_offset; -stw_p(fib.data, data); +stl_p(fib.data, data); if (pbdev-fh ENABLE_BIT_OFFSET) { fib.fc |= 0x80; -- 2.1.4
[Qemu-devel] [PATCH 2/3 V3] s390: implement pci instructions
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/Makefile.objs | 2 +- hw/s390x/s390-pci-inst.c | 811 +++ hw/s390x/s390-pci-inst.h | 288 + target-s390x/kvm.c | 153 + 4 files changed, 1253 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 428d957..27cd75a 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,4 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o -obj-y += s390-pci-bus.o +obj-y += s390-pci-bus.o s390-pci-inst.o diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c new file mode 100644 index 000..d486cbb --- /dev/null +++ b/hw/s390x/s390-pci-inst.c @@ -0,0 +1,811 @@ +/* + * s390 PCI instructions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include s390-pci-inst.h +#include s390-pci-bus.h +#include exec/memory-internal.h +#include qemu/error-report.h + +/* #define DEBUG_S390PCI_INST */ +#ifdef DEBUG_S390PCI_INST +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, s390pci-inst: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static void s390_set_status_code(CPUS390XState *env, + uint8_t r, uint64_t status_code) +{ +env-regs[r] = ~0xff00ULL; +env-regs[r] |= (status_code 0xff) 24; +} + +static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) +{ +S390PCIBusDevice *pbdev; +uint32_t res_code, initial_l2, g_l2, finish; +int rc, idx; +uint64_t resume_token; + +rc = 0; +if (lduw_p(rrb-request.hdr.len) != 32) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) CLP_MASK_FMT) != 0) { +res_code = CLP_RC_FMT; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) ~CLP_MASK_FMT) != 0 || +ldq_p(rrb-request.reserved1) != 0 || +ldq_p(rrb-request.reserved2) != 0) { +res_code = CLP_RC_RESNOT0; +rc = -EINVAL; +goto out; +} + +resume_token = ldq_p(rrb-request.resume_token); + +if (resume_token) { +pbdev = s390_pci_find_dev_by_idx(resume_token); +if (!pbdev) { +res_code = CLP_RC_LISTPCI_BADRT; +rc = -EINVAL; +goto out; +} +} + +if (lduw_p(rrb-response.hdr.len) 48) { +res_code = CLP_RC_8K; +rc = -EINVAL; +goto out; +} + +initial_l2 = lduw_p(rrb-response.hdr.len); +if ((initial_l2 - LIST_PCI_HDR_LEN) % sizeof(ClpFhListEntry) +!= 0) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +*cc = 3; +goto out; +} + +stl_p(rrb-response.fmt, 0); +stq_p(rrb-response.reserved1, 0); +stq_p(rrb-response.reserved2, 0); +stl_p(rrb-response.mdd, FH_VIRT); +stw_p(rrb-response.max_fn, PCI_MAX_FUNCTIONS); +rrb-response.entry_size = sizeof(ClpFhListEntry); +finish = 0; +idx = resume_token; +g_l2 = LIST_PCI_HDR_LEN; +do { +pbdev = s390_pci_find_dev_by_idx(idx); +if (!pbdev) { +finish = 1; +break; +} +stw_p(rrb-response.fh_list[idx - resume_token].device_id, +pci_get_word(pbdev-pdev-config + PCI_DEVICE_ID)); +stw_p(rrb-response.fh_list[idx - resume_token].vendor_id, +pci_get_word(pbdev-pdev-config + PCI_VENDOR_ID)); +stl_p(rrb-response.fh_list[idx - resume_token].config, 0x8000); +stl_p(rrb-response.fh_list[idx - resume_token].fid, pbdev-fid); +stl_p(rrb-response.fh_list[idx - resume_token].fh, pbdev-fh); + +g_l2 += sizeof(ClpFhListEntry); +/* Add endian check for DPRINTF? */ +DPRINTF(g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n, +g_l2, +lduw_p(rrb-response.fh_list[idx - resume_token].vendor_id), +lduw_p(rrb-response.fh_list[idx - resume_token].device_id), +ldl_p(rrb-response.fh_list[idx - resume_token].fid), +ldl_p(rrb-response.fh_list[idx - resume_token].fh)); +idx++; +} while (g_l2 initial_l2); + +if (finish == 1) { +resume_token = 0
[Qemu-devel] [PATCH 3/3 V3] kvm: extend kvm_irqchip_add_msi_route to work on s390
From: Frank Blaschka frank.blasc...@de.ibm.com on s390 MSI-X irqs are presented as thin or adapter interrupts for this we have to reorganize the routing entry to contain valid information for the adapter interrupt code on s390. To minimize impact on existing code we introduce an architecture function to fixup the routing entry. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- include/sysemu/kvm.h | 4 kvm-all.c| 7 +++ target-arm/kvm.c | 6 ++ target-i386/kvm.c| 6 ++ target-mips/kvm.c| 6 ++ target-ppc/kvm.c | 6 ++ target-s390x/kvm.c | 26 ++ 7 files changed, 61 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 104cf35..30cb84d 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -158,6 +158,7 @@ extern bool kvm_readonly_mem_allowed; struct kvm_run; struct kvm_lapic_state; +struct kvm_irq_routing_entry; typedef struct KVMCapabilityInfo { const char *name; @@ -270,6 +271,9 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); + int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); diff --git a/kvm-all.c b/kvm-all.c index 18cc6b4..2f21a4e 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1225,6 +1225,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +kvm_irqchip_release_virq(s, virq); +return -EINVAL; +} kvm_add_routing_entry(s, kroute); kvm_irqchip_commit_routes(s); @@ -1250,6 +1254,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +return -EINVAL; +} return kvm_update_routing_entry(s, kroute); } diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 4d81f3d..23cefe9 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -548,3 +548,9 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f92edfe..54ccb89 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2733,3 +2733,9 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | KVM_DEV_IRQ_HOST_MSIX); } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-mips/kvm.c b/target-mips/kvm.c index a761ea5..b68191c 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -688,3 +688,9 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 6843fa0..04c83cd 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2388,3 +2388,9 @@ out_close: error_out: return; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a6849ab..89cc218 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -41,6 +41,7 @@ #include trace.h #include qapi-event.h #include hw/s390x/s390-pci-inst.h +#include hw/s390x/s390-pci-bus.h /* #define DEBUG_KVM */ @@ -1514,3 +1515,28 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +S390PCIBusDevice *pbdev; +uint32_t fid = data ZPCI_MSI_VEC_BITS; +uint32_t vec = data ZPCI_MSI_VEC_MASK; + +pbdev = s390_pci_find_dev_by_fid(fid); +if (!pbdev) { +DPRINTF(add_msi_route no dev\n); +return -ENODEV; +} + +pbdev-routes.adapter.ind_offset = vec; + +route-type = KVM_IRQ_ROUTING_S390_ADAPTER; +route-flags = 0; +route-u.adapter.summary_addr = pbdev-routes.adapter.summary_addr; +route-u.adapter.ind_addr = pbdev-routes.adapter.ind_addr; +route-u.adapter.summary_offset = pbdev
[Qemu-devel] [PATCH 1/3 V3] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- MAINTAINERS | 2 + default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 591 ++ hw/s390x/s390-pci-bus.h | 251 hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/ioinst.c | 52 target-s390x/ioinst.h | 1 + 12 files changed, 929 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/MAINTAINERS b/MAINTAINERS index 01cfb05..19c274b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -534,6 +534,7 @@ S390 Virtio M: Alexander Graf ag...@suse.de S: Maintained F: hw/s390x/s390-*.c +X: hw/s390x/*pci*.[hc] S390 Virtio-ccw M: Cornelia Huck cornelia.h...@de.ibm.com @@ -544,6 +545,7 @@ F: hw/s390x/s390-virtio-ccw.c F: hw/s390x/css.[hc] F: hw/s390x/sclp*.[hc] F: hw/s390x/ipl*.[hc] +F: hw/s390x/*pci*.[hc] F: include/hw/s390x/ F: pc-bios/s390-ccw/ T: git git://github.com/cohuck/qemu virtio-ccw-upstr diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 126d88d..6ee2ff8 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1ba6c3a..428d957 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..d0c5dde 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, cssid); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..5bebe96 --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,591 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include s390-pci-bus.h +#include hw/pci/pci_bus.h +#include hw/pci/msi.h +#include qemu/error-report.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +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; +} + +sei_cont = QTAILQ_FIRST(s-pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(s-pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +eccdf-e = cpu_to_be32(sei_cont-e); +eccdf-faddr = cpu_to_be64(sei_cont-faddr); +eccdf-pec = cpu_to_be16(sei_cont-pec); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32
[Qemu-devel] [PATCH 0/3 V3] add PCI support for the s390 platform
This set of patches implemets PCI support for the s390 platform. Now it is possible to run virtio-net-pci and potentially all virtual pci devices conforming to s390 platform constrains. V1 added lot of feedback from Alex Graf fixed tons of endian issues V2 added couple of small improvments and code cleanup fixed build on 32-bit and non Linux added pci to maintainer file V3 fix css_generate_css_crws to pass cssid to css_queue_crw fix and compile test w32 build review #defines for ULL usage patches apply to latest qemu master please consider for integration into 2.3 Thanks, Frank Frank Blaschka (3): s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 MAINTAINERS | 2 + default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 591 +++ hw/s390x/s390-pci-bus.h | 251 hw/s390x/s390-pci-inst.c | 811 ++ hw/s390x/s390-pci-inst.h | 288 ++ hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + include/sysemu/kvm.h | 4 + kvm-all.c | 7 + target-arm/kvm.c | 6 + target-i386/kvm.c | 6 + target-mips/kvm.c | 6 + target-ppc/kvm.c | 6 + target-s390x/ioinst.c | 52 +++ target-s390x/ioinst.h | 1 + target-s390x/kvm.c| 179 + 21 files changed, 2242 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h -- 2.1.4
Re: [Qemu-devel] [PULL v2 0/7] s390x patches for 2.3
On Wed, Jan 07, 2015 at 04:08:13PM +0100, Cornelia Huck wrote: On Sat, 20 Dec 2014 22:03:34 + Peter Maydell peter.mayd...@linaro.org wrote: On 18 December 2014 at 16:34, Cornelia Huck cornelia.h...@de.ibm.com wrote: Next try for s390x updates. The previous build failures should be fixed now. Still not building on w32, I'm afraid. I think most of this is run-on error from using __uint16_t c rather than uint16_t c. Sigh. Every time I try to set up a mingw build environment, I get lost in some library dependencies and give up. But yes, the __uint* stuff looks like some copypaste error from the respective Linux headers. I'll leave it to Frank to fix that up. ok, I'm working on a patch to fix this but I hate to go on this way and steel your time by let you compile test the changes. I do not have a windows build system available so I'm wondering if there is some kind of public infrastructure I can use to do a win build? Thx for any pointers and help ... You also have a bunch of 64 bit constants like the ZPCI_*_ADDR which need a trailing ULL, and also some with a UL which should probably be ULL. For instance in #define ZPCI_STE_FLAG_MASK 0x7ffUL #define ZPCI_STE_ADDR_MASK (~ZPCI_STE_FLAG_MASK) though ZPCI_STE_FLAG_MASK is OK by itself, when you use it in ZPCI_STE_ADDR_MASK you will get the logical-negate done at 32 bits before zero-extend to 64 bits, rather than a 64 bit negate. (I think that UL is almost never correct in QEMU -- you either want at least 32 bits, in which case U is sufficient, or you need 64 bits, in which case you need ULL.) That's probably also an artifact of grabbing the constants from Linux (where the code is 64 bit only). Some of those suffixes are provoking compiler warnings or errors below, but some of them will just be silent wrong behaviour, so you should probably eyeball the #defines... There are also some possibly dodgy places in non-pci code; I'll take a look at those as well.
[Qemu-devel] [PATCH 0/3 V2] add PCI support for the s390 platform
This set of patches implemets PCI support for the s390 platform. Now it is possible to run virtio-net-pci and potentially all virtual pci devices conforming to s390 platform constrains. V1 added lot of feedback from Alex Graf fixed tons of endian issues V2 added couple of small improvments and code cleanup fixed build on 32-bit and non Linux added pci to maintainer file Please consider for integration into 2.3 Thanks, Frank Frank Blaschka (3): s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 MAINTAINERS | 2 + default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 591 +++ hw/s390x/s390-pci-bus.h | 251 hw/s390x/s390-pci-inst.c | 811 ++ hw/s390x/s390-pci-inst.h | 288 ++ hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + include/sysemu/kvm.h | 4 + kvm-all.c | 7 + target-arm/kvm.c | 6 + target-i386/kvm.c | 6 + target-mips/kvm.c | 6 + target-ppc/kvm.c | 6 + target-s390x/ioinst.c | 52 +++ target-s390x/ioinst.h | 1 + target-s390x/kvm.c| 179 + 21 files changed, 2242 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h -- 1.8.5.5
[Qemu-devel] [PATCH 1/3 V2] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- MAINTAINERS | 2 + default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 591 ++ hw/s390x/s390-pci-bus.h | 251 hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/ioinst.c | 52 target-s390x/ioinst.h | 1 + 12 files changed, 929 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/MAINTAINERS b/MAINTAINERS index d72d6e3..790dfce 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -534,6 +534,7 @@ S390 Virtio M: Alexander Graf ag...@suse.de S: Maintained F: hw/s390x/s390-*.c +X: hw/s390x/*pci*.[hc] S390 Virtio-ccw M: Cornelia Huck cornelia.h...@de.ibm.com @@ -544,6 +545,7 @@ F: hw/s390x/s390-virtio-ccw.c F: hw/s390x/css.[hc] F: hw/s390x/sclp*.[hc] F: hw/s390x/ipl*.[hc] +F: hw/s390x/*pci*.[hc] F: include/hw/s390x/ F: pc-bios/s390-ccw/ T: git git://github.com/cohuck/qemu virtio-ccw-upstr diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 126d88d..6ee2ff8 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1ba6c3a..428d957 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..7553085 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..c9c06e6 --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,591 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include s390-pci-bus.h +#include hw/pci/pci_bus.h +#include hw/pci/msi.h +#include qemu/error-report.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +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; +} + +sei_cont = QTAILQ_FIRST(s-pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(s-pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +eccdf-e = cpu_to_be32(sei_cont-e); +eccdf-faddr = cpu_to_be64(sei_cont-faddr); +eccdf-pec = cpu_to_be16(sei_cont-pec); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont
[Qemu-devel] [PATCH 2/3 V2] s390: implement pci instructions
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/Makefile.objs | 2 +- hw/s390x/s390-pci-inst.c | 811 +++ hw/s390x/s390-pci-inst.h | 288 + target-s390x/kvm.c | 153 + 4 files changed, 1253 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 428d957..27cd75a 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,4 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o -obj-y += s390-pci-bus.o +obj-y += s390-pci-bus.o s390-pci-inst.o diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c new file mode 100644 index 000..d486cbb --- /dev/null +++ b/hw/s390x/s390-pci-inst.c @@ -0,0 +1,811 @@ +/* + * s390 PCI instructions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include s390-pci-inst.h +#include s390-pci-bus.h +#include exec/memory-internal.h +#include qemu/error-report.h + +/* #define DEBUG_S390PCI_INST */ +#ifdef DEBUG_S390PCI_INST +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, s390pci-inst: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static void s390_set_status_code(CPUS390XState *env, + uint8_t r, uint64_t status_code) +{ +env-regs[r] = ~0xff00ULL; +env-regs[r] |= (status_code 0xff) 24; +} + +static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) +{ +S390PCIBusDevice *pbdev; +uint32_t res_code, initial_l2, g_l2, finish; +int rc, idx; +uint64_t resume_token; + +rc = 0; +if (lduw_p(rrb-request.hdr.len) != 32) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) CLP_MASK_FMT) != 0) { +res_code = CLP_RC_FMT; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) ~CLP_MASK_FMT) != 0 || +ldq_p(rrb-request.reserved1) != 0 || +ldq_p(rrb-request.reserved2) != 0) { +res_code = CLP_RC_RESNOT0; +rc = -EINVAL; +goto out; +} + +resume_token = ldq_p(rrb-request.resume_token); + +if (resume_token) { +pbdev = s390_pci_find_dev_by_idx(resume_token); +if (!pbdev) { +res_code = CLP_RC_LISTPCI_BADRT; +rc = -EINVAL; +goto out; +} +} + +if (lduw_p(rrb-response.hdr.len) 48) { +res_code = CLP_RC_8K; +rc = -EINVAL; +goto out; +} + +initial_l2 = lduw_p(rrb-response.hdr.len); +if ((initial_l2 - LIST_PCI_HDR_LEN) % sizeof(ClpFhListEntry) +!= 0) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +*cc = 3; +goto out; +} + +stl_p(rrb-response.fmt, 0); +stq_p(rrb-response.reserved1, 0); +stq_p(rrb-response.reserved2, 0); +stl_p(rrb-response.mdd, FH_VIRT); +stw_p(rrb-response.max_fn, PCI_MAX_FUNCTIONS); +rrb-response.entry_size = sizeof(ClpFhListEntry); +finish = 0; +idx = resume_token; +g_l2 = LIST_PCI_HDR_LEN; +do { +pbdev = s390_pci_find_dev_by_idx(idx); +if (!pbdev) { +finish = 1; +break; +} +stw_p(rrb-response.fh_list[idx - resume_token].device_id, +pci_get_word(pbdev-pdev-config + PCI_DEVICE_ID)); +stw_p(rrb-response.fh_list[idx - resume_token].vendor_id, +pci_get_word(pbdev-pdev-config + PCI_VENDOR_ID)); +stl_p(rrb-response.fh_list[idx - resume_token].config, 0x8000); +stl_p(rrb-response.fh_list[idx - resume_token].fid, pbdev-fid); +stl_p(rrb-response.fh_list[idx - resume_token].fh, pbdev-fh); + +g_l2 += sizeof(ClpFhListEntry); +/* Add endian check for DPRINTF? */ +DPRINTF(g_l2 %d vendor id 0x%x device id 0x%x fid 0x%x fh 0x%x\n, +g_l2, +lduw_p(rrb-response.fh_list[idx - resume_token].vendor_id), +lduw_p(rrb-response.fh_list[idx - resume_token].device_id), +ldl_p(rrb-response.fh_list[idx - resume_token].fid), +ldl_p(rrb-response.fh_list[idx - resume_token].fh)); +idx++; +} while (g_l2 initial_l2); + +if (finish == 1) { +resume_token = 0
[Qemu-devel] [PATCH 3/3 V2] kvm: extend kvm_irqchip_add_msi_route to work on s390
From: Frank Blaschka frank.blasc...@de.ibm.com on s390 MSI-X irqs are presented as thin or adapter interrupts for this we have to reorganize the routing entry to contain valid information for the adapter interrupt code on s390. To minimize impact on existing code we introduce an architecture function to fixup the routing entry. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- include/sysemu/kvm.h | 4 kvm-all.c| 7 +++ target-arm/kvm.c | 6 ++ target-i386/kvm.c| 6 ++ target-mips/kvm.c| 6 ++ target-ppc/kvm.c | 6 ++ target-s390x/kvm.c | 26 ++ 7 files changed, 61 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 104cf35..30cb84d 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -158,6 +158,7 @@ extern bool kvm_readonly_mem_allowed; struct kvm_run; struct kvm_lapic_state; +struct kvm_irq_routing_entry; typedef struct KVMCapabilityInfo { const char *name; @@ -270,6 +271,9 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); + int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); diff --git a/kvm-all.c b/kvm-all.c index 18cc6b4..2f21a4e 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1225,6 +1225,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +kvm_irqchip_release_virq(s, virq); +return -EINVAL; +} kvm_add_routing_entry(s, kroute); kvm_irqchip_commit_routes(s); @@ -1250,6 +1254,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +return -EINVAL; +} return kvm_update_routing_entry(s, kroute); } diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 4d81f3d..23cefe9 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -548,3 +548,9 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f92edfe..54ccb89 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2733,3 +2733,9 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | KVM_DEV_IRQ_HOST_MSIX); } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-mips/kvm.c b/target-mips/kvm.c index a761ea5..b68191c 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -688,3 +688,9 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 6843fa0..04c83cd 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2388,3 +2388,9 @@ out_close: error_out: return; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a6849ab..89cc218 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -41,6 +41,7 @@ #include trace.h #include qapi-event.h #include hw/s390x/s390-pci-inst.h +#include hw/s390x/s390-pci-bus.h /* #define DEBUG_KVM */ @@ -1514,3 +1515,28 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +S390PCIBusDevice *pbdev; +uint32_t fid = data ZPCI_MSI_VEC_BITS; +uint32_t vec = data ZPCI_MSI_VEC_MASK; + +pbdev = s390_pci_find_dev_by_fid(fid); +if (!pbdev) { +DPRINTF(add_msi_route no dev\n); +return -ENODEV; +} + +pbdev-routes.adapter.ind_offset = vec; + +route-type = KVM_IRQ_ROUTING_S390_ADAPTER; +route-flags = 0; +route-u.adapter.summary_addr = pbdev-routes.adapter.summary_addr; +route-u.adapter.ind_addr = pbdev-routes.adapter.ind_addr; +route-u.adapter.summary_offset = pbdev
[Qemu-devel] [PATCH] s390/pci: fix build on 32-bit and non linux
From: Frank Blaschka frank.blasc...@de.ibm.com Remove unnecessary and wrong includes. Fix get_rt_sto and get_st_pto to build on 32-bit. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/s390-pci-bus.c | 25 +++-- hw/s390x/s390-pci-inst.c | 30 +++--- 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index c1b57d0..c9c06e6 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -11,13 +11,10 @@ * directory. */ -#include hw/pci/pci.h +#include s390-pci-bus.h #include hw/pci/pci_bus.h -#include hw/s390x/css.h -#include hw/s390x/sclp.h #include hw/pci/msi.h -#include qemu/error-report.h -#include s390-pci-bus.h +#include qemu/error-report.h /* #define DEBUG_S390PCI_BUS */ #ifdef DEBUG_S390PCI_BUS @@ -253,18 +250,18 @@ static unsigned int calc_px(dma_addr_t ptr) return ((unsigned long) ptr PAGE_SHIFT) ZPCI_PT_MASK; } -static unsigned long *get_rt_sto(unsigned long entry) +static uint64_t get_rt_sto(uint64_t entry) { return ((entry ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX) -? (unsigned long *) (entry ZPCI_RTE_ADDR_MASK) -: NULL; +? (entry ZPCI_RTE_ADDR_MASK) +: 0; } -static unsigned long *get_st_pto(unsigned long entry) +static uint64_t get_st_pto(uint64_t entry) { return ((entry ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX) -? (unsigned long *) (entry ZPCI_STE_ADDR_MASK) -: NULL; +? (entry ZPCI_STE_ADDR_MASK) +: 0; } static uint64_t s390_guest_io_table_walk(uint64_t guest_iota, @@ -280,7 +277,7 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota, sto_a = guest_iota + rtx * sizeof(uint64_t); sto = ldq_phys(address_space_memory, sto_a); -sto = (uint64_t)get_rt_sto(sto); +sto = get_rt_sto(sto); if (!sto) { pte = 0; goto out; @@ -288,7 +285,7 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota, pto_a = sto + sx * sizeof(uint64_t); pto = ldq_phys(address_space_memory, pto_a); -pto = (uint64_t)get_st_pto(pto); +pto = get_st_pto(pto); if (!pto) { pte = 0; goto out; @@ -322,7 +319,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, /* s390 does not have an APIC maped to main storage so we use * a separate AddressSpace only for msix notifications */ -if (addr == ZPCI_MSI_ADDR) { +if (((uint64_t)addr) == ZPCI_MSI_ADDR) { ret.target_as = s-msix_notify_as; ret.iova = addr; ret.translated_addr = addr; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 83ab60f..d486cbb 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -11,34 +11,10 @@ * directory. */ -#include sys/types.h -#include sys/ioctl.h -#include sys/mman.h - -#include linux/kvm.h -#include asm/ptrace.h -#include hw/pci/pci.h -#include hw/pci/pci_host.h -#include net/net.h - -#include qemu-common.h -#include qemu/timer.h -#include migration/qemu-file.h -#include sysemu/sysemu.h -#include sysemu/kvm.h -#include cpu.h -#include sysemu/device_tree.h -#include monitor/monitor.h #include s390-pci-inst.h - -#include hw/hw.h -#include hw/pci/pci.h -#include hw/pci/pci_bridge.h -#include hw/pci/pci_bus.h -#include hw/pci/pci_host.h -#include hw/s390x/s390-pci-bus.h -#include exec/exec-all.h -#include exec/memory-internal.h +#include s390-pci-bus.h +#include exec/memory-internal.h +#include qemu/error-report.h /* #define DEBUG_S390PCI_INST */ #ifdef DEBUG_S390PCI_INST -- 1.8.5.5
Re: [Qemu-devel] [PATCH] s390/pci: fix build on 32-bit and non linux
On Tue, Dec 16, 2014 at 11:35:19AM +0100, Alexander Graf wrote: Am 16.12.2014 um 10:28 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: From: Frank Blaschka frank.blasc...@de.ibm.com Remove unnecessary and wrong includes. Fix get_rt_sto and get_st_pto to build on 32-bit. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com Could you please roll the fixes into the offending patches and repost the set? Otherwise we break bisectability on 32bit hosts. Sure, but since this is an initial drop and I have to touch the patches anyhow can I merge all add-ons and fixes to the initial patch set? I would like to end up finally with just 3 patches: s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 If so I would post V2 of the initial patch set including all changes. Frank Alex
Re: [Qemu-devel] [PATCH] s390/pci: fix build on 32-bit and non linux
On Tue, Dec 16, 2014 at 12:56:58PM +0100, Alexander Graf wrote: On 16.12.14 12:46, Frank Blaschka wrote: On Tue, Dec 16, 2014 at 11:35:19AM +0100, Alexander Graf wrote: Am 16.12.2014 um 10:28 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: From: Frank Blaschka frank.blasc...@de.ibm.com Remove unnecessary and wrong includes. Fix get_rt_sto and get_st_pto to build on 32-bit. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com Could you please roll the fixes into the offending patches and repost the set? Otherwise we break bisectability on 32bit hosts. Sure, but since this is an initial drop and I have to touch the patches anyhow can I merge all add-ons and fixes to the initial patch set? I would like to end up finally with just 3 patches: s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 If so I would post V2 of the initial patch set including all changes. Cornelia is the maintainer here, so you'll need to ask her :). Anything that doesn't break bisectability is certainly better than code that breaks it. OK. Coni what do you prefere? By squashing all those patches together you'll make bisecting harder for s390 - if you can live with it so can I. Alex
Re: [Qemu-devel] [PATCH 2/2] s390/pci: implement stpcifc instruction
On Fri, Dec 05, 2014 at 02:15:07PM +0100, Thomas Huth wrote: Hi Frank, On Fri, 5 Dec 2014 10:19:59 +0100 Frank Blaschka blasc...@linux.vnet.ibm.com wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the last remaining s390 pci instruction to query the function information block. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/s390-pci-bus.h | 1 + hw/s390x/s390-pci-inst.c | 64 hw/s390x/s390-pci-inst.h | 1 + target-s390x/kvm.c | 9 +-- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 2a9f735..35f4da5 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -223,6 +223,7 @@ typedef struct S390PCIBusDevice { uint64_t g_iota; uint64_t pba; uint64_t pal; +uint64_t fmb_addr; uint8_t isc; uint16_t noi; uint8_t sum; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8648594..f503665 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -766,6 +766,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) pbdev-lgstg_blocked = false; break; case ZPCI_MOD_FC_SET_MEASURE: +pbdev-fmb_addr = ldq_p(fib.fmb_addr); break; default: program_interrupt(cpu-env, PGM_OPERAND, 6); @@ -775,3 +776,66 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) setcc(cpu, cc); return 0; } + +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) +{ +CPUS390XState *env = cpu-env; +uint32_t fh; +ZpciFib fib; +S390PCIBusDevice *pbdev; +uint32_t data; +uint64_t cc = ZPCI_PCI_LS_OK; + +cpu_synchronize_state(CPU(cpu)); You're calling cpu_synchronize_state twice, one time in kvm_stpcifc_service_call() already and one time here. So I think you could remove the call here. Hi Thomas, looks like this is not the only duplicate cpu_synchronize_state. Will create an add on patch to remove all unnecessary calls to cpu_synchronize_state. Thx for the finding. Frank +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 6); +return 0; +} + +fh = env-regs[r1] 32; + +if (fiba 0x7) { +program_interrupt(env, PGM_SPECIFICATION, 6); +return 0; +} + +pbdev = s390_pci_find_dev_by_fh(fh); +if (!pbdev) { +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +memset(fib, 0, sizeof(fib)); +stq_p(fib.pba, pbdev-pba); +stq_p(fib.pal, pbdev-pal); +stq_p(fib.iota, pbdev-g_iota); +stq_p(fib.aibv, pbdev-routes.adapter.ind_addr); +stq_p(fib.aisb, pbdev-routes.adapter.summary_addr); +stq_p(fib.fmb_addr, pbdev-fmb_addr); + +data = (pbdev-isc 28) | (pbdev-noi 16) | + (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | + pbdev-routes.adapter.summary_offset; +stw_p(fib.data, data); + +if (pbdev-fh ENABLE_BIT_OFFSET) { +fib.fc |= 0x80; +} + +if (pbdev-error_state) { +fib.fc |= 0x40; +} + +if (pbdev-lgstg_blocked) { +fib.fc |= 0x20; +} + +if (pbdev-g_iota) { +fib.fc |= 0x10; +} + +cpu_physical_memory_write(fiba, (uint8_t *)fib, sizeof(fib)); +setcc(cpu, cc); +return 0; +} diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 609e3e0..1c2f458 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -283,5 +283,6 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr); int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); #endif diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 32af46b..b70d482 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -876,8 +876,13 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run) static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run) { -qemu_log_mask(LOG_UNIMP, STPCIFC missing\n); -return 0; +uint8_t r1 = (run-s390_sieic.ipa 0x00f0) 4; +uint64_t fiba; + +cpu_synchronize_state(CPU(cpu)); +fiba = get_base_disp_rxy(cpu, run); + +return stpcifc_service_call(cpu, r1, fiba); } static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run)
[Qemu-devel] [PATCH] s390/pci: remove unnecessary cpu_synchronize_state
Remove all unnecessary calls to cpu_synchronize_state Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/s390x/s390-pci-inst.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index f503665..83ab60f 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -564,8 +564,6 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr) uint8_t pcias; uint8_t len; -cpu_synchronize_state(CPU(cpu)); - if (env-psw.mask PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, 6); return 0; @@ -711,8 +709,6 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) S390PCIBusDevice *pbdev; uint64_t cc = ZPCI_PCI_LS_OK; -cpu_synchronize_state(CPU(cpu)); - if (env-psw.mask PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, 6); return 0; @@ -786,8 +782,6 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) uint32_t data; uint64_t cc = ZPCI_PCI_LS_OK; -cpu_synchronize_state(CPU(cpu)); - if (env-psw.mask PSW_MASK_PSTATE) { program_interrupt(env, PGM_PRIVILEGED, 6); return 0; -- 1.8.5.5
[Qemu-devel] [PATCH 0/2] s390/pci: add 2 more features
Coni, Alex, Christian, here are 2 more s390/pci features on top of the base pci support. Thx! Frank Frank Blaschka (2): s390/pci: add error event support s390/pci: implement stpcifc instruction hw/s390x/s390-pci-bus.c | 50 ++-- hw/s390x/s390-pci-bus.h | 36 +++- hw/s390x/s390-pci-inst.c | 148 --- hw/s390x/s390-pci-inst.h | 1 + target-s390x/kvm.c | 9 ++- 5 files changed, 227 insertions(+), 17 deletions(-) -- 1.8.5.5
[Qemu-devel] [PATCH 1/2] s390/pci: add error event support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch adds support to generate s390 pci error events Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/s390-pci-bus.c | 50 +--- hw/s390x/s390-pci-bus.h | 35 +++- hw/s390x/s390-pci-inst.c | 86 ++-- 3 files changed, 155 insertions(+), 16 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 06d153a..c1b57d0 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -52,6 +52,9 @@ int chsc_sei_nt2_get_event(void *res) eccdf = (PciCcdfErr *)nt2_res-ccdf; eccdf-fid = cpu_to_be32(sei_cont-fid); eccdf-fh = cpu_to_be32(sei_cont-fh); +eccdf-e = cpu_to_be32(sei_cont-e); +eccdf-faddr = cpu_to_be64(sei_cont-faddr); +eccdf-pec = cpu_to_be16(sei_cont-pec); break; case 2: /* availability event */ accdf = (PciCcdfAvail *)nt2_res-ccdf; @@ -184,8 +187,8 @@ S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh) return NULL; } -static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh, - uint32_t fid) +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 = g_malloc0(sizeof(SeiContainer)); S390pciState *s = S390_PCI_HOST_BRIDGE( @@ -197,13 +200,28 @@ static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh, sei_cont-fh = fh; sei_cont-fid = fid; -sei_cont-cc = 2; +sei_cont-cc = cc; sei_cont-pec = pec; +sei_cont-faddr = faddr; +sei_cont-e = e; QTAILQ_INSERT_TAIL(s-pending_sei, sei_cont, link); css_generate_css_crws(0); } +static void s390_pci_generate_plug_event(uint16_t pec, uint32_t fh, + uint32_t fid) +{ +s390_pci_generate_event(2, pec, fh, fid, 0, 0); +} + +static void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, + uint32_t fid, uint64_t faddr, + uint32_t e) +{ +s390_pci_generate_event(1, pec, fh, fid, faddr, e); +} + static void s390_pci_set_irq(void *opaque, int irq, int level) { /* nothing to do */ @@ -313,10 +331,30 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, return ret; } +if (!pbdev-g_iota) { +pbdev-error_state = true; +pbdev-lgstg_blocked = true; +s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev-fh, pbdev-fid, + addr, 0); +return ret; +} + +if (addr pbdev-pba || addr pbdev-pal) { +pbdev-error_state = true; +pbdev-lgstg_blocked = true; +s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev-fh, pbdev-fid, + addr, 0); +return ret; +} + pte = s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev-g_iota), addr); if (!pte) { +pbdev-error_state = true; +pbdev-lgstg_blocked = true; +s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev-fh, pbdev-fid, + addr, ERR_EVENT_Q_BIT); return ret; } @@ -353,7 +391,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set) ind_addr = cpu_physical_memory_map(ind_loc, len, 1); if (!ind_addr) { -error_report(%s: unable to access indicator, __func__); +s390_pci_generate_error_event(ERR_EVENT_AIRERR, 0, 0, 0, 0); return -1; } do { @@ -374,12 +412,14 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, uint32_t vec = data ZPCI_MSI_VEC_MASK; uint64_t ind_bit; uint32_t sum_bit; +uint32_t e = 0; DPRINTF(write_msix data 0x%lx fid %d vec 0x%x\n, data, fid, vec); pbdev = s390_pci_find_dev_by_fid(fid); if (!pbdev) { -DPRINTF(msix_notify no dev\n); +e |= (vec ERR_EVENT_MVN_OFFSET); +s390_pci_generate_error_event(ERR_EVENT_NOMSI, 0, fid, addr, e); return; } diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index fc567b7..2a9f735 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -33,6 +33,31 @@ #define HP_EVENT_CONFIGURED_TO_STBRES 0x0304 #define HP_EVENT_STANDBY_TO_RESERVED 0x0308 +#define ERR_EVENT_INVALAS 0x1 +#define ERR_EVENT_OORANGE 0x2 +#define ERR_EVENT_INVALTF 0x3 +#define ERR_EVENT_TPROTE 0x4 +#define ERR_EVENT_APROTE 0x5 +#define ERR_EVENT_KEYE0x6 +#define ERR_EVENT_INVALTE 0x7 +#define ERR_EVENT_INVALTL 0x8 +#define ERR_EVENT_TT 0x9 +#define ERR_EVENT_INVALMS 0xa +#define ERR_EVENT_SERR0xb +#define ERR_EVENT_NOMSI 0x10 +#define
[Qemu-devel] [PATCH 2/2] s390/pci: implement stpcifc instruction
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the last remaining s390 pci instruction to query the function information block. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/s390-pci-bus.h | 1 + hw/s390x/s390-pci-inst.c | 64 hw/s390x/s390-pci-inst.h | 1 + target-s390x/kvm.c | 9 +-- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 2a9f735..35f4da5 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -223,6 +223,7 @@ typedef struct S390PCIBusDevice { uint64_t g_iota; uint64_t pba; uint64_t pal; +uint64_t fmb_addr; uint8_t isc; uint16_t noi; uint8_t sum; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8648594..f503665 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -766,6 +766,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) pbdev-lgstg_blocked = false; break; case ZPCI_MOD_FC_SET_MEASURE: +pbdev-fmb_addr = ldq_p(fib.fmb_addr); break; default: program_interrupt(cpu-env, PGM_OPERAND, 6); @@ -775,3 +776,66 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) setcc(cpu, cc); return 0; } + +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba) +{ +CPUS390XState *env = cpu-env; +uint32_t fh; +ZpciFib fib; +S390PCIBusDevice *pbdev; +uint32_t data; +uint64_t cc = ZPCI_PCI_LS_OK; + +cpu_synchronize_state(CPU(cpu)); + +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 6); +return 0; +} + +fh = env-regs[r1] 32; + +if (fiba 0x7) { +program_interrupt(env, PGM_SPECIFICATION, 6); +return 0; +} + +pbdev = s390_pci_find_dev_by_fh(fh); +if (!pbdev) { +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +memset(fib, 0, sizeof(fib)); +stq_p(fib.pba, pbdev-pba); +stq_p(fib.pal, pbdev-pal); +stq_p(fib.iota, pbdev-g_iota); +stq_p(fib.aibv, pbdev-routes.adapter.ind_addr); +stq_p(fib.aisb, pbdev-routes.adapter.summary_addr); +stq_p(fib.fmb_addr, pbdev-fmb_addr); + +data = (pbdev-isc 28) | (pbdev-noi 16) | + (pbdev-routes.adapter.ind_offset 8) | (pbdev-sum 7) | + pbdev-routes.adapter.summary_offset; +stw_p(fib.data, data); + +if (pbdev-fh ENABLE_BIT_OFFSET) { +fib.fc |= 0x80; +} + +if (pbdev-error_state) { +fib.fc |= 0x40; +} + +if (pbdev-lgstg_blocked) { +fib.fc |= 0x20; +} + +if (pbdev-g_iota) { +fib.fc |= 0x10; +} + +cpu_physical_memory_write(fiba, (uint8_t *)fib, sizeof(fib)); +setcc(cpu, cc); +return 0; +} diff --git a/hw/s390x/s390-pci-inst.h b/hw/s390x/s390-pci-inst.h index 609e3e0..1c2f458 100644 --- a/hw/s390x/s390-pci-inst.h +++ b/hw/s390x/s390-pci-inst.h @@ -283,5 +283,6 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2); int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr); int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); +int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba); #endif diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 32af46b..b70d482 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -876,8 +876,13 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run) static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run) { -qemu_log_mask(LOG_UNIMP, STPCIFC missing\n); -return 0; +uint8_t r1 = (run-s390_sieic.ipa 0x00f0) 4; +uint64_t fiba; + +cpu_synchronize_state(CPU(cpu)); +fiba = get_base_disp_rxy(cpu, run); + +return stpcifc_service_call(cpu, r1, fiba); } static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run) -- 1.8.5.5
[Qemu-devel] [PATCH 3/3 V1] kvm: extend kvm_irqchip_add_msi_route to work on s390
From: Frank Blaschka frank.blasc...@de.ibm.com on s390 MSI-X irqs are presented as thin or adapter interrupts for this we have to reorganize the routing entry to contain valid information for the adapter interrupt code on s390. To minimize impact on existing code we introduce an architecture function to fixup the routing entry. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- include/sysemu/kvm.h | 4 kvm-all.c| 7 +++ target-arm/kvm.c | 6 ++ target-i386/kvm.c| 6 ++ target-mips/kvm.c| 6 ++ target-ppc/kvm.c | 6 ++ target-s390x/kvm.c | 26 ++ 7 files changed, 61 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index b0cd657..702dc93 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -148,6 +148,7 @@ extern bool kvm_readonly_mem_allowed; struct kvm_run; struct kvm_lapic_state; +struct kvm_irq_routing_entry; typedef struct KVMCapabilityInfo { const char *name; @@ -259,6 +260,9 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); + int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); diff --git a/kvm-all.c b/kvm-all.c index 596e7ce..38589b3 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1208,6 +1208,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +kvm_irqchip_release_virq(s, virq); +return -EINVAL; +} kvm_add_routing_entry(s, kroute); kvm_irqchip_commit_routes(s); @@ -1233,6 +1237,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +return -EINVAL; +} return kvm_update_routing_entry(s, kroute); } diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 319784d..3285f81 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -441,3 +441,9 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ccf36e8..7bc818c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2707,3 +2707,9 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | KVM_DEV_IRQ_HOST_MSIX); } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-mips/kvm.c b/target-mips/kvm.c index 97fd51a..c7eb1dc 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -688,3 +688,9 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 6843fa0..04c83cd 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2388,3 +2388,9 @@ out_close: error_out: return; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 1b62257..32af46b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -41,6 +41,7 @@ #include trace.h #include qapi-event.h #include hw/s390x/s390-pci-inst.h +#include hw/s390x/s390-pci-bus.h /* #define DEBUG_KVM */ @@ -1510,3 +1511,28 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +S390PCIBusDevice *pbdev; +uint32_t fid = data ZPCI_MSI_VEC_BITS; +uint32_t vec = data ZPCI_MSI_VEC_MASK; + +pbdev = s390_pci_find_dev_by_fid(fid); +if (!pbdev) { +DPRINTF(add_msi_route no dev\n); +return -ENODEV; +} + +pbdev-routes.adapter.ind_offset = vec; + +route-type = KVM_IRQ_ROUTING_S390_ADAPTER; +route-flags = 0; +route-u.adapter.summary_addr = pbdev-routes.adapter.summary_addr; +route-u.adapter.ind_addr = pbdev-routes.adapter.ind_addr; +route-u.adapter.summary_offset = pbdev
[Qemu-devel] [PATCH 0/3 V1] add PCI support for the s390 platform
This set of patches implemets PCI support for the s390 platform. Now it is possible to run virtio-net-pci and potentially all virtual pci devices conforming to s390 platform constrains. V1 added lot of feedback from Alex Graf fixed tons of endian issues Please review and consider for integration into 2.3 Thanks, Frank Frank Blaschka (3): s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 554 + hw/s390x/s390-pci-bus.h | 217 hw/s390x/s390-pci-inst.c | 711 ++ hw/s390x/s390-pci-inst.h | 287 +++ hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + include/sysemu/kvm.h | 4 + kvm-all.c | 7 + target-arm/kvm.c | 6 + target-i386/kvm.c | 6 + target-mips/kvm.c | 6 + target-ppc/kvm.c | 6 + target-s390x/ioinst.c | 52 +++ target-s390x/ioinst.h | 1 + target-s390x/kvm.c| 174 ++ 20 files changed, 2063 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h -- 1.8.5.5
[Qemu-devel] [PATCH 1/3 V1] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 554 ++ hw/s390x/s390-pci-bus.h | 217 +++ hw/s390x/s390-virtio-ccw.c| 7 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/ioinst.c | 52 target-s390x/ioinst.h | 1 + 11 files changed, 856 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 126d88d..6ee2ff8 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1ba6c3a..428d957 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..7553085 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..06d153a --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,554 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +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; +} + +sei_cont = QTAILQ_FIRST(s-pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(s-pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont-fid); +accdf-fh = cpu_to_be32(sei_cont-fh); +accdf-pec = cpu_to_be16(sei_cont-pec); +break; +default: +abort(); +} +g_free(sei_cont); +rc = 0; +} + +return rc; +} + +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; +} + +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
[Qemu-devel] [PATCH 2/3 V1] s390: implement pci instructions
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/Makefile.objs | 2 +- hw/s390x/s390-pci-inst.c | 711 +++ hw/s390x/s390-pci-inst.h | 287 +++ target-s390x/kvm.c | 148 ++ 4 files changed, 1147 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-inst.c create mode 100644 hw/s390x/s390-pci-inst.h diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 428d957..27cd75a 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,4 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o -obj-y += s390-pci-bus.o +obj-y += s390-pci-bus.o s390-pci-inst.o diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c new file mode 100644 index 000..e233046 --- /dev/null +++ b/hw/s390x/s390-pci-inst.c @@ -0,0 +1,711 @@ +/* + * s390 PCI instructions + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include sys/types.h +#include sys/ioctl.h +#include sys/mman.h + +#include linux/kvm.h +#include asm/ptrace.h +#include hw/pci/pci.h +#include hw/pci/pci_host.h +#include net/net.h + +#include qemu-common.h +#include qemu/timer.h +#include migration/qemu-file.h +#include sysemu/sysemu.h +#include sysemu/kvm.h +#include cpu.h +#include sysemu/device_tree.h +#include monitor/monitor.h +#include s390-pci-inst.h + +#include hw/hw.h +#include hw/pci/pci.h +#include hw/pci/pci_bridge.h +#include hw/pci/pci_bus.h +#include hw/pci/pci_host.h +#include hw/s390x/s390-pci-bus.h +#include exec/exec-all.h +#include exec/memory-internal.h + +/* #define DEBUG_S390PCI_INST */ +#ifdef DEBUG_S390PCI_INST +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, s390pci-inst: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static void s390_set_status_code(CPUS390XState *env, + uint8_t r, uint64_t status_code) +{ +env-regs[r] = ~0xff00ULL; +env-regs[r] |= (status_code 0xff) 24; +} + +static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) +{ +S390PCIBusDevice *pbdev; +uint32_t res_code, initial_l2, g_l2, finish; +int rc, idx; +uint64_t resume_token; + +rc = 0; +if (lduw_p(rrb-request.hdr.len) != 32) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) CLP_MASK_FMT) != 0) { +res_code = CLP_RC_FMT; +rc = -EINVAL; +goto out; +} + +if ((ldl_p(rrb-request.fmt) ~CLP_MASK_FMT) != 0 || +ldq_p(rrb-request.reserved1) != 0 || +ldq_p(rrb-request.reserved2) != 0) { +res_code = CLP_RC_RESNOT0; +rc = -EINVAL; +goto out; +} + +resume_token = ldq_p(rrb-request.resume_token); + +if (resume_token) { +pbdev = s390_pci_find_dev_by_idx(resume_token); +if (!pbdev) { +res_code = CLP_RC_LISTPCI_BADRT; +rc = -EINVAL; +goto out; +} +} + +if (lduw_p(rrb-response.hdr.len) 48) { +res_code = CLP_RC_8K; +rc = -EINVAL; +goto out; +} + +initial_l2 = lduw_p(rrb-response.hdr.len); +if ((initial_l2 - LIST_PCI_HDR_LEN) % sizeof(ClpFhListEntry) +!= 0) { +res_code = CLP_RC_LEN; +rc = -EINVAL; +*cc = 3; +goto out; +} + +stl_p(rrb-response.fmt, 0); +stq_p(rrb-response.reserved1, 0); +stq_p(rrb-response.reserved2, 0); +stl_p(rrb-response.mdd, FH_VIRT); +stw_p(rrb-response.max_fn, PCI_MAX_FUNCTIONS); +rrb-response.entry_size = sizeof(ClpFhListEntry); +finish = 0; +idx = resume_token; +g_l2 = LIST_PCI_HDR_LEN; +do { +pbdev = s390_pci_find_dev_by_idx(idx); +if (!pbdev) { +finish = 1; +break; +} +stw_p(rrb-response.fh_list[idx - resume_token].device_id, +pci_get_word(pbdev-pdev-config + PCI_DEVICE_ID)); +stw_p(rrb-response.fh_list[idx - resume_token].vendor_id, +pci_get_word(pbdev-pdev-config + PCI_VENDOR_ID)); +stl_p(rrb-response.fh_list[idx - resume_token].config, 0x8000); +stl_p(rrb-response.fh_list[idx - resume_token].fid, pbdev-fid); +stl_p(rrb-response.fh_list[idx - resume_token].fh, pbdev-fh); + +g_l2 += sizeof(ClpFhListEntry
Re: [Qemu-devel] [PATCH 1/3] s390: Add PCI bus support
On Tue, Nov 18, 2014 at 06:00:40PM +0100, Alexander Graf wrote: On 18.11.14 13:50, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:14:16PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com [...] diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..f2fa6ba --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,485 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); Please get rid of all statics ;). All state has to live in objects. be_to_le was misleading and unnecesary will remove this one but static QTAILQ_HEAD seems to be a common practice for list anchors. If you really want me to change this do you have any prefered way, or can you point me to some code doing this? For PCI devices, I don't think you need a list at all. Your PHB device should already have a proper qbus that knows about all its child devices. OK As for pending_sei, what is this about? This is a queue to store events (StoreEventInformation) used for hotplug support. In case a device is pluged/unpluged an event is stored to this queue and the guest is notified. Then the guest pick up the event information via chsc instruction. + +int chsc_sei_nt2_get_event(void *res) [...] + +int chsc_sei_nt2_get_event(void *res); +int chsc_sei_nt2_have_event(void); +void s390_pci_sclp_configure(int configure, SCCB *sccb); +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); I think it makes sense to pass the PHB device as parameter on these. Don't assume you only have one. We need to lookup our device mainly in the instruction handlers and there we do not have a PHB available. Then have a way to find your PHB - either put a variable into the machine object, or find it by path via QOM tree lookups. Maybe we need multiple PHBs, identified by part of the ID? I know too little about the way PCI works on s390x to really tell. Again, are there specs? Yes there are, but unfortunately they are not public. Also having one list for our S390PCIBusDevices devices does not prevent us from supporting more PHBs. +void s390_pci_bus_init(void); +uint64_t s390_pci_get_table_origin(uint64_t iota); +uint64_t s390_guest_io_table_walk(uint64_t guest_iota, + uint64_t guest_dma_address); Why are these exported? + +#endif diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index bc4dc2a..2e25834 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -18,6 +18,7 @@ #include css.h #include virtio-ccw.h #include qemu/config-file.h +#include s390-pci-bus.h #define TYPE_S390_CCW_MACHINE s390-ccw-machine @@ -127,6 +128,8 @@ static void ccw_init(MachineState *machine) machine-initrd_filename, s390-ccw.img); s390_flic_init(); +s390_pci_bus_init(); Please just inline that function here. What do you mean by just inline? The contents of the s390_pci_bus_init() function should just be standing right here. There's no value in creating a public wrapper function for initialization. We only did this back in the old days before qdev was around, because initialization was difficult back then and some devices didn't make the jump to get rid of their public init functions. + /* register
Re: [Qemu-devel] [PATCH 1/3] s390: Add PCI bus support
On Tue, Nov 25, 2014 at 01:14:01PM +0100, Alexander Graf wrote: On 25.11.14 11:11, Frank Blaschka wrote: On Tue, Nov 18, 2014 at 06:00:40PM +0100, Alexander Graf wrote: On 18.11.14 13:50, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:14:16PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com [...] diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..f2fa6ba --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,485 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); Please get rid of all statics ;). All state has to live in objects. be_to_le was misleading and unnecesary will remove this one but static QTAILQ_HEAD seems to be a common practice for list anchors. If you really want me to change this do you have any prefered way, or can you point me to some code doing this? For PCI devices, I don't think you need a list at all. Your PHB device should already have a proper qbus that knows about all its child devices. OK As for pending_sei, what is this about? This is a queue to store events (StoreEventInformation) used for hotplug support. In case a device is pluged/unpluged an event is stored to this queue and the guest is notified. Then the guest pick up the event information via chsc instruction. Is this for overall CCW or only for PCI? Depending on the answer, you can put the sei event list into the respective parent device. An NT2 event is pci specific. So I moved the queue for NT2 events to the PHB as well. Alex
Re: [Qemu-devel] [PATCH 1/3] s390: Add PCI bus support
On Mon, Nov 10, 2014 at 04:14:16PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 485 ++ hw/s390x/s390-pci-bus.h | 254 hw/s390x/s390-virtio-ccw.c| 3 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/ioinst.c | 52 target-s390x/ioinst.h | 1 + 11 files changed, 820 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 126d88d..6ee2ff8 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1ba6c3a..428d957 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..7553085 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..f2fa6ba --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,485 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); Please get rid of all statics ;). All state has to live in objects. be_to_le was misleading and unnecesary will remove this one but static QTAILQ_HEAD seems to be a common practice for list anchors. If you really want me to change this do you have any prefered way, or can you point me to some code doing this? + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +PciCcdfErr *eccdf; +int rc = 1; +SeiContainer *sei_cont; + +sei_cont = QTAILQ_FIRST(pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Tue, Nov 11, 2014 at 04:24:24PM +0100, Alexander Graf wrote: On 11.11.14 15:08, Frank Blaschka wrote: On Tue, Nov 11, 2014 at 01:51:25PM +0100, Alexander Graf wrote: Am 11.11.2014 um 13:39 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Tue, Nov 11, 2014 at 01:16:04PM +0100, Alexander Graf wrote: On 11.11.14 13:10, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 753 + target-s390x/pci_ic.h | 335 4 files changed, 1141 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h [...] +int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run) +{ +CPUS390XState *env = cpu-env; +S390PCIBusDevice *pbdev; +uint8_t r1 = (run-s390_sieic.ipb 0x00f0) 20; +uint8_t r2 = (run-s390_sieic.ipb 0x000f) 16; +PciLgStg *rp; +uint64_t offset; +uint64_t data; +uint8_t len; + +cpu_synchronize_state(CPU(cpu)); + +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 4); +return 0; +} + +if (r2 0x1) { +program_interrupt(env, PGM_SPECIFICATION, 4); +return 0; +} + +rp = (PciLgStg *)env-regs[r2]; +offset = env-regs[r2 + 1]; + +pbdev = s390_pci_find_dev_by_fh(rp-fh); +if (!pbdev) { +DPRINTF(pcilg no pci dev\n); +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +len = rp-len 0xF; +if (rp-pcias 6) { +if ((8 - (offset 0x7)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +MemoryRegion *mr = pbdev-pdev-io_regions[rp-pcias].memory; +io_mem_read(mr, offset, data, len); +} else if (rp-pcias == 15) { +if ((4 - (offset 0x3)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +data = pci_host_config_read_common( + pbdev-pdev, offset, pci_config_size(pbdev-pdev), len); + +switch (len) { +case 1: +break; +case 2: +data = cpu_to_le16(data); +break; +case 4: +data = cpu_to_le32(data); +break; +case 8: +data = cpu_to_le64(data); +break; Why? Also, this is wrong. cpu_to_le64 convert between host endianness and LE. So if you're running this on an LE host, you won't swap the value and get a broken result. If you know that the value is always swapped, use bswapxx(). Actually the code is right and required for a big endian host :-) pcilg/pcistg provide access to the PCI config space which is defined as PCI byte order (little endian). Since pci_host_config_read_common does already a le to cpu conversion we have to convert back to PCI byte order. Doing an unconditional swap would be a bug on a little endian host. Why would it be a bug? The value you end up writing is contents of a register and thus doesn't have endianness. So if QEMU was an LE process, No, the s390 guest executing pcilg instruction expects to receive config space data in PCI byte order. the value of data would be identical as on a BE QEMU before your swab. After the swab, it would be bswap'ed on BE, but not LE. So LE hosts break. Again on BE endian host we do the swap because of pci_host_config_read_common does read the value and do a byte swap for that value, but we need PCI byte order not BE here. On LE host pci_host_config_read_common does not do a byte swap so we do not have to convert back to PCI byte order. We maintain the PCI config space always in LE byte order in memory, that's why there is a bwap in its read function. The return result of the read function however is always the same, regardless of LE or BE host. If I do a read of size 4, I will always get 0x1, not 0x0100 returned. So now you need to convert that 0x1 into a 0x0100 manually here because some architect thought that registers have endianness (which they don't). But you need to do it always, even on an LE host, because the pci config space return value is identical on LE and BE. so you
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Wed, Nov 12, 2014 at 10:08:19AM +0100, Alexander Graf wrote: On 12.11.14 09:49, Frank Blaschka wrote: On Tue, Nov 11, 2014 at 04:24:24PM +0100, Alexander Graf wrote: On 11.11.14 15:08, Frank Blaschka wrote: On Tue, Nov 11, 2014 at 01:51:25PM +0100, Alexander Graf wrote: Am 11.11.2014 um 13:39 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Tue, Nov 11, 2014 at 01:16:04PM +0100, Alexander Graf wrote: On 11.11.14 13:10, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 753 + target-s390x/pci_ic.h | 335 4 files changed, 1141 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h [...] +int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run) +{ +CPUS390XState *env = cpu-env; +S390PCIBusDevice *pbdev; +uint8_t r1 = (run-s390_sieic.ipb 0x00f0) 20; +uint8_t r2 = (run-s390_sieic.ipb 0x000f) 16; +PciLgStg *rp; +uint64_t offset; +uint64_t data; +uint8_t len; + +cpu_synchronize_state(CPU(cpu)); + +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 4); +return 0; +} + +if (r2 0x1) { +program_interrupt(env, PGM_SPECIFICATION, 4); +return 0; +} + +rp = (PciLgStg *)env-regs[r2]; +offset = env-regs[r2 + 1]; + +pbdev = s390_pci_find_dev_by_fh(rp-fh); +if (!pbdev) { +DPRINTF(pcilg no pci dev\n); +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +len = rp-len 0xF; +if (rp-pcias 6) { +if ((8 - (offset 0x7)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +MemoryRegion *mr = pbdev-pdev-io_regions[rp-pcias].memory; +io_mem_read(mr, offset, data, len); +} else if (rp-pcias == 15) { +if ((4 - (offset 0x3)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +data = pci_host_config_read_common( + pbdev-pdev, offset, pci_config_size(pbdev-pdev), len); + +switch (len) { +case 1: +break; +case 2: +data = cpu_to_le16(data); +break; +case 4: +data = cpu_to_le32(data); +break; +case 8: +data = cpu_to_le64(data); +break; Why? Also, this is wrong. cpu_to_le64 convert between host endianness and LE. So if you're running this on an LE host, you won't swap the value and get a broken result. If you know that the value is always swapped, use bswapxx(). Actually the code is right and required for a big endian host :-) pcilg/pcistg provide access to the PCI config space which is defined as PCI byte order (little endian). Since pci_host_config_read_common does already a le to cpu conversion we have to convert back to PCI byte order. Doing an unconditional swap would be a bug on a little endian host. Why would it be a bug? The value you end up writing is contents of a register and thus doesn't have endianness. So if QEMU was an LE process, No, the s390 guest executing pcilg instruction expects to receive config space data in PCI byte order. the value of data would be identical as on a BE QEMU before your swab. After the swab, it would be bswap'ed on BE, but not LE. So LE hosts break. Again on BE endian host we do the swap because of pci_host_config_read_common does read the value and do a byte swap for that value, but we need PCI byte order not BE here. On LE host pci_host_config_read_common does not do a byte swap so we do not have to convert back to PCI byte order. We maintain the PCI config space always in LE byte order in memory, that's why there is a bwap in its read function. The return result of the read function however is always the same, regardless of LE or BE host. If I do a read of size 4, I will always get 0x1, not 0x0100 returned. So now you need to convert that 0x1 into a 0x0100 manually here because some architect thought that registers have endianness (which they don't). But you
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Wed, Nov 12, 2014 at 10:36:03AM +0100, Paolo Bonzini wrote: On 12/11/2014 10:22, Alexander Graf wrote: Absolutely lets make an example for qemu running on BE and LE byte orderconfig space backing pci_default_read_config pcilg (with cpu_to_le) BE0x78563412 0x123456780x78563412 LE0x78563412 0x785634120x78563412 No, pci_default_read_config() always returns 0x12345678 because it returns a register, not memory. You mean implementation of pci_default_read_config is broken? If it should return a register it should not do return le32_to_cpu(val); It has to, to convert from memory (after memcpy) to an actual register value. Look at the value list in Paolo's email - I really have no idea how to explain it any better. pci_default_read_config is reading from a *device* register, and has absolutely zero knowledge of the host CPU endianness. Another way to explain that the result of pci_default_read_config is independent of the host endianness, is that the function is basically doing this: switch (len) { case 1: return d-config[address]; case 2: return ldw_le_p(d-config[address)]); case 4: return ldl_le_p(d-config[address)]); default: abort(); } So if you want to make the outcome big endian, you have to swap unconditionally. Paolo Hi Paolo, Alex, thx a lot for all the explanation and patience. I think I have understand your point now. I will change the code to unconditional swap. I feel I had a knowledge gap regarding running guest and host which different byte orders. Hope this gap is filled now ;) Frank
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 753 + target-s390x/pci_ic.h | 335 4 files changed, 1141 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 2c57494..cc71400 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -2,4 +2,4 @@ obj-y += translate.o helper.o cpu.o interrupt.o obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pci_ic.o diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 5b10a25..d59e740 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -40,6 +40,7 @@ #include exec/gdbstub.h #include trace.h #include qapi-event.h +#include pci_ic.h /* #define DEBUG_KVM */ @@ -56,6 +57,7 @@ #define IPA0_B2 0xb200 #define IPA0_B9 0xb900 #define IPA0_EB 0xeb00 +#define IPA0_E3 0xe300 #define PRIV_B2_SCLP_CALL 0x20 #define PRIV_B2_CSCH0x30 @@ -76,8 +78,17 @@ #define PRIV_B2_XSCH0x76 #define PRIV_EB_SQBS0x8a +#define PRIV_EB_PCISTB 0xd0 +#define PRIV_EB_SIC 0xd1 #define PRIV_B9_EQBS0x9c +#define PRIV_B9_CLP 0xa0 +#define PRIV_B9_PCISTG 0xd0 +#define PRIV_B9_PCILG 0xd2 +#define PRIV_B9_RPCIT 0xd3 + +#define PRIV_E3_MPCIFC 0xd0 +#define PRIV_E3_STPCIFC 0xd4 #define DIAG_IPL0x308 #define DIAG_KVM_HYPERCALL 0x500 @@ -814,6 +825,18 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) int r = 0; switch (ipa1) { +case PRIV_B9_CLP: +r = kvm_clp_service_call(cpu, run); +break; +case PRIV_B9_PCISTG: +r = kvm_pcistg_service_call(cpu, run); +break; +case PRIV_B9_PCILG: +r = kvm_pcilg_service_call(cpu, run); +break; +case PRIV_B9_RPCIT: +r = kvm_rpcit_service_call(cpu, run); +break; case PRIV_B9_EQBS: /* just inject exception */ r = -1; @@ -832,6 +855,12 @@ static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) int r = 0; switch (ipa1) { +case PRIV_EB_PCISTB: +r = kvm_pcistb_service_call(cpu, run); +break; +case PRIV_EB_SIC: +r = kvm_sic_service_call(cpu, run); +break; case PRIV_EB_SQBS: /* just inject exception */ r = -1; @@ -845,6 +874,26 @@ static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) return r; } +static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl) +{ +int r = 0; + +switch (ipbl) { +case PRIV_E3_MPCIFC: +r = kvm_mpcifc_service_call(cpu, run); +break; +case PRIV_E3_STPCIFC: +r = kvm_stpcifc_service_call(cpu, run); +break; +default: +r = -1; +DPRINTF(KVM: unhandled PRIV: 0xe3%x\n, ipbl); +break; +} + +return r; +} + static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { CPUS390XState *env = cpu-env; @@ -1041,6 +1090,9 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) case IPA0_EB: r = handle_eb(cpu, run, ipa1); break; +case IPA0_E3: +r = handle_e3(cpu, run, run-s390_sieic.ipb 0xff); +break; case IPA0_DIAG: r = handle_diag(cpu, run, run-s390_sieic.ipb); break; diff --git a/target-s390x/pci_ic.c b/target-s390x/pci_ic.c new file mode 100644 index 000..6c05faf --- /dev/null +++ b/target-s390x/pci_ic.c @@ -0,0 +1,753 @@ +/* + * s390 PCI intercepts + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Tue, Nov 11, 2014 at 01:16:04PM +0100, Alexander Graf wrote: On 11.11.14 13:10, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 753 + target-s390x/pci_ic.h | 335 4 files changed, 1141 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h [...] +int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run) +{ +CPUS390XState *env = cpu-env; +S390PCIBusDevice *pbdev; +uint8_t r1 = (run-s390_sieic.ipb 0x00f0) 20; +uint8_t r2 = (run-s390_sieic.ipb 0x000f) 16; +PciLgStg *rp; +uint64_t offset; +uint64_t data; +uint8_t len; + +cpu_synchronize_state(CPU(cpu)); + +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 4); +return 0; +} + +if (r2 0x1) { +program_interrupt(env, PGM_SPECIFICATION, 4); +return 0; +} + +rp = (PciLgStg *)env-regs[r2]; +offset = env-regs[r2 + 1]; + +pbdev = s390_pci_find_dev_by_fh(rp-fh); +if (!pbdev) { +DPRINTF(pcilg no pci dev\n); +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +len = rp-len 0xF; +if (rp-pcias 6) { +if ((8 - (offset 0x7)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +MemoryRegion *mr = pbdev-pdev-io_regions[rp-pcias].memory; +io_mem_read(mr, offset, data, len); +} else if (rp-pcias == 15) { +if ((4 - (offset 0x3)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +data = pci_host_config_read_common( + pbdev-pdev, offset, pci_config_size(pbdev-pdev), len); + +switch (len) { +case 1: +break; +case 2: +data = cpu_to_le16(data); +break; +case 4: +data = cpu_to_le32(data); +break; +case 8: +data = cpu_to_le64(data); +break; Why? Also, this is wrong. cpu_to_le64 convert between host endianness and LE. So if you're running this on an LE host, you won't swap the value and get a broken result. If you know that the value is always swapped, use bswapxx(). Actually the code is right and required for a big endian host :-) pcilg/pcistg provide access to the PCI config space which is defined as PCI byte order (little endian). Since pci_host_config_read_common does already a le to cpu conversion we have to convert back to PCI byte order. Doing an unconditional swap would be a bug on a little endian host. Why would it be a bug? The value you end up writing is contents of a register and thus doesn't have endianness. So if QEMU was an LE process, No, the s390 guest executing pcilg instruction expects to receive config space data in PCI byte order. the value of data would be identical as on a BE QEMU before your swab. After the swab, it would be bswap'ed on BE, but not LE. So LE hosts break. Again on BE endian host we do the swap because of pci_host_config_read_common does read the value and do a byte swap for that value, but we need PCI byte order not BE here. On LE host pci_host_config_read_common does not do a byte swap so we do not have to convert back to PCI byte order. Alex
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Tue, Nov 11, 2014 at 12:17:17PM +, Peter Maydell wrote: On 11 November 2014 12:10, Frank Blaschka blasc...@linux.vnet.ibm.com wrote: On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: +static uint8_t barsize(uint64_t size) +{ +uint64_t mask = 1; +int i; + +if (!size) { +return 0; +} + +for (i = 0; i 64; i++) { +if (size mask) { +break; +} +mask = (mask 1); +} + +return i; +} Isn't there an existing helper for this in the PCI layer? Did not find one, this function is used to fill a s390 specific len in an instruction intercept (architecture specific encoding of the len). If you do need to implement this here then you should probably be using ctz64(). I think what you have here is equivalent to return size ? ctz64(size) : 0; but you should check that. will do thx! thanks -- PMM
Re: [Qemu-devel] [PATCH 2/3] s390: implement pci instructions
On Tue, Nov 11, 2014 at 01:51:25PM +0100, Alexander Graf wrote: Am 11.11.2014 um 13:39 schrieb Frank Blaschka blasc...@linux.vnet.ibm.com: On Tue, Nov 11, 2014 at 01:16:04PM +0100, Alexander Graf wrote: On 11.11.14 13:10, Frank Blaschka wrote: On Mon, Nov 10, 2014 at 04:56:21PM +0100, Alexander Graf wrote: On 10.11.14 15:20, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 753 + target-s390x/pci_ic.h | 335 4 files changed, 1141 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h [...] +int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run) +{ +CPUS390XState *env = cpu-env; +S390PCIBusDevice *pbdev; +uint8_t r1 = (run-s390_sieic.ipb 0x00f0) 20; +uint8_t r2 = (run-s390_sieic.ipb 0x000f) 16; +PciLgStg *rp; +uint64_t offset; +uint64_t data; +uint8_t len; + +cpu_synchronize_state(CPU(cpu)); + +if (env-psw.mask PSW_MASK_PSTATE) { +program_interrupt(env, PGM_PRIVILEGED, 4); +return 0; +} + +if (r2 0x1) { +program_interrupt(env, PGM_SPECIFICATION, 4); +return 0; +} + +rp = (PciLgStg *)env-regs[r2]; +offset = env-regs[r2 + 1]; + +pbdev = s390_pci_find_dev_by_fh(rp-fh); +if (!pbdev) { +DPRINTF(pcilg no pci dev\n); +setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); +return 0; +} + +len = rp-len 0xF; +if (rp-pcias 6) { +if ((8 - (offset 0x7)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +MemoryRegion *mr = pbdev-pdev-io_regions[rp-pcias].memory; +io_mem_read(mr, offset, data, len); +} else if (rp-pcias == 15) { +if ((4 - (offset 0x3)) len) { +program_interrupt(env, PGM_OPERAND, 4); +return 0; +} +data = pci_host_config_read_common( + pbdev-pdev, offset, pci_config_size(pbdev-pdev), len); + +switch (len) { +case 1: +break; +case 2: +data = cpu_to_le16(data); +break; +case 4: +data = cpu_to_le32(data); +break; +case 8: +data = cpu_to_le64(data); +break; Why? Also, this is wrong. cpu_to_le64 convert between host endianness and LE. So if you're running this on an LE host, you won't swap the value and get a broken result. If you know that the value is always swapped, use bswapxx(). Actually the code is right and required for a big endian host :-) pcilg/pcistg provide access to the PCI config space which is defined as PCI byte order (little endian). Since pci_host_config_read_common does already a le to cpu conversion we have to convert back to PCI byte order. Doing an unconditional swap would be a bug on a little endian host. Why would it be a bug? The value you end up writing is contents of a register and thus doesn't have endianness. So if QEMU was an LE process, No, the s390 guest executing pcilg instruction expects to receive config space data in PCI byte order. the value of data would be identical as on a BE QEMU before your swab. After the swab, it would be bswap'ed on BE, but not LE. So LE hosts break. Again on BE endian host we do the swap because of pci_host_config_read_common does read the value and do a byte swap for that value, but we need PCI byte order not BE here. On LE host pci_host_config_read_common does not do a byte swap so we do not have to convert back to PCI byte order. We maintain the PCI config space always in LE byte order in memory, that's why there is a bwap in its read function. The return result of the read function however is always the same, regardless of LE or BE host. If I do a read of size 4, I will always get 0x1, not 0x0100 returned. So now you need to convert that 0x1 into a 0x0100 manually here because some architect thought that registers have endianness (which they don't). But you need to do it always, even on an LE host, because the pci config space return value is identical on LE and BE. so you tell me pci_host_config_read_common does not end up in pci_default_read_config? uint32_t
[Qemu-devel] [PATCH 3/3] kvm: extend kvm_irqchip_add_msi_route to work on s390
From: Frank Blaschka frank.blasc...@de.ibm.com on s390 MSI-X irqs are presented as thin or adapter interrupts for this we have to reorganize the routing entry to contain valid information for the adapter interrupt code on s390. To minimize impact on existing code we introduce an architecture function to fixup the routing entry. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- include/sysemu/kvm.h | 4 kvm-all.c| 7 +++ target-arm/kvm.c | 6 ++ target-i386/kvm.c| 6 ++ target-mips/kvm.c| 6 ++ target-ppc/kvm.c | 6 ++ target-s390x/kvm.c | 26 ++ 7 files changed, 61 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index b0cd657..702dc93 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -148,6 +148,7 @@ extern bool kvm_readonly_mem_allowed; struct kvm_run; struct kvm_lapic_state; +struct kvm_irq_routing_entry; typedef struct KVMCapabilityInfo { const char *name; @@ -259,6 +260,9 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); + int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); diff --git a/kvm-all.c b/kvm-all.c index 44a5e72..7556d3f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1206,6 +1206,10 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +kvm_irqchip_release_virq(s, virq); +return -EINVAL; +} kvm_add_routing_entry(s, kroute); kvm_irqchip_commit_routes(s); @@ -1231,6 +1235,9 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +if (kvm_arch_fixup_msi_route(kroute, msg.address, msg.data)) { +return -EINVAL; +} return kvm_update_routing_entry(s, kroute); } diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 319784d..3285f81 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -441,3 +441,9 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ccf36e8..7bc818c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2707,3 +2707,9 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | KVM_DEV_IRQ_HOST_MSIX); } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-mips/kvm.c b/target-mips/kvm.c index 97fd51a..c7eb1dc 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -688,3 +688,9 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 6843fa0..04c83cd 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2388,3 +2388,9 @@ out_close: error_out: return; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +return 0; +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index d59e740..a08641b 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -41,6 +41,7 @@ #include trace.h #include qapi-event.h #include pci_ic.h +#include hw/s390x/s390-pci-bus.h /* #define DEBUG_KVM */ @@ -1414,3 +1415,28 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) return ret; } + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +S390PCIBusDevice *pbdev; +uint32_t fid = data ZPCI_MSI_VEC_BITS; +uint32_t vec = data ZPCI_MSI_VEC_MASK; + +pbdev = s390_pci_find_dev_by_fid(fid); +if (!pbdev) { +DPRINTF(add_msi_route no dev\n); +return -ENODEV; +} + +pbdev-routes.adapter.ind_offset = vec; + +route-type = KVM_IRQ_ROUTING_S390_ADAPTER; +route-flags = 0; +route-u.adapter.summary_addr = pbdev-routes.adapter.summary_addr; +route-u.adapter.ind_addr = pbdev-routes.adapter.ind_addr; +route-u.adapter.summary_offset = pbdev
[Qemu-devel] [PATCH 0/3] add PCI support for the s390 platform
This set of patches implemets PCI support for the s390 platform. Now it is possible to run virtio-net-pci and potentially all virtual pci devices conforming to s390 platform constrains. Please review and consider for integration into 2.3 Thanks, Frank Blaschka (3): s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 485 hw/s390x/s390-pci-bus.h | 254 + hw/s390x/s390-virtio-ccw.c| 3 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + include/sysemu/kvm.h | 4 + kvm-all.c | 7 + target-arm/kvm.c | 6 + target-i386/kvm.c | 6 + target-mips/kvm.c | 6 + target-ppc/kvm.c | 6 + target-s390x/Makefile.objs| 2 +- target-s390x/ioinst.c | 52 +++ target-s390x/ioinst.h | 1 + target-s390x/kvm.c| 78 target-s390x/pci_ic.c | 753 ++ target-s390x/pci_ic.h | 335 + 21 files changed, 2022 insertions(+), 2 deletions(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h -- 1.8.5.5
[Qemu-devel] [PATCH 1/3] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 485 ++ hw/s390x/s390-pci-bus.h | 254 hw/s390x/s390-virtio-ccw.c| 3 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/ioinst.c | 52 target-s390x/ioinst.h | 1 + 11 files changed, 820 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index 126d88d..6ee2ff8 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 1ba6c3a..428d957 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..7553085 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..f2fa6ba --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,485 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +PciCcdfErr *eccdf; +int rc = 1; +SeiContainer *sei_cont; + +sei_cont = QTAILQ_FIRST(pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont-fid); +accdf-fh = cpu_to_be32(sei_cont-fh); +accdf-pec = cpu_to_be16(sei_cont-pec); +break; +default: +abort(); +} +g_free(sei_cont); +rc = 0; +} + +return rc; +} + +int chsc_sei_nt2_have_event(void) +{ +return !QTAILQ_EMPTY(pending_sei); +} + +S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) +{ +S390PCIBusDevice *pbdev; + +QTAILQ_FOREACH(pbdev, device_list, next) { +if (pbdev-fid == fid) { +return pbdev
Re: [Qemu-devel] [PATCH] vfio: check if host device supports INTx
On Thu, Oct 23, 2014 at 08:26:51AM -0600, Alex Williamson wrote: On Thu, 2014-10-23 at 10:21 +0200, Frank Blaschka wrote: On Wed, Oct 22, 2014 at 11:17:11AM -0600, Alex Williamson wrote: On Wed, 2014-10-22 at 17:13 +0200, Frank Blaschka wrote: From: Frank Blaschka frank.blasc...@de.ibm.com Let the kernel announce if INTx is available. Yes, there are platforms (e.g. s390) which do not support INTx. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/misc/vfio.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index d66f3d2..3e9600b 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -109,6 +109,7 @@ typedef struct VFIOVGA { } VFIOVGA; typedef struct VFIOINTx { +bool available; /* intx available */ bool pending; /* interrupt pending */ bool kvm_accel; /* set when QEMU bypass through KVM enabled */ uint8_t pin; /* which pin to pull for qemu_set_irq */ @@ -554,7 +555,7 @@ static int vfio_enable_intx(VFIODevice *vdev) struct vfio_irq_set *irq_set; int32_t *pfd; -if (!pin) { +if (!pin || !vdev-intx.available) { return 0; } @@ -4032,6 +4033,21 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) vdev-host.function); } +irq_info.index = VFIO_PCI_INTX_IRQ_INDEX; +ret = ioctl(vdev-fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info); +if (ret) { +/* + * This can fail for an old kernel or legacy PCI dev + * we assume intx is available + */ Is this true? It's unfortunately from an ABI stability standpoint that we weren't calling this, but the ioctl should have always been there and worked. I'd rather error out here than add a fallback if this is just ok paranoia. Note that SR-IOV VFs will also report count=0 but their IRQ pin register will read 0. We do also have the option to virtualize the IRQ pin register for s390 devices which would make them look the same as sounds interesting, can you elaborate a little bit more on this? At what point can we hook in and modify the pci device config space? Untested, but I think it would be something like this: This is great, works perfect and there is no need to do any qemu vfio changes anymore. You can forget about this patch. Thx, Frank --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -609,6 +609,10 @@ static int __init init_pci_cap_basic_perm(struct perm_bits /* Sometimes used by sw, just virtualize */ p_setb(perm, PCI_INTERRUPT_LINE, (u8)ALL_VIRT, (u8)ALL_WRITE); + + /* Virtualize interrupt pin to allow hiding INTx */ + p_setb(perm, PCI_INTERRUPT_PIN, (u8)ALL_VIRT, (u8)NO_WRITE); + return 0; } @@ -1445,6 +1449,9 @@ int vfio_config_init(struct vfio_pci_device *vdev) *(__le16 *)vconfig[PCI_DEVICE_ID] = cpu_to_le16(pdev-device); } + if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX)) + vconfig[PCI_INTERRUPT_PIN] = 0; + ret = vfio_cap_init(vdev); if (ret) goto out;
[Qemu-devel] [PATCH 3/3 RPC] kvm: extend kvm_irqchip_add_msi_route to work on s390
From: Frank Blaschka frank.blasc...@de.ibm.com on s390 MSI-X irqs are presented as thin or adapter interrupts for this we have to reorganize the routing entry to contain valid information for the adapter interrupt code on s390. To minimize impact on existing code we introduce an architecture function to fixup the routing entry. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- include/sysemu/kvm.h | 4 kvm-all.c| 2 ++ target-arm/kvm.c | 5 + target-i386/kvm.c| 5 + target-mips/kvm.c| 5 + target-ppc/kvm.c | 5 + target-s390x/kvm.c | 25 + 7 files changed, 51 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 77ee240..d4c89c3 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -148,6 +148,7 @@ extern bool kvm_readonly_mem_allowed; struct kvm_run; struct kvm_lapic_state; +struct kvm_irq_routing_entry; typedef struct KVMCapabilityInfo { const char *name; @@ -261,6 +262,9 @@ int kvm_arch_on_sigbus(int code, void *addr); void kvm_arch_init_irq_routing(KVMState *s); +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data); + int kvm_set_irq(KVMState *s, int irq, int level); int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); diff --git a/kvm-all.c b/kvm-all.c index 682420b..965c888 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1198,6 +1198,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +kvm_arch_fixup_msi_route(kroute, msg.address, msg.data); kvm_add_routing_entry(s, kroute); kvm_irqchip_commit_routes(s); @@ -1223,6 +1224,7 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) kroute.u.msi.address_lo = (uint32_t)msg.address; kroute.u.msi.address_hi = msg.address 32; kroute.u.msi.data = le32_to_cpu(msg.data); +kvm_arch_fixup_msi_route(kroute, msg.address, msg.data); return kvm_update_routing_entry(s, kroute); } diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 319784d..5204c48 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -441,3 +441,8 @@ int kvm_arch_irqchip_create(KVMState *s) return 0; } + +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +} diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ddedc73..5e80ecd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -2688,3 +2688,8 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id) return kvm_deassign_irq_internal(s, dev_id, KVM_DEV_IRQ_GUEST_MSIX | KVM_DEV_IRQ_HOST_MSIX); } + +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +} diff --git a/target-mips/kvm.c b/target-mips/kvm.c index 97fd51a..fe34eb2 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -688,3 +688,8 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +} diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 9c23c6b..55627b9 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -2388,3 +2388,8 @@ out_close: error_out: return; } + +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +} diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 9280132..c3b3b0f 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -43,6 +43,7 @@ #include trace.h #include qapi-event.h #include pci_ic.h +#include hw/s390x/s390-pci-bus.h /* #define DEBUG_KVM */ @@ -1639,3 +1640,27 @@ int kvm_s390_get_machine_props(S390MachineProps *prop) { return cpu_model_get(KVM_S390_VM_CPU_MACHINE, (uint64_t) prop); } + +void kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data) +{ +S390PCIBusDevice *pbdev; +uint32_t fid = data ZPCI_MSI_VEC_BITS; +uint32_t vec = data ZPCI_MSI_VEC_MASK; + +pbdev = s390_pci_find_dev_by_fid(fid); +if (!pbdev) { +DPRINTF(add_msi_route no dev\n); +return; +} + +pbdev-routes.adapter.ind_offset = vec; + +route-type = KVM_IRQ_ROUTING_S390_ADAPTER; +route-flags = 0; +route-u.adapter.summary_addr = pbdev-routes.adapter.summary_addr; +route-u.adapter.ind_addr = pbdev-routes.adapter.ind_addr; +route-u.adapter.summary_offset = pbdev-routes.adapter.summary_offset; +route-u.adapter.ind_offset = pbdev-routes.adapter.ind_offset; +route-u.adapter.adapter_id = pbdev-routes.adapter.adapter_id
[Qemu-devel] [PATCH 1/3 RFC] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with infrastructure to generate and handle hotplug events, to configure/unconfigure via sclp instruction, to do iommu translations and provide s390 support for MSI/MSI-X notification processing. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 447 ++ hw/s390x/s390-pci-bus.h | 252 + hw/s390x/s390-virtio-ccw.c| 3 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + target-s390x/cpu-models.h | 8 +- target-s390x/ioinst.c | 52 + target-s390x/ioinst.h | 1 + 12 files changed, 787 insertions(+), 2 deletions(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak index a683760..db9284f 100644 --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index dc03e1d..921e255 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,4 +8,5 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-y += s390-pci-bus.o obj-$(CONFIG_S390_CONFIG) += config.o diff --git a/hw/s390x/css.c b/hw/s390x/css.c index b67c039..7553085 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1299,6 +1299,11 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid) /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); diff --git a/hw/s390x/css.h b/hw/s390x/css.h index 33104ac..7e53148 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -101,6 +101,7 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid); void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c new file mode 100644 index 000..f612108 --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,447 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_bus.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +PciCcdfErr *eccdf; +int rc = 1; +SeiContainer *sei_cont; + +sei_cont = QTAILQ_FIRST(pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont-fid); +accdf-fh = cpu_to_be32(sei_cont-fh); +accdf-pec = cpu_to_be16(sei_cont-pec); +break; +default: +abort(); +} +g_free(sei_cont); +rc = 0; +} + +return rc; +} + +int chsc_sei_nt2_have_event(void) +{ +return !QTAILQ_EMPTY(pending_sei); +} + +S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) +{ +S390PCIBusDevice *pbdev; + +QTAILQ_FOREACH(pbdev, device_list, next
[Qemu-devel] [PATCH 0/3 RFC] add PCI support for the s390 platform
This set of patches implemets PCI support for the s390 platform. Now it is possible to run virtio-net-pci and potentially all virtual pci devices conforming to s390 platform constrains. (In parallel I also post some changes to make vfio run on s390) I hope to get feedback and guidance especially for kvm: extend kvm_irqchip_add_msi_route to work on s390 which adds the s390 interpretation of MSI-X to the common kvm add_msi_route functionality. Thx for any help, Frank Frank Blaschka (3): s390: Add PCI bus support s390: implement pci instructions kvm: extend kvm_irqchip_add_msi_route to work on s390 default-configs/s390x-softmmu.mak | 1 + hw/s390x/Makefile.objs| 1 + hw/s390x/css.c| 5 + hw/s390x/css.h| 1 + hw/s390x/s390-pci-bus.c | 447 +++ hw/s390x/s390-pci-bus.h | 252 + hw/s390x/s390-virtio-ccw.c| 3 + hw/s390x/sclp.c | 10 +- include/hw/s390x/sclp.h | 8 + include/sysemu/kvm.h | 4 + kvm-all.c | 2 + target-arm/kvm.c | 5 + target-i386/kvm.c | 5 + target-mips/kvm.c | 5 + target-ppc/kvm.c | 5 + target-s390x/Makefile.objs| 2 +- target-s390x/cpu-models.h | 8 +- target-s390x/ioinst.c | 52 +++ target-s390x/ioinst.h | 1 + target-s390x/kvm.c| 77 target-s390x/pci_ic.c | 735 ++ target-s390x/pci_ic.h | 316 22 files changed, 1942 insertions(+), 3 deletions(-) create mode 100644 hw/s390x/s390-pci-bus.c create mode 100644 hw/s390x/s390-pci-bus.h create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h -- 1.8.5.5
[Qemu-devel] [PATCH 2/3 RFC] s390: implement pci instructions
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. It allows to access and drive pci devices attached to the s390 pci bus. Because of platform constrains devices using IO BARs are not supported. Also a device has to support MSI/MSI-X to run on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs | 2 +- target-s390x/kvm.c | 52 target-s390x/pci_ic.c | 735 + target-s390x/pci_ic.h | 316 +++ 4 files changed, 1104 insertions(+), 1 deletion(-) create mode 100644 target-s390x/pci_ic.c create mode 100644 target-s390x/pci_ic.h diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs index 9f55140..b99849e 100644 --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -3,4 +3,4 @@ obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o obj-y += cpu-models.o obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pci_ic.o diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 467f452..9280132 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -42,6 +42,7 @@ #include exec/gdbstub.h #include trace.h #include qapi-event.h +#include pci_ic.h /* #define DEBUG_KVM */ @@ -58,6 +59,7 @@ #define IPA0_B2 0xb200 #define IPA0_B9 0xb900 #define IPA0_EB 0xeb00 +#define IPA0_E3 0xe300 #define PRIV_B2_SCLP_CALL 0x20 #define PRIV_B2_CSCH0x30 @@ -78,8 +80,17 @@ #define PRIV_B2_XSCH0x76 #define PRIV_EB_SQBS0x8a +#define PRIV_EB_PCISTB 0xd0 +#define PRIV_EB_SIC 0xd1 #define PRIV_B9_EQBS0x9c +#define PRIV_B9_CLP 0xa0 +#define PRIV_B9_PCISTG 0xd0 +#define PRIV_B9_PCILG 0xd2 +#define PRIV_B9_RPCIT 0xd3 + +#define PRIV_E3_MPCIFC 0xd0 +#define PRIV_E3_STPCIFC 0xd4 #define DIAG_IPL0x308 #define DIAG_KVM_HYPERCALL 0x500 @@ -923,6 +934,18 @@ static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) int r = 0; switch (ipa1) { +case PRIV_B9_CLP: +r = kvm_clp_service_call(cpu, run); +break; +case PRIV_B9_PCISTG: +r = kvm_pcistg_service_call(cpu, run); +break; +case PRIV_B9_PCILG: +r = kvm_pcilg_service_call(cpu, run); +break; +case PRIV_B9_RPCIT: +r = kvm_rpcit_service_call(cpu, run); +break; case PRIV_B9_EQBS: /* just inject exception */ r = -1; @@ -941,6 +964,12 @@ static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl) int r = 0; switch (ipbl) { +case PRIV_EB_PCISTB: +r = kvm_pcistb_service_call(cpu, run); +break; +case PRIV_EB_SIC: +r = kvm_sic_service_call(cpu, run); +break; case PRIV_EB_SQBS: /* just inject exception */ r = -1; @@ -954,6 +983,26 @@ static int handle_eb(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl) return r; } +static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipbl) +{ +int r = 0; + +switch (ipbl) { +case PRIV_E3_MPCIFC: +r = kvm_mpcifc_service_call(cpu, run); +break; +case PRIV_E3_STPCIFC: +r = kvm_stpcifc_service_call(cpu, run); +break; +default: +r = -1; +DPRINTF(KVM: unhandled PRIV: 0xe3%x\n, ipbl); +break; +} + +return r; +} + static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { CPUS390XState *env = cpu-env; @@ -1150,6 +1199,9 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) case IPA0_EB: r = handle_eb(cpu, run, run-s390_sieic.ipb 0xff); break; +case IPA0_E3: +r = handle_e3(cpu, run, run-s390_sieic.ipb 0xff); +break; case IPA0_DIAG: r = handle_diag(cpu, run, run-s390_sieic.ipb); break; diff --git a/target-s390x/pci_ic.c b/target-s390x/pci_ic.c new file mode 100644 index 000..a496e6b --- /dev/null +++ b/target-s390x/pci_ic.c @@ -0,0 +1,735 @@ +/* + * s390 PCI intercepts + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include sys/types.h +#include sys/ioctl.h +#include sys/mman.h + +#include linux/kvm.h +#include asm/ptrace.h +#include hw/pci/pci.h +#include hw/pci/pci_host.h +#include
[Qemu-devel] [PATCH] vfio: check if host device supports INTx
From: Frank Blaschka frank.blasc...@de.ibm.com Let the kernel announce if INTx is available. Yes, there are platforms (e.g. s390) which do not support INTx. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/misc/vfio.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index d66f3d2..3e9600b 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -109,6 +109,7 @@ typedef struct VFIOVGA { } VFIOVGA; typedef struct VFIOINTx { +bool available; /* intx available */ bool pending; /* interrupt pending */ bool kvm_accel; /* set when QEMU bypass through KVM enabled */ uint8_t pin; /* which pin to pull for qemu_set_irq */ @@ -554,7 +555,7 @@ static int vfio_enable_intx(VFIODevice *vdev) struct vfio_irq_set *irq_set; int32_t *pfd; -if (!pin) { +if (!pin || !vdev-intx.available) { return 0; } @@ -4032,6 +4033,21 @@ static int vfio_get_device(VFIOGroup *group, const char *name, VFIODevice *vdev) vdev-host.function); } +irq_info.index = VFIO_PCI_INTX_IRQ_INDEX; +ret = ioctl(vdev-fd, VFIO_DEVICE_GET_IRQ_INFO, irq_info); +if (ret) { +/* + * This can fail for an old kernel or legacy PCI dev + * we assume intx is available + */ +vdev-intx.available = true; +ret = 0; +} else if (irq_info.count == 0) { +vdev-intx.available = false; +} else { +vdev-intx.available = true; +} + error: if (ret) { QLIST_REMOVE(vdev, next); -- 1.8.5.5
[Qemu-devel] [PATCH] vfio: fix adding memory listener to the right address space
Depending on the device, container-space-as contains the valid AddressSpace. Using address_space_memory breaks devices sitting behind an iommu (and using a separate address space). Signed-off-by: Frank Blaschka blasc...@linux.vnet.ibm.com --- hw/misc/vfio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index d66f3d2..fcc1958 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -3703,7 +3703,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) container-iommu_data.release = vfio_listener_release; memory_listener_register(container-iommu_data.type1.listener, - address_space_memory); + container-space-as); if (container-iommu_data.type1.error) { ret = container-iommu_data.type1.error; -- 1.8.5.5
Re: [Qemu-devel] [RFC patch 0/6] vfio based pci pass-through for qemu/KVM on s390
On Wed, Oct 01, 2014 at 11:26:51AM -0600, Alex Williamson wrote: On Wed, 2014-10-01 at 11:11 +0200, Frank Blaschka wrote: On Fri, Sep 26, 2014 at 01:59:40PM -0600, Alex Williamson wrote: On Fri, 2014-09-26 at 08:45 +0200, Frank Blaschka wrote: On Wed, Sep 24, 2014 at 10:05:57AM -0600, Alex Williamson wrote: On Wed, 2014-09-24 at 10:47 +0200, Frank Blaschka wrote: On Mon, Sep 22, 2014 at 02:47:31PM -0600, Alex Williamson wrote: On Fri, 2014-09-19 at 13:54 +0200, frank.blasc...@de.ibm.com wrote: This set of patches implements a vfio based solution for pci pass-through on the s390 platform. The kernel stuff is pretty much straight forward, but qemu needs more work. Most interesting patch is: vfio: make vfio run on s390 platform I hope Alex Alex can give me some guidance how to do the changes in an appropriate way. After creating a separate iommmu address space for each attached PCI device I can successfully run the vfio type1 iommu. So If we could extend type1 not registering all guest memory (see patch) I think we do not need a special vfio iommu for s390 for the moment. The patches implement the base pass-through support. s390 specific virtualization functions are currently not included. This would be a second step after the base support is done. kernel patches apply to linux-kvm-next KVM: s390: Enable PCI instructions iommu: add iommu for s390 platform vfio: make vfio build on s390 qemu patches apply to qemu-master s390: Add PCI bus support s390: implement pci instruction vfio: make vfio run on s390 platform Thx for feedback and review comments Sending patches as attachments makes it difficult to comment inline. Sorry, don't understand this. I sent every patch as separate email so you can comment directly on the patch. What do you prefer? The patches in each email are showing up as attachments in my mail client. Is it just me? 2/6 - careful of the namespace as you're changing functions from static and exporting them - doesn't seem like functions need to be exported, just non-static to call from s390-iommu.c Ok, will change this. 6/6 - We shouldn't need to globally disable mmap, each VFIO region reports whether it supports mmap and vfio-pci on s390 should indicate mmap is not supported on the platform. Yes, this is even better to let the kernel announce a BAR can not be mmap'ed. Checking the kernel code I realized the BARs are valid for mmap'ing but the s390 platform does simply not allow this. So I feal we have to introduce a platform switch in kernel. How about this ... --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -377,9 +377,11 @@ static long vfio_pci_ioctl(void *device_ info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; +#ifndef CONFIG_S390 if (pci_resource_flags(pdev, info.index) IORESOURCE_MEM info.size = PAGE_SIZE) info.flags |= VFIO_REGION_INFO_FLAG_MMAP; +#endif break; case VFIO_PCI_ROM_REGION_INDEX: { Maybe pull it out into a function. Also, is there some capability or feature we can test rather than just the architecture? I'd prefer it to be excluded because of a platform feature that prevents it rather than the overall architecture itself. Ok, understand this. There is no capability of feature so I will go with the function. - INTx should be done the same way, the interrupt index for INTx should report 0 count. The current code likely doesn't handle this, but it should be easy to fix. The current code is fine. Problem is the card reports an interrupt index (PCI_INTERRUPT_PIN) but again the platform does not support INTx at all. So we need a platform switch as well. Yep, let's try to do something consistent with the MMAP testing. Do you mean let the kernel announce this also? Yes, the kernel reports a count of 0 in vfio_irq_info when the interrupt type is not supported. We do this for MSI/X already, but it's assumed that INTx is always present since it's part of what most platforms would consider the minimal feature set
Re: [Qemu-devel] [RFC patch 0/6] vfio based pci pass-through for qemu/KVM on s390
On Fri, Sep 26, 2014 at 01:59:40PM -0600, Alex Williamson wrote: On Fri, 2014-09-26 at 08:45 +0200, Frank Blaschka wrote: On Wed, Sep 24, 2014 at 10:05:57AM -0600, Alex Williamson wrote: On Wed, 2014-09-24 at 10:47 +0200, Frank Blaschka wrote: On Mon, Sep 22, 2014 at 02:47:31PM -0600, Alex Williamson wrote: On Fri, 2014-09-19 at 13:54 +0200, frank.blasc...@de.ibm.com wrote: This set of patches implements a vfio based solution for pci pass-through on the s390 platform. The kernel stuff is pretty much straight forward, but qemu needs more work. Most interesting patch is: vfio: make vfio run on s390 platform I hope Alex Alex can give me some guidance how to do the changes in an appropriate way. After creating a separate iommmu address space for each attached PCI device I can successfully run the vfio type1 iommu. So If we could extend type1 not registering all guest memory (see patch) I think we do not need a special vfio iommu for s390 for the moment. The patches implement the base pass-through support. s390 specific virtualization functions are currently not included. This would be a second step after the base support is done. kernel patches apply to linux-kvm-next KVM: s390: Enable PCI instructions iommu: add iommu for s390 platform vfio: make vfio build on s390 qemu patches apply to qemu-master s390: Add PCI bus support s390: implement pci instruction vfio: make vfio run on s390 platform Thx for feedback and review comments Sending patches as attachments makes it difficult to comment inline. Sorry, don't understand this. I sent every patch as separate email so you can comment directly on the patch. What do you prefer? The patches in each email are showing up as attachments in my mail client. Is it just me? 2/6 - careful of the namespace as you're changing functions from static and exporting them - doesn't seem like functions need to be exported, just non-static to call from s390-iommu.c Ok, will change this. 6/6 - We shouldn't need to globally disable mmap, each VFIO region reports whether it supports mmap and vfio-pci on s390 should indicate mmap is not supported on the platform. Yes, this is even better to let the kernel announce a BAR can not be mmap'ed. Checking the kernel code I realized the BARs are valid for mmap'ing but the s390 platform does simply not allow this. So I feal we have to introduce a platform switch in kernel. How about this ... --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -377,9 +377,11 @@ static long vfio_pci_ioctl(void *device_ info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; +#ifndef CONFIG_S390 if (pci_resource_flags(pdev, info.index) IORESOURCE_MEM info.size = PAGE_SIZE) info.flags |= VFIO_REGION_INFO_FLAG_MMAP; +#endif break; case VFIO_PCI_ROM_REGION_INDEX: { Maybe pull it out into a function. Also, is there some capability or feature we can test rather than just the architecture? I'd prefer it to be excluded because of a platform feature that prevents it rather than the overall architecture itself. Ok, understand this. There is no capability of feature so I will go with the function. - INTx should be done the same way, the interrupt index for INTx should report 0 count. The current code likely doesn't handle this, but it should be easy to fix. The current code is fine. Problem is the card reports an interrupt index (PCI_INTERRUPT_PIN) but again the platform does not support INTx at all. So we need a platform switch as well. Yep, let's try to do something consistent with the MMAP testing. Do you mean let the kernel announce this also? Yes, the kernel reports a count of 0 in vfio_irq_info when the interrupt type is not supported. We do this for MSI/X already, but it's assumed that INTx is always present since it's part of what most platforms would consider the minimal feature set. - s390_msix_notify() vs msix_notify() should be abstracted somewhere Platform does not have have an apic so there is nothing we could emulate in qemu to make the existing msix_notify() work. else. How would an emulated PCI device with MSI-X support work? - same for add_msi_route Same here, we have to setup an adapter route due to the fact MSIX notifications are delivered as adapter/thin IRQs on the platform
Re: [Qemu-devel] [RFC patch 0/6] vfio based pci pass-through for qemu/KVM on s390
On Wed, Sep 24, 2014 at 10:05:57AM -0600, Alex Williamson wrote: On Wed, 2014-09-24 at 10:47 +0200, Frank Blaschka wrote: On Mon, Sep 22, 2014 at 02:47:31PM -0600, Alex Williamson wrote: On Fri, 2014-09-19 at 13:54 +0200, frank.blasc...@de.ibm.com wrote: This set of patches implements a vfio based solution for pci pass-through on the s390 platform. The kernel stuff is pretty much straight forward, but qemu needs more work. Most interesting patch is: vfio: make vfio run on s390 platform I hope Alex Alex can give me some guidance how to do the changes in an appropriate way. After creating a separate iommmu address space for each attached PCI device I can successfully run the vfio type1 iommu. So If we could extend type1 not registering all guest memory (see patch) I think we do not need a special vfio iommu for s390 for the moment. The patches implement the base pass-through support. s390 specific virtualization functions are currently not included. This would be a second step after the base support is done. kernel patches apply to linux-kvm-next KVM: s390: Enable PCI instructions iommu: add iommu for s390 platform vfio: make vfio build on s390 qemu patches apply to qemu-master s390: Add PCI bus support s390: implement pci instruction vfio: make vfio run on s390 platform Thx for feedback and review comments Sending patches as attachments makes it difficult to comment inline. Sorry, don't understand this. I sent every patch as separate email so you can comment directly on the patch. What do you prefer? The patches in each email are showing up as attachments in my mail client. Is it just me? 2/6 - careful of the namespace as you're changing functions from static and exporting them - doesn't seem like functions need to be exported, just non-static to call from s390-iommu.c Ok, will change this. 6/6 - We shouldn't need to globally disable mmap, each VFIO region reports whether it supports mmap and vfio-pci on s390 should indicate mmap is not supported on the platform. Yes, this is even better to let the kernel announce a BAR can not be mmap'ed. Checking the kernel code I realized the BARs are valid for mmap'ing but the s390 platform does simply not allow this. So I feal we have to introduce a platform switch in kernel. How about this ... --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -377,9 +377,11 @@ static long vfio_pci_ioctl(void *device_ info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; +#ifndef CONFIG_S390 if (pci_resource_flags(pdev, info.index) IORESOURCE_MEM info.size = PAGE_SIZE) info.flags |= VFIO_REGION_INFO_FLAG_MMAP; +#endif break; case VFIO_PCI_ROM_REGION_INDEX: { Maybe pull it out into a function. Also, is there some capability or feature we can test rather than just the architecture? I'd prefer it to be excluded because of a platform feature that prevents it rather than the overall architecture itself. Ok, understand this. There is no capability of feature so I will go with the function. - INTx should be done the same way, the interrupt index for INTx should report 0 count. The current code likely doesn't handle this, but it should be easy to fix. The current code is fine. Problem is the card reports an interrupt index (PCI_INTERRUPT_PIN) but again the platform does not support INTx at all. So we need a platform switch as well. Yep, let's try to do something consistent with the MMAP testing. Do you mean let the kernel announce this also? - s390_msix_notify() vs msix_notify() should be abstracted somewhere Platform does not have have an apic so there is nothing we could emulate in qemu to make the existing msix_notify() work. else. How would an emulated PCI device with MSI-X support work? - same for add_msi_route Same here, we have to setup an adapter route due to the fact MSIX notifications are delivered as adapter/thin IRQs on the platform. Any suggestion or idea how a better abstraction could look like? With all the platform constraints I was not able to find a suitable emulated device. Remember s390: - does not support IO BARs - does not support INTx only MSIX What about MSI (non-X)? In theory MSI should work also but I have not seen in reality. - in reality currently there is only a PCI network card available On the physical hardware? yes - platform does not support fancy I/O like usb or audio :-) So we don't even have kernel (host and guest) support for this kind of devices. Does that mean you couldn't
Re: [Qemu-devel] [RFC patch 5/6] s390: implement pci instruction
On Fri, Sep 19, 2014 at 05:12:15PM +0200, Thomas Huth wrote: Hi Frank, On Fri, 19 Sep 2014 13:54:34 +0200 frank.blasc...@de.ibm.com wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. This allows to attach qemu pci devices including vfio. This does not mean the devices are functional but at least detection and config/memory space access is working. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs |2 target-s390x/kvm.c | 52 +++ target-s390x/pci_ic.c | 621 + target-s390x/pci_ic.h | 425 ++ 4 files changed, 1099 insertions(+), 1 deletion(-) --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -2,4 +2,4 @@ obj-y += translate.o helper.o cpu.o inte obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pci_ic.o --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -40,6 +40,7 @@ #include exec/gdbstub.h #include trace.h #include qapi-event.h +#include pci_ic.h /* #define DEBUG_KVM */ @@ -56,6 +57,7 @@ #define IPA0_B2 0xb200 #define IPA0_B9 0xb900 #define IPA0_EB 0xeb00 +#define IPA0_E3 0xe300 #define PRIV_B2_SCLP_CALL 0x20 #define PRIV_B2_CSCH0x30 @@ -76,8 +78,17 @@ #define PRIV_B2_XSCH0x76 #define PRIV_EB_SQBS0x8a +#define PRIV_EB_PCISTB 0xd0 +#define PRIV_EB_SIC 0xd1 #define PRIV_B9_EQBS0x9c +#define PRIV_B9_CLP 0xa0 +#define PRIV_B9_PCISTG 0xd0 +#define PRIV_B9_PCILG 0xd2 +#define PRIV_B9_RPCIT 0xd3 + +#define PRIV_E3_MPCIFC 0xd0 +#define PRIV_E3_STPCIFC 0xd4 #define DIAG_IPL0x308 #define DIAG_KVM_HYPERCALL 0x500 @@ -813,6 +824,18 @@ static int handle_b9(S390CPU *cpu, struc int r = 0; switch (ipa1) { +case PRIV_B9_CLP: +r = kvm_clp_service_call(cpu, run); +break; +case PRIV_B9_PCISTG: +r = kvm_pcistg_service_call(cpu, run); +break; +case PRIV_B9_PCILG: +r = kvm_pcilg_service_call(cpu, run); +break; +case PRIV_B9_RPCIT: +r = kvm_rpcit_service_call(cpu, run); +break; case PRIV_B9_EQBS: /* just inject exception */ r = -1; @@ -831,6 +854,12 @@ static int handle_eb(S390CPU *cpu, struc int r = 0; switch (ipa1) { +case PRIV_EB_PCISTB: +r = kvm_pcistb_service_call(cpu, run); +break; +case PRIV_EB_SIC: +r = kvm_sic_service_call(cpu, run); +break; case PRIV_EB_SQBS: /* just inject exception */ r = -1; I'm not sure, but I think the handler for the eb instructions is wrong: The second byte of the opcode is encoded in the lowest byte of the ipb field, not the lowest byte of the ipa field (just like with the e3 handler). Did you verify that your handlers get called correctly? Hi Thomas, you are absolutely right. I already have a patch available for this issue but did not append it to this RFC post (since it is basically a bug fix). To the next posting I will add this patch as well. Will also fix the remaining issues thx for your review. @@ -844,6 +873,26 @@ static int handle_eb(S390CPU *cpu, struc return r; } +static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +{ +int r = 0; + +switch (ipa1) { +case PRIV_E3_MPCIFC: +r = kvm_mpcifc_service_call(cpu, run); +break; +case PRIV_E3_STPCIFC: +r = kvm_stpcifc_service_call(cpu, run); +break; +default: +r = -1; +DPRINTF(KVM: unhandled PRIV: 0xe3%x\n, ipa1); +break; +} + +return r; +} Could you please replace ipa1 with ipb1 to avoid confusion here? static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { CPUS390XState *env = cpu-env; @@ -1038,6 +1087,9 @@ static int handle_instruction(S390CPU *c case IPA0_EB: r = handle_eb(cpu, run, ipa1); break; +case IPA0_E3: +r = handle_e3(cpu, run, run-s390_sieic.ipb 0xff); +break; case IPA0_DIAG: r = handle_diag(cpu, run, run-s390_sieic.ipb); break; --- /dev/null +++ b/target-s390x/pci_ic.c @@ -0,0 +1,621 @@ [...] + +int kvm_pcilg_service_call
[Qemu-devel] [RFC patch 3/6] vfio: make vfio build on s390
From: Frank Blaschka frank.blasc...@de.ibm.com This patch adds some small changes to make vfio build on s390. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- drivers/vfio/Kconfig |2 +- drivers/vfio/pci/vfio_pci_rdwr.c |8 2 files changed, 9 insertions(+), 1 deletion(-) --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -16,7 +16,7 @@ config VFIO_SPAPR_EEH menuconfig VFIO tristate VFIO Non-Privileged userspace driver framework depends on IOMMU_API - select VFIO_IOMMU_TYPE1 if X86 + select VFIO_IOMMU_TYPE1 if (X86 || S390) select VFIO_IOMMU_SPAPR_TCE if (PPC_POWERNV || PPC_PSERIES) select VFIO_SPAPR_EEH if (PPC_POWERNV || PPC_PSERIES) select ANON_INODES --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -177,6 +177,13 @@ ssize_t vfio_pci_bar_rw(struct vfio_pci_ return done; } +#ifdef CONFIG_NO_IOPORT_MAP +ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf, + size_t count, loff_t *ppos, bool iswrite) +{ + return -EINVAL; +} +#else ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf, size_t count, loff_t *ppos, bool iswrite) { @@ -236,3 +243,4 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_ return done; } +#endif
[Qemu-devel] [RFC patch 1/6] KVM: s390: Enable PCI instructions
Enable PCI instructions for s390 KVM. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/kvm/kvm-s390.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -1787,7 +1787,7 @@ static int __init kvm_s390_init(void) } memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); vfacilities[0] = 0xff82fff3f4fc2000UL; - vfacilities[1] = 0x005cUL; + vfacilities[1] = 0x07dcUL; return 0; }
[Qemu-devel] [RFC patch 0/6] vfio based pci pass-through for qemu/KVM on s390
This set of patches implements a vfio based solution for pci pass-through on the s390 platform. The kernel stuff is pretty much straight forward, but qemu needs more work. Most interesting patch is: vfio: make vfio run on s390 platform I hope Alex Alex can give me some guidance how to do the changes in an appropriate way. After creating a separate iommmu address space for each attached PCI device I can successfully run the vfio type1 iommu. So If we could extend type1 not registering all guest memory (see patch) I think we do not need a special vfio iommu for s390 for the moment. The patches implement the base pass-through support. s390 specific virtualization functions are currently not included. This would be a second step after the base support is done. kernel patches apply to linux-kvm-next KVM: s390: Enable PCI instructions iommu: add iommu for s390 platform vfio: make vfio build on s390 qemu patches apply to qemu-master s390: Add PCI bus support s390: implement pci instruction vfio: make vfio run on s390 platform Thx for feedback and review comments Frank
[Qemu-devel] [RFC patch 5/6] s390: implement pci instruction
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements the s390 pci instructions in qemu. This allows to attach qemu pci devices including vfio. This does not mean the devices are functional but at least detection and config/memory space access is working. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- target-s390x/Makefile.objs |2 target-s390x/kvm.c | 52 +++ target-s390x/pci_ic.c | 621 + target-s390x/pci_ic.h | 425 ++ 4 files changed, 1099 insertions(+), 1 deletion(-) --- a/target-s390x/Makefile.objs +++ b/target-s390x/Makefile.objs @@ -2,4 +2,4 @@ obj-y += translate.o helper.o cpu.o inte obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o obj-y += gdbstub.o obj-$(CONFIG_SOFTMMU) += ioinst.o arch_dump.o -obj-$(CONFIG_KVM) += kvm.o +obj-$(CONFIG_KVM) += kvm.o pci_ic.o --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -40,6 +40,7 @@ #include exec/gdbstub.h #include trace.h #include qapi-event.h +#include pci_ic.h /* #define DEBUG_KVM */ @@ -56,6 +57,7 @@ #define IPA0_B2 0xb200 #define IPA0_B9 0xb900 #define IPA0_EB 0xeb00 +#define IPA0_E3 0xe300 #define PRIV_B2_SCLP_CALL 0x20 #define PRIV_B2_CSCH0x30 @@ -76,8 +78,17 @@ #define PRIV_B2_XSCH0x76 #define PRIV_EB_SQBS0x8a +#define PRIV_EB_PCISTB 0xd0 +#define PRIV_EB_SIC 0xd1 #define PRIV_B9_EQBS0x9c +#define PRIV_B9_CLP 0xa0 +#define PRIV_B9_PCISTG 0xd0 +#define PRIV_B9_PCILG 0xd2 +#define PRIV_B9_RPCIT 0xd3 + +#define PRIV_E3_MPCIFC 0xd0 +#define PRIV_E3_STPCIFC 0xd4 #define DIAG_IPL0x308 #define DIAG_KVM_HYPERCALL 0x500 @@ -813,6 +824,18 @@ static int handle_b9(S390CPU *cpu, struc int r = 0; switch (ipa1) { +case PRIV_B9_CLP: +r = kvm_clp_service_call(cpu, run); +break; +case PRIV_B9_PCISTG: +r = kvm_pcistg_service_call(cpu, run); +break; +case PRIV_B9_PCILG: +r = kvm_pcilg_service_call(cpu, run); +break; +case PRIV_B9_RPCIT: +r = kvm_rpcit_service_call(cpu, run); +break; case PRIV_B9_EQBS: /* just inject exception */ r = -1; @@ -831,6 +854,12 @@ static int handle_eb(S390CPU *cpu, struc int r = 0; switch (ipa1) { +case PRIV_EB_PCISTB: +r = kvm_pcistb_service_call(cpu, run); +break; +case PRIV_EB_SIC: +r = kvm_sic_service_call(cpu, run); +break; case PRIV_EB_SQBS: /* just inject exception */ r = -1; @@ -844,6 +873,26 @@ static int handle_eb(S390CPU *cpu, struc return r; } +static int handle_e3(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) +{ +int r = 0; + +switch (ipa1) { +case PRIV_E3_MPCIFC: +r = kvm_mpcifc_service_call(cpu, run); +break; +case PRIV_E3_STPCIFC: +r = kvm_stpcifc_service_call(cpu, run); +break; +default: +r = -1; +DPRINTF(KVM: unhandled PRIV: 0xe3%x\n, ipa1); +break; +} + +return r; +} + static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { CPUS390XState *env = cpu-env; @@ -1038,6 +1087,9 @@ static int handle_instruction(S390CPU *c case IPA0_EB: r = handle_eb(cpu, run, ipa1); break; +case IPA0_E3: +r = handle_e3(cpu, run, run-s390_sieic.ipb 0xff); +break; case IPA0_DIAG: r = handle_diag(cpu, run, run-s390_sieic.ipb); break; --- /dev/null +++ b/target-s390x/pci_ic.c @@ -0,0 +1,621 @@ +/* + * s390 PCI intercepts + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include sys/types.h +#include sys/ioctl.h +#include sys/mman.h + +#include linux/kvm.h +#include asm/ptrace.h +#include hw/pci/pci.h +#include hw/pci/pci_host.h +#include net/net.h + +#include qemu-common.h +#include qemu/timer.h +#include migration/qemu-file.h +#include sysemu/sysemu.h +#include sysemu/kvm.h +#include cpu.h +#include sysemu/device_tree.h +#include monitor/monitor.h +#include pci_ic.h + +#include hw/hw.h +#include hw/pci/pci.h +#include hw/pci/pci_bridge.h +#include hw/pci/pci_bus.h +#include hw/pci/pci_host.h +#include hw/s390x/s390-pci-bus.h +#include exec/exec-all.h + +/* #define DEBUG_S390PCI_IC */ +#ifdef DEBUG_S390PCI_IC +#define DPRINTF(fmt
[Qemu-devel] [RFC patch 2/6] iommu: add iommu for s390 platform
From: Frank Blaschka frank.blasc...@de.ibm.com Add a basic iommu for the s390 platform. The code is pretty simple since on s390 each PCI device has its own virtual io address space starting at the same vio address. For this a domain could hold only one pci device. Also there is no relation between pci devices so each device belongs to a separate iommu group. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/include/asm/pci.h |3 arch/s390/pci/pci_dma.c | 21 - drivers/iommu/Kconfig |9 ++ drivers/iommu/Makefile |1 drivers/iommu/s390-iommu.c | 181 5 files changed, 213 insertions(+), 2 deletions(-) --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -177,6 +177,9 @@ struct zpci_dev *get_zdev_by_fid(u32); /* DMA */ int zpci_dma_init(void); void zpci_dma_exit(void); +int dma_update_trans(struct zpci_dev *zdev, unsigned long pa, +dma_addr_t dma_addr, size_t size, int flags); +void dma_purge_rto_entries(struct zpci_dev *zdev); /* FMB */ int zpci_fmb_enable_device(struct zpci_dev *); --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -139,8 +139,8 @@ static void dma_update_cpu_trans(struct entry_clr_protected(entry); } -static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa, - dma_addr_t dma_addr, size_t size, int flags) +int dma_update_trans(struct zpci_dev *zdev, unsigned long pa, +dma_addr_t dma_addr, size_t size, int flags) { unsigned int nr_pages = PAGE_ALIGN(size) PAGE_SHIFT; u8 *page_addr = (u8 *) (pa PAGE_MASK); @@ -180,6 +180,7 @@ no_refresh: spin_unlock_irqrestore(zdev-dma_table_lock, irq_flags); return rc; } +EXPORT_SYMBOL_GPL(dma_update_trans); static void dma_free_seg_table(unsigned long entry) { @@ -210,6 +211,22 @@ static void dma_cleanup_tables(struct zp zdev-dma_table = NULL; } +void dma_purge_rto_entries(struct zpci_dev *zdev) +{ + unsigned long *table; + int rtx; + + if (!zdev || !zdev-dma_table) + return; + table = zdev-dma_table; + for (rtx = 0; rtx ZPCI_TABLE_ENTRIES; rtx++) + if (reg_entry_isvalid(table[rtx])) { + dma_free_seg_table(table[rtx]); + invalidate_table_entry(table[rtx]); + } +} +EXPORT_SYMBOL_GPL(dma_purge_rto_entries); + static unsigned long __dma_alloc_iommu(struct zpci_dev *zdev, unsigned long start, int size) { --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -302,4 +302,13 @@ config ARM_SMMU Say Y here if your SoC includes an IOMMU device implementing the ARM SMMU architecture. +config S390_IOMMU +bool s390 IOMMU Support +depends on S390 +select IOMMU_API +help + Support for the IBM s/390 IOMMU + + If unsure, say N here. + endif # IOMMU_SUPPORT --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iom obj-$(CONFIG_SHMOBILE_IOMMU) += shmobile-iommu.o obj-$(CONFIG_SHMOBILE_IPMMU) += shmobile-ipmmu.o obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o +obj-$(CONFIG_S390_IOMMU) += s390-iommu.o --- /dev/null +++ b/drivers/iommu/s390-iommu.c @@ -0,0 +1,181 @@ +#include linux/io.h +#include linux/interrupt.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/pm_runtime.h +#include linux/clk.h +#include linux/err.h +#include linux/mm.h +#include linux/iommu.h +#include linux/errno.h +#include linux/list.h +#include linux/memblock.h +#include linux/export.h +#include linux/pci.h +#include linux/sizes.h +#include asm/pci_dma.h + +#define S390_IOMMU_PGSIZES SZ_4K + +struct s390_domain { + struct zpci_dev *zdev; +}; + +static int s390_iommu_domain_init(struct iommu_domain *domain) +{ + struct s390_domain *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + domain-priv = priv; + return 0; +} + +static void s390_iommu_domain_destroy(struct iommu_domain *domain) +{ + kfree(domain-priv); + domain-priv = NULL; +} + +static int s390_iommu_attach_device(struct iommu_domain *domain, + struct device *dev) +{ + struct s390_domain *priv = domain-priv; + + if (priv-zdev) + return -EEXIST; + + priv-zdev = (struct zpci_dev *)to_pci_dev(dev)-sysdata; + return 0; +} + +static void s390_iommu_detach_device(struct iommu_domain *domain, +struct device *dev) +{ + struct s390_domain *priv = domain-priv; + + dma_purge_rto_entries(priv-zdev); + priv-zdev = NULL; +} + +static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova
[Qemu-devel] [RFC patch 6/6] vfio: make vfio run on s390 platform
From: Frank Blaschka frank.blasc...@de.ibm.com Following changes are made because of platform differences: 1) s390 does not support mmap'ing of PCI BARs so we have to go via slow path 2) no intx support 3) no classic MSIX interrupts. The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs. Introduce s390 specific functions for msix notification (slow path) and msi routes (kvm fast path). 4) Use type1 iommu but register only for iommu address space Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/misc/vfio.c | 24 1 file changed, 24 insertions(+) --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -40,6 +40,9 @@ #include sysemu/kvm.h #include sysemu/sysemu.h #include hw/misc/vfio.h +#ifdef TARGET_S390X +#include hw/s390x/s390-pci-bus.h +#endif /* #define DEBUG_VFIO */ #ifdef DEBUG_VFIO @@ -51,7 +54,11 @@ #endif /* Extra debugging, trap acceleration paths for more logging */ +#ifdef TARGET_S390X +#define VFIO_ALLOW_MMAP 0 +#else #define VFIO_ALLOW_MMAP 1 +#endif #define VFIO_ALLOW_KVM_INTX 1 #define VFIO_ALLOW_KVM_MSI 1 #define VFIO_ALLOW_KVM_MSIX 1 @@ -554,6 +561,10 @@ static int vfio_enable_intx(VFIODevice * struct vfio_irq_set *irq_set; int32_t *pfd; +#ifdef TARGET_S390X +return 0; +#endif + if (!pin) { return 0; } @@ -664,7 +675,11 @@ static void vfio_msi_interrupt(void *opa #endif if (vdev-interrupt == VFIO_INT_MSIX) { +#ifdef TARGET_S390X +s390_msix_notify(vdev-pdev, nr); +#else msix_notify(vdev-pdev, nr); +#endif } else if (vdev-interrupt == VFIO_INT_MSI) { msi_notify(vdev-pdev, nr); } else { @@ -730,7 +745,11 @@ static void vfio_add_kvm_msi_virq(VFIOMS return; } +#ifdef TARGET_S390X +virq = s390_irqchip_add_msi_route(vector-vdev-pdev, kvm_state, *msg); +#else virq = kvm_irqchip_add_msi_route(kvm_state, *msg); +#endif if (virq 0) { event_notifier_cleanup(vector-kvm_interrupt); return; @@ -3702,8 +3721,13 @@ static int vfio_connect_container(VFIOGr container-iommu_data.type1.listener = vfio_memory_listener; container-iommu_data.release = vfio_listener_release; +#ifdef TARGET_S390X +memory_listener_register(container-iommu_data.type1.listener, + container-space-as); +#else memory_listener_register(container-iommu_data.type1.listener, address_space_memory); +#endif if (container-iommu_data.type1.error) { ret = container-iommu_data.type1.error;
[Qemu-devel] [RFC patch 4/6] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with some infrastructure to generate and handle hotplug events. It also provides device configuration/unconfiguration via sclp instruction interception. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak |1 hw/s390x/Makefile.objs|1 hw/s390x/css.c|5 hw/s390x/css.h|1 hw/s390x/s390-pci-bus.c | 404 ++ hw/s390x/s390-pci-bus.h | 166 +++ hw/s390x/s390-virtio-ccw.c|2 hw/s390x/sclp.c | 10 include/hw/s390x/sclp.h |8 target-s390x/ioinst.c | 52 target-s390x/ioinst.h |1 11 files changed, 650 insertions(+), 1 deletion(-) --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,3 +1,4 @@ +include pci.mak CONFIG_VIRTIO=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-$(CONFIG_KVM) += s390-pci-bus.o --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1281,6 +1281,11 @@ void css_generate_chp_crws(uint8_t cssid /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -99,6 +99,7 @@ void css_queue_crw(uint8_t rsc, uint8_t void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,404 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include hw/pci/msi.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static const unsigned long be_to_le = BITS_PER_LONG - 1; +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +PciCcdfErr *eccdf; +int rc = 1; +SeiContainer *sei_cont; + +sei_cont = QTAILQ_FIRST(pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont-fid); +accdf-fh = cpu_to_be32(sei_cont-fh); +accdf-pec = cpu_to_be16(sei_cont-pec); +break; +default: +abort(); +} +g_free(sei_cont); +rc = 0; +} + +return rc; +} + +int chsc_sei_nt2_have_event(void) +{ +return !QTAILQ_EMPTY(pending_sei); +} + +static S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) +{ +S390PCIBusDevice *pbdev; + +QTAILQ_FOREACH(pbdev, device_list, next) { +if (pbdev-fid == fid) { +return pbdev; +} +} +return NULL; +} + +void s390_pci_sclp_configure(int configure, SCCB *sccb) +{ +PciCfgSccb *psccb = (PciCfgSccb *)sccb; +S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb-aid)); +uint16_t rc; + +if (pbdev) { +if ((configure == 1 pbdev-configured == true) || +(configure == 0 pbdev-configured == false)) { +rc = SCLP_RC_NO_ACTION_REQUIRED; +} else { +pbdev-configured = !pbdev-configured; +rc = SCLP_RC_NORMAL_COMPLETION; +} +} else { +DPRINTF(sclp config %d no dev found\n, configure); +rc
Re: [Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390
On Thu, Sep 04, 2014 at 07:16:24AM -0600, Alex Williamson wrote: On Thu, 2014-09-04 at 12:52 +0200, frank.blasc...@de.ibm.com wrote: This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms. Major differences are: 1) all PCI operations are driven by special s390 instructions Generating config cycles is always arch specific. 2) all s390 PCI instructions are privileged While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged. 3) PCI config and memory spaces can not be mmap'ed VFIO has mapping flags that allow any region to specify mmap support. Hi Alex, thx for your reply. Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view. 4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs. VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism. yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio. 5) For DMA access there is always an IOMMU required. x86 requires the same. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request. Sounds like POWER. Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request. 6) The OS does not get any informations about the physical layout of the PCI bus. If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy. OK 7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM The KVM-VFIO device allows interaction between VFIO devices and KVM. 8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel. VFIO supports different device backends, currently pci_dev and working towards platform devices. zpci might just be an extension to standard pci. 7 - 8 At least this is not as straightforward as the pure kernel approach, but I have to dig into that in more detail if we could only agree on a vfio solution. For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration: -device s390-pci,host=:00:00.0 The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. kernel patches apply to linux-kvm s390: cio: chsc function to register GIB s390: pci: export pci functions for pass-through usage KVM: s390: Add GISA support KVM: s390: Add PCI pass-through support qemu patches apply to qemu-master s390: Add PCI bus support s390: Add PCI pass-through device support Feedback and discussion is highly welcome ... KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks, Is this your personal opinion or was this a strategic decision of the QEMU/KVM community? Can anybody give us direction about this? Actually I can understand your point. In the last weeks I did some development and testing regarding the use of vfio too. But the in kernel solutions seems to offer the best performance and most straighforward implementation for our platform. Greetings, Frank Alex -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support
On Fri, Sep 05, 2014 at 10:29:26AM +0200, Alexander Graf wrote: On 04.09.14 12:52, frank.blasc...@de.ibm.com wrote: From: Frank Blaschka frank.blasc...@de.ibm.com This patch adds GISA (Guest Interrupt State Area) support to s390 kvm. GISA can be used for exitless interrupts. The patch provides a set of functions for GISA related operations like accessing GISA fields or registering ISCs for alert. Exploiters of GISA will follow with additional patches. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com That's a nice feature. However, please make sure that you maintain the abstraction levels. What should happen is that you request an irqfd from FLIC. Then you associate that irqfd with the PCI device. Thanks to that association, both parties can now talk to each other and negotiate their GISA number space and make sure things are connected. However, it should always be possible to do things without this direct IRQ injection. So you should be able to receive an irqfd event when an IRQ happened, so that VFIO user space applications can also handle interrupts for example. And the same applies for interrupt injection. We also need to be able to inject an adapter interrupt from QEMU for emulated devices ;). OK, assuming we are doing the vfio solution expoiting GISA would be a second step. Will take your feedback into account. THX! Alex -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390
On Fri, Sep 05, 2014 at 10:21:27AM +0200, Alexander Graf wrote: On 04.09.14 12:52, frank.blasc...@de.ibm.com wrote: This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms. Major differences are: 1) all PCI operations are driven by special s390 instructions 2) all s390 PCI instructions are privileged 3) PCI config and memory spaces can not be mmap'ed That's ok, vfio abstracts config space anyway. 4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs. This is in line with other implementations. Interrupts go from device - PHB - PIC - CPU (some times you can have another converter device in between) In your case, the PHB converts INTX and MSI interrupts to Adapter interrupts to go to the floating interrupt controller. Same thing as everyone else really. Yes, I think this can be done, but we need s390 specific changes in vfio. 5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request. Sounds great :). So I suppose we should implement a guest facing IOMMU? 6) The OS does not get any informations about the physical layout of the PCI bus. So how does it know whether different devices are behind the same IOMMU context? Or can we assume that every device has its own context? Actually yes 7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM Pleas elaborate. 8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel. Why? We have following s390 specific virtualization features: 1) interpretive execution of pci load/store instruction. If we use this function pci access does not get intercepted (no SIE exit) but is handled via microcode. To enable this we have to disable zpci device and enable it again with information from the SIE control block. Further in qemu problem is: vfio traps access to MSIX table so we have to find another way programming msix if we do not get intercepts for memory space access. 2) Adapter event forwarding (with alerting). This is a mechanism the adpater event (irq) is directly forwarded to the guest. To set this up we also need to manipulate the zpci device (in kernel) with information form the SIE block. Exploiting GISA is only one part of this mechanism. Both might be possible with some more or less nice looking vfio extensions. As I said before we have to dig more into. Also this can be further optimazation steps later if we have a running vfio implementation on the platform. For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a I fail to see the rationale and I definitely don't want to see anything even remotely similar to the legacy x86 device assignment on s390 ;). Can't we just enhance VFIO? Probably yes, but we need some vfio changes (kernel and qemu) Also, I think we'll get the cleanest model if we start off with an implementation that allows us to add emulated PCI devices to an s390x machine and only then follow on with physical ones. I can already do this. With some more s390 intercepts a device can be detected and guest is able to access config/memory space. Unfortunately s390 platform does not support I/O bars so non of the emulated devices will work on the platform ... Alex -- To unsubscribe from this list: send the line unsubscribe kvm in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390
On Fri, Sep 05, 2014 at 10:35:59AM +0200, Alexander Graf wrote: On 05.09.14 09:46, Frank Blaschka wrote: On Thu, Sep 04, 2014 at 07:16:24AM -0600, Alex Williamson wrote: On Thu, 2014-09-04 at 12:52 +0200, frank.blasc...@de.ibm.com wrote: This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms. Major differences are: 1) all PCI operations are driven by special s390 instructions Generating config cycles is always arch specific. 2) all s390 PCI instructions are privileged While the operations to generate config cycles on x86 are not privileged, they must be arbitrated between accesses, so in a sense they're privileged. 3) PCI config and memory spaces can not be mmap'ed VFIO has mapping flags that allow any region to specify mmap support. Hi Alex, thx for your reply. Let me elaborate a little bit ore on 1 - 3. Config and memory space can not be accessed via memory operations. You have to use special s390 instructions. This instructions can not be executed in user space. So there is no other way than executing this instructions in kernel. Yes vfio does support a slow path via ioctrl we could use, but this seems suboptimal from performance point of view. Ah, I missed the memory spaces part ;). I agree that it's suboptimal to call into the kernel for every PCI access, but I still think that VFIO provides the correct abstraction layer for us to use. If nothing else, it would at least give us identical configuration to x86 and nice debugability en par with the other platforms. 4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs. VFIO delivers interrupts as eventfds regardless of the underlying platform mechanism. yes that's right, but then we have to do platform specific stuff to present the irq to the guest. I do not say this is impossible but we have add s390 specific code to vfio. Not at all - interrupt delivery is completely transparent to VFIO. interrupt yes, but MSIX no 5) For DMA access there is always an IOMMU required. x86 requires the same. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request. Sounds like POWER. Don't know the details from power, maybe it is similar but not the same. We might be able to extend vfio to have a new interface allowing us to do DMA mappings on request. We already have that. Great, can you give me some pointers how to use? Thx! 6) The OS does not get any informations about the physical layout of the PCI bus. If that means that every device is isolated (seems unlikely for multifunction devices) then that makes IOMMU group support really easy. OK 7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM The KVM-VFIO device allows interaction between VFIO devices and KVM. 8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel. VFIO supports different device backends, currently pci_dev and working towards platform devices. zpci might just be an extension to standard pci. 7 - 8 At least this is not as straightforward as the pure kernel approach, but I have to dig into that in more detail if we could only agree on a vfio solution. Please do so, yes :). For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration: -device s390-pci,host=:00:00.0 The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. kernel patches apply to linux-kvm s390: cio: chsc function to register GIB s390: pci: export pci functions for pass-through usage KVM: s390: Add GISA support KVM: s390: Add PCI pass-through support qemu patches apply to qemu-master s390: Add PCI bus support s390: Add PCI pass-through device support Feedback and discussion is highly welcome ... KVM-based device assignment needs to go away. It's a horrible model for devices, it offers very little protection to the kernel, assumes every device is fully isolated and visible to the IOMMU, relies on smattering of sysfs files to operate, etc. x86, POWER, and ARM are all moving to VFIO-based device assignment. Why is s390 special enough to repeat all the mistakes that x86 did? Thanks, Is this your personal opinion or was this a strategic decision of the QEMU/KVM community? Can anybody give us direction about
[Qemu-devel] [RFC][patch 3/6] KVM: s390: Add GISA support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch adds GISA (Guest Interrupt State Area) support to s390 kvm. GISA can be used for exitless interrupts. The patch provides a set of functions for GISA related operations like accessing GISA fields or registering ISCs for alert. Exploiters of GISA will follow with additional patches. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/include/asm/kvm_host.h | 72 arch/s390/kvm/kvm-s390.c | 167 +++ arch/s390/kvm/kvm-s390.h | 28 ++ 3 files changed, 265 insertions(+), 2 deletions(-) --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -129,11 +129,12 @@ struct kvm_s390_sie_block { __u8reserved60; /* 0x0060 */ __u8ecb;/* 0x0061 */ __u8ecb2; /* 0x0062 */ - __u8reserved63[1]; /* 0x0063 */ + __u8ecb3; /* 0x0063 */ __u32 scaol; /* 0x0064 */ __u8reserved68[4]; /* 0x0068 */ __u32 todpr; /* 0x006c */ - __u8reserved70[32]; /* 0x0070 */ + __u32 gd; /* 0x0070 */ + __u8reserved74[28]; /* 0x0074 */ psw_t gpsw; /* 0x0090 */ __u64 gg14; /* 0x00a0 */ __u64 gg15; /* 0x00a8 */ @@ -300,6 +301,70 @@ struct kvm_s390_interrupt_info { #define ACTION_STORE_ON_STOP (10) #define ACTION_STOP_ON_STOP(11) +#define KVM_S390_GISA_FORMAT_0 0 +#define KVM_S390_GISA_FORMAT_1 1 + +struct kvm_s390_gisa_f0 { + u32 next_alert; + u8 ipm; + u16 rsv0:14; + u16 g:1; + u16 c:1; + u8 iam; + u32 rsv1; + u32 count; +} __packed; + +struct kvm_s390_gisa_f1 { + u32 next_alert; + u8 ipm; + u8 simm; + u8 nimm; + u8 iam; + u64 aisma; + u32 rsv0:6; + u32 g:1; + u32 c:1; + u32 rsv1:24; + u64 rsv2; + u32 count; +} __packed; + +union kvm_s390_gisa { + struct kvm_s390_gisa_f0 f0; + struct kvm_s390_gisa_f1 f1; +}; + +struct kvm_s390_gait { + u32 gd; + u16 : 5; + u16 gisc : 3; + u16 rpu : 8; + u16: 10; + u16 gaisbo : 6; + u64 gaisba; +} __packed; + +struct kvm_s390_aifte { + u64 faisba; + u64 gaita; + u16 simm : 8; + u16 : 5; + u16 afi : 3; + u16 reserved1; + u16 reserved2; + u16 faal; +} __packed; + +struct kvm_s390_gib { + u32 alo; + u32 reserved1; + u32 : 5; + u32 nisc : 3; + u32 : 24; + u8 reserverd2[20]; +} __packed; + struct kvm_s390_local_interrupt { spinlock_t lock; struct list_head list; @@ -420,6 +485,9 @@ struct kvm_arch{ struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; wait_queue_head_t ipte_wq; spinlock_t start_stop_lock; + union kvm_s390_gisa *gisa; + unsigned long iam; + atomic_t in_sie; }; #define KVM_HVA_ERR_BAD(-1UL) --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -404,6 +404,16 @@ long kvm_arch_vm_ioctl(struct file *filp return r; } +static u8 kvm_s390_gisa_get_alert_mask(struct kvm *kvm) +{ + return (u8)ACCESS_ONCE(kvm-arch.iam); +} + +static void kvm_s390_gisa_set_alert_mask(struct kvm *kvm, u8 iam) +{ + xchg(kvm-arch.iam, iam); +} + int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) { int rc; @@ -461,6 +471,14 @@ int kvm_arch_init_vm(struct kvm *kvm, un kvm-arch.css_support = 0; kvm-arch.use_irqchip = 0; + kvm-arch.gisa = (union kvm_s390_gisa *)get_zeroed_page( + GFP_KERNEL | GFP_DMA); + if (!kvm-arch.gisa) + goto out_nogmap; + kvm_s390_gisa_set_next_alert(kvm, (u32)(unsigned long)kvm-arch.gisa); + kvm_s390_gisa_set_alert_mask(kvm, 0); + atomic_set(kvm-arch.in_sie, 0); + spin_lock_init(kvm-arch.start_stop_lock); return 0; @@ -520,6 +538,7 @@ void kvm_arch_sync_events(struct kvm *kv void kvm_arch_destroy_vm(struct kvm *kvm) { + free_page((unsigned long)kvm-arch.gisa); kvm_free_vcpus(kvm); free_page((unsigned long)(kvm-arch.sca)); debug_unregister(kvm-arch.dbf); @@ -656,6 +675,19 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu return rc; } +u32 kvm_s390_gisa_get_fmt(void) +{ + if (test_facility(70) || test_facility(72)) + return KVM_S390_GISA_FORMAT_1; + else + return KVM_S390_GISA_FORMAT_0; +} + +static u32 kvm_s390_build_gd(struct kvm *kvm) +{ + return (u32)(unsigned long)kvm-arch.gisa | kvm_s390_gisa_get_fmt(); +} + struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm
[Qemu-devel] [RFC][patch 1/6] s390: cio: chsc function to register GIB
From: Frank Blaschka frank.blasc...@de.ibm.com This patch provides a new chsc function to register/unregister a GIB (Guest Information Block). Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/include/asm/cio.h |1 drivers/s390/cio/chsc.c | 50 2 files changed, 51 insertions(+) --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -311,5 +311,6 @@ extern int cio_get_iplinfo(struct cio_ip /* Function from drivers/s390/cio/chsc.c */ int chsc_sstpc(void *page, unsigned int op, u16 ctrl); int chsc_sstpi(void *page, void *result, size_t size); +int chsc_sgib(u32 gibo); #endif --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1188,6 +1188,56 @@ out: EXPORT_SYMBOL_GPL(chsc_siosl); /** + * chsc_sgib() - register guest information block + * @gibo: guest information block + * + * gibo must be allocated in low memory + * + * Returns 0 on success. + */ +int chsc_sgib(u32 gibo) +{ + struct { + struct chsc_header request; + u16 operation_code; + u16 : 16; + u32 : 4; + u32 fmt : 4; + u32 : 24; + u32 : 32; + u32 : 32; + u32 gibo; + u64 : 64; + u32 : 16; + u32 aix : 8; + u32 : 8; + u32 reserved[1007]; + struct chsc_header response; + } __packed *scssc; + unsigned long flags; + int rc; + + spin_lock_irqsave(chsc_page_lock, flags); + memset(chsc_page, 0, PAGE_SIZE); + scssc = chsc_page; + + scssc-request.length = 0x0fe0; + scssc-request.code = 0x0021; + scssc-operation_code = 1; + scssc-gibo = gibo; + + rc = chsc(scssc); + if (rc) + rc = -EIO; + else + rc = chsc_error_from_response(scssc-response.code); + + spin_unlock_irqrestore(chsc_page_lock, flags); + return rc; +} +EXPORT_SYMBOL_GPL(chsc_sgib); + +/** * chsc_scm_info() - store SCM information (SSI) * @scm_area: request and response block for SSI * @token: continuation token
[Qemu-devel] [RFC][patch 4/6] KVM: s390: Add PCI pass-through support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implemets PCI pass-through kernel support for s390. Design approach is very similar to the x86 device assignment. User space executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. s390 pci instructions are intercepted in kernel and operations are passed directly to the assigned pci device. To take advantage of all system z specific virtualization features we need to access the SIE control block residing in KVM. Also we have to enable z pci devices with special configuration information coming form the SIE block as well. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/include/asm/kvm_host.h |1 arch/s390/kvm/Makefile |2 arch/s390/kvm/intercept.c|1 arch/s390/kvm/kvm-s390.c | 33 arch/s390/kvm/kvm-s390.h | 17 arch/s390/kvm/pci.c | 2130 +++ arch/s390/kvm/priv.c | 21 7 files changed, 2202 insertions(+), 3 deletions(-) --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -488,6 +488,7 @@ struct kvm_arch{ union kvm_s390_gisa *gisa; unsigned long iam; atomic_t in_sie; + struct list_head ppt_dev_list; }; #define KVM_HVA_ERR_BAD(-1UL) --- a/arch/s390/kvm/Makefile +++ b/arch/s390/kvm/Makefile @@ -12,6 +12,6 @@ common-objs = $(KVM)/kvm_main.o $(KVM)/e ccflags-y := -Ivirt/kvm -Iarch/s390/kvm kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o -kvm-objs += diag.o gaccess.o guestdbg.o +kvm-objs += diag.o gaccess.o guestdbg.o pci.o obj-$(CONFIG_KVM) += kvm.o --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c @@ -34,6 +34,7 @@ static const intercept_handler_t instruc [0xb6] = kvm_s390_handle_stctl, [0xb7] = kvm_s390_handle_lctl, [0xb9] = kvm_s390_handle_b9, + [0xe3] = kvm_s390_handle_e3, [0xe5] = kvm_s390_handle_e5, [0xeb] = kvm_s390_handle_eb, }; --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -397,6 +397,24 @@ long kvm_arch_vm_ioctl(struct file *filp r = kvm_s390_vm_has_attr(kvm, attr); break; } + case KVM_ASSIGN_PCI_DEVICE: { + struct kvm_assigned_pci_dev assigned_dev; + + r = -EFAULT; + if (copy_from_user(assigned_dev, argp, sizeof(assigned_dev))) + break; + r = kvm_s390_ioctrl_assign_pci(kvm, assigned_dev); + break; + } + case KVM_DEASSIGN_PCI_DEVICE: { + struct kvm_assigned_pci_dev assigned_dev; + + r = -EFAULT; + if (copy_from_user(assigned_dev, argp, sizeof(assigned_dev))) + break; + r = kvm_s390_ioctrl_deassign_pci(kvm, assigned_dev); + break; + } default: r = -ENOTTY; } @@ -478,6 +496,7 @@ int kvm_arch_init_vm(struct kvm *kvm, un kvm_s390_gisa_set_next_alert(kvm, (u32)(unsigned long)kvm-arch.gisa); kvm_s390_gisa_set_alert_mask(kvm, 0); atomic_set(kvm-arch.in_sie, 0); + INIT_LIST_HEAD(kvm-arch.ppt_dev_list); spin_lock_init(kvm-arch.start_stop_lock); @@ -538,6 +557,7 @@ void kvm_arch_sync_events(struct kvm *kv void kvm_arch_destroy_vm(struct kvm *kvm) { + s390_pci_cleanup(kvm); free_page((unsigned long)kvm-arch.gisa); kvm_free_vcpus(kvm); free_page((unsigned long)(kvm-arch.sca)); @@ -656,7 +676,10 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu vcpu-arch.sie_block-ecb |= 0x10; vcpu-arch.sie_block-ecb2 = 8; - vcpu-arch.sie_block-eca = 0xD1002000U; + vcpu-arch.sie_block-eca = 0xD1202000U; + vcpu-arch.sie_block-ecb2 |= 0x02; + vcpu-arch.sie_block-ecb3 = 0x20; + if (sclp_has_siif()) vcpu-arch.sie_block-eca |= 1; vcpu-arch.sie_block-fac = (int) (long) vfacilities; @@ -1920,6 +1943,12 @@ static int __init kvm_s390_init(void) if (ret) return ret; + ret = s390_pci_init(); + if (ret) { + kvm_exit(); + return ret; + } + /* * guests can ask for up to 255+1 double words, we need a full page * to hold the maximum amount of facilities. On the other hand, we @@ -1932,7 +1961,7 @@ static int __init kvm_s390_init(void) } memcpy(vfacilities, S390_lowcore.stfle_fac_list, 16); vfacilities[0] = 0xff82fff3f4fc2000UL; - vfacilities[1] = 0x005cUL; + vfacilities[1] = 0x07dcUL; return 0; } --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h @@ -167,6 +167,7 @@ int kvm_s390_mask_adapter(struct kvm *kv /* implemented in priv.c */ int is_valid_psw(psw_t *psw); int
[Qemu-devel] [RFC][patch 0/6] pci pass-through support for qemu/KVM on s390
This set of patches implements pci pass-through support for qemu/KVM on s390. PCI support on s390 is very different from other platforms. Major differences are: 1) all PCI operations are driven by special s390 instructions 2) all s390 PCI instructions are privileged 3) PCI config and memory spaces can not be mmap'ed 4) no classic interrupts (INTX, MSI). The pci hw understands the concept of requesting MSIX irqs but irqs are delivered as s390 adapter irqs. 5) For DMA access there is always an IOMMU required. s390 pci implementation does not support a complete memory to iommu mapping, dma mappings are created on request. 6) The OS does not get any informations about the physical layout of the PCI bus. 7) To take advantage of system z specific virtualization features we need to access the SIE control block residing in the kernel KVM 8) To enable system z specific virtualization features we have to manipulate the zpci device in kernel. For this reasons I decided to implement a kernel based approach similar to x86 device assignment. There is a new qemu device (s390-pci) representing a pass through device on the host. Here is a sample qemu device configuration: -device s390-pci,host=:00:00.0 The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. kernel patches apply to linux-kvm s390: cio: chsc function to register GIB s390: pci: export pci functions for pass-through usage KVM: s390: Add GISA support KVM: s390: Add PCI pass-through support qemu patches apply to qemu-master s390: Add PCI bus support s390: Add PCI pass-through device support Feedback and discussion is highly welcome ... Thx! Frank
[Qemu-devel] [RFC][patch 2/6] s390: pci: export pci functions for pass-through usage
From: Frank Blaschka frank.blasc...@de.ibm.com This patch exports a couple of zPCI functions. The new pci pass-through driver for KVM will use this functions to enable the device with virtualization information and update the device dma translation table on the host. We add a new interface to purge the translation table of a device. Also we moved some zPCI functions to the pci_insn header file. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- arch/s390/include/asm/pci.h |6 ++ arch/s390/include/asm/pci_clp.h |3 - arch/s390/include/asm/pci_insn.h | 92 arch/s390/pci/pci_clp.c |4 + arch/s390/pci/pci_dma.c | 24 - arch/s390/pci/pci_insn.c | 97 --- 6 files changed, 126 insertions(+), 100 deletions(-) --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -140,6 +140,7 @@ int zpci_register_ioat(struct zpci_dev * int zpci_unregister_ioat(struct zpci_dev *, u8); /* CLP */ +u8 clp_instr(void *data); int clp_scan_pci_devices(void); int clp_rescan_pci_devices(void); int clp_rescan_pci_devices_simple(void); @@ -177,6 +178,11 @@ struct zpci_dev *get_zdev_by_fid(u32); /* DMA */ int zpci_dma_init(void); void zpci_dma_exit(void); +int dma_update_trans(struct zpci_dev *zdev, unsigned long pa, +dma_addr_t dma_addr, size_t size, int flags); +void dma_update_cpu_trans(struct zpci_dev *zdev, void *page_addr, + dma_addr_t dma_addr, int flags); +void dma_purge_rto_entries(struct zpci_dev *zdev); /* FMB */ int zpci_fmb_enable_device(struct zpci_dev *); --- a/arch/s390/include/asm/pci_clp.h +++ b/arch/s390/include/asm/pci_clp.h @@ -148,7 +148,8 @@ struct clp_req_set_pci { u16 reserved2; u8 oc; /* operation controls */ u8 ndas;/* number of dma spaces */ - u64 reserved3; + u32 reserved3; + u32 gd; /* GISA Designation */ } __packed; /* Set PCI function response */ --- a/arch/s390/include/asm/pci_insn.h +++ b/arch/s390/include/asm/pci_insn.h @@ -1,6 +1,8 @@ #ifndef _ASM_S390_PCI_INSN_H #define _ASM_S390_PCI_INSN_H +#include asm/processor.h + /* Load/Store status codes */ #define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4 #define ZPCI_PCI_ST_FUNC_IN_ERR8 @@ -83,4 +85,94 @@ int zpci_store(u64 data, u64 req, u64 of int zpci_store_block(const u64 *data, u64 req, u64 offset); void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc); +static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status) +{ + u8 cc; + + asm volatile ( + .insn rxy,0xe3d0,%[req],%[fib]\n + ipm %[cc]\n + srl %[cc],28\n + : [cc] =d (cc), [req] +d (req), [fib] +Q (*fib) + : : cc); + *status = req 24 0xff; + return cc; +} + +static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status) +{ + register u64 __addr asm(2) = addr; + register u64 __range asm(3) = range; + u8 cc; + + asm volatile ( + .insn rre,0xb9d3,%[fn],%[addr]\n + ipm %[cc]\n + srl %[cc],28\n + : [cc] =d (cc), [fn] +d (fn) + : [addr] d (__addr), d (__range) + : cc); + *status = fn 24 0xff; + return cc; +} + +static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status) +{ + register u64 __req asm(2) = req; + register u64 __offset asm(3) = offset; + int cc = -ENXIO; + u64 __data; + + asm volatile ( + .insn rre,0xb9d2,%[data],%[req]\n + 0: ipm %[cc]\n + srl %[cc],28\n + 1:\n + EX_TABLE(0b, 1b) + : [cc] +d (cc), [data] =d (__data), [req] +d (__req) + : d (__offset) + : cc); + *status = __req 24 0xff; + if (!cc) + *data = __data; + + return cc; +} + +static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status) +{ + register u64 __req asm(2) = req; + register u64 __offset asm(3) = offset; + int cc = -ENXIO; + + asm volatile ( + .insn rre,0xb9d0,%[data],%[req]\n + 0: ipm %[cc]\n + srl %[cc],28\n + 1:\n + EX_TABLE(0b, 1b) + : [cc] +d (cc), [req] +d (__req) + : d (__offset), [data] d (data) + : cc); + *status = __req 24 0xff; + return cc; +} + +static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status) +{ + int cc = -ENXIO; + + asm volatile ( + .insn rsy,0xebd0,%[req],%[offset],%[data]\n
[Qemu-devel] [RFC][patch 6/6] s390: Add PCI pass-through device support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch adds a new device class handling s390 pci pass-through device assignment. The approach is very similar to the x86 device assignment. The device executes the KVM_ASSIGN_PCI_DEVICE ioctl to create a proxy instance in the kernel KVM and connect this instance to the host pci device. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- hw/s390x/Makefile.objs |2 hw/s390x/s390-pci-bus.c | 14 +- hw/s390x/s390_pci.c | 321 hw/s390x/s390_pci.h | 31 4 files changed, 365 insertions(+), 3 deletions(-) --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,4 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o -obj-$(CONFIG_KVM) += s390-pci-bus.o +obj-$(CONFIG_KVM) += s390-pci-bus.o s390_pci.o --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -16,6 +16,7 @@ #include hw/s390x/sclp.h #include qemu/error-report.h #include s390-pci-bus.h +#include s390_pci.h /* #define DEBUG_S390PCI_BUS */ #ifdef DEBUG_S390PCI_BUS @@ -219,8 +220,17 @@ static void s390_pcihost_hot_plug(Hotplu pbdev-pdev = pci_dev; pbdev-configured = true; -pbdev-fh = s390_pci_get_pfh(pci_dev); -pbdev-is_virt = 1; +if (!strcmp(pci_dev-name, s390-pci)) { +S390PCIDevice *sdev = DO_UPCAST(S390PCIDevice, pdev, pci_dev); +pbdev-fh = s390_pci_get_fh(sdev-host); +if (!pbdev-fh) { +g_free(pbdev); +return; +} +} else { +pbdev-fh = s390_pci_get_pfh(pci_dev); +pbdev-is_virt = 1; +} QTAILQ_INSERT_TAIL(device_list, pbdev, next); if (dev-hotplugged) { --- /dev/null +++ b/hw/s390x/s390_pci.c @@ -0,0 +1,321 @@ +/* + * s390 PCI pass-through device assignment + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/pci/pci_host.h +#include hw/pci/pci_bus.h +#include net/net.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include exec/exec-all.h +#include sysemu/sysemu.h +#include exec/address-spaces.h +#include qemu/error-report.h +#include qapi/qmp/qerror.h + +#include s390_pci.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI */ +#ifdef DEBUG_S390PCI +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, s390pci: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +#define ASSIGN_FLAG_HOSTIRQ 0x1 + +uint32_t s390_pci_get_fh(PCIHostDeviceAddress host) +{ +char fh_path[128]; +struct stat st; +FILE *fd; +uint32_t fh; + +snprintf(fh_path, sizeof(fh_path), +/sys/bus/pci/devices/%04x:%02x:%02x.%x/function_handle, +host.domain, host.bus, host.slot, host.function); + +if (stat(fh_path, st)) { +error_report(get function handle faild: no host device specified); +return -1; +} + +fd = fopen(fh_path, r); +if (fd == NULL) { +error_report(%s: %s: %m, __func__, fh_path); +return 0; +} +if (fscanf(fd, %x, fh) != 1) { +fclose(fd); +return 0; +} +fclose(fd); +return fh; +} + +uint32_t s390_pci_get_fid(PCIHostDeviceAddress host) +{ +char fid_path[128]; +struct stat st; +FILE *fd; +uint32_t fid; + +snprintf(fid_path, sizeof(fid_path), +/sys/bus/pci/devices/%04x:%02x:%02x.%x/function_id, +host.domain, host.bus, host.slot, host.function); + +if (stat(fid_path, st)) { +error_report(get function id faild: no host device specified); +return -1; +} + +fd = fopen(fid_path, r); +if (fd == NULL) { +error_report(%s: %s: %m, __func__, fid_path); +return -1; +} +if (fscanf(fd, %x, fid) != 1) { +fclose(fd); +return -1; +} +fclose(fd); +return fid; +} + +static int get_real_id(const char *devpath, const char *idname, uint16_t *val) +{ +FILE *f; +char name[128]; +long id; + +snprintf(name, sizeof(name), %s%s, devpath, idname); +f = fopen(name, r); +if (f == NULL) { +error_report(%s: %s: %m, __func__, name); +return -1; +} +if (fscanf(f, %li\n, id) == 1) { +*val = id; +} else { +fclose(f); +return -1; +} +fclose(f); + +return 0; +} + +static int get_real_vendor_id(const char *devpath, uint16_t *val) +{ +return get_real_id(devpath, vendor, val); +} + +static int get_real_device_id(const char *devpath, uint16_t *val) +{ +return get_real_id(devpath, device, val); +} + +static void assign_failed_examine(S390PCIDevice *dev) +{ +char name[PATH_MAX], dir[PATH_MAX], driver
[Qemu-devel] [RFC][patch 5/6] s390: Add PCI bus support
From: Frank Blaschka frank.blasc...@de.ibm.com This patch implements a pci bus for s390x together with some infrastructure to generate and handle hotplug events. It also provides device configuration/unconfiguration via sclp instruction interception. Signed-off-by: Frank Blaschka frank.blasc...@de.ibm.com --- default-configs/s390x-softmmu.mak |1 hw/s390x/Makefile.objs|1 hw/s390x/css.c|5 hw/s390x/css.h|1 hw/s390x/s390-pci-bus.c | 287 ++ hw/s390x/s390-pci-bus.h | 139 ++ hw/s390x/s390-virtio-ccw.c|2 hw/s390x/sclp.c | 10 + include/hw/s390x/sclp.h |8 + target-s390x/Makefile.objs|2 target-s390x/ioinst.c | 52 ++ target-s390x/ioinst.h |1 target-s390x/kvm.c|5 target-s390x/pci_ic.c | 230 ++ target-s390x/pci_ic.h | 214 15 files changed, 956 insertions(+), 2 deletions(-) --- a/default-configs/s390x-softmmu.mak +++ b/default-configs/s390x-softmmu.mak @@ -1,4 +1,5 @@ CONFIG_VIRTIO=y +CONFIG_PCI=y CONFIG_SCLPCONSOLE=y CONFIG_S390_FLIC=y CONFIG_S390_FLIC_KVM=$(CONFIG_KVM) --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -8,3 +8,4 @@ obj-y += ipl.o obj-y += css.o obj-y += s390-virtio-ccw.o obj-y += virtio-ccw.o +obj-$(CONFIG_KVM) += s390-pci-bus.o --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1281,6 +1281,11 @@ void css_generate_chp_crws(uint8_t cssid /* TODO */ } +void css_generate_css_crws(uint8_t cssid) +{ +css_queue_crw(CRW_RSC_CSS, 0, 0, 0); +} + int css_enable_mcsse(void) { trace_css_enable_facility(mcsse); --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -99,6 +99,7 @@ void css_queue_crw(uint8_t rsc, uint8_t void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid, int hotplugged, int add); void css_generate_chp_crws(uint8_t cssid, uint8_t chpid); +void css_generate_css_crws(uint8_t cssid); void css_adapter_interrupt(uint8_t isc); #define CSS_IO_ADAPTER_VIRTIO 1 --- /dev/null +++ b/hw/s390x/s390-pci-bus.c @@ -0,0 +1,287 @@ +/* + * s390 PCI BUS + * + * Copyright 2014 IBM Corp. + * Author(s): Frank Blaschka frank.blasc...@de.ibm.com + *Hong Bo Li lih...@cn.ibm.com + *Yi Min Zhao zyi...@cn.ibm.com + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include hw/pci/pci.h +#include hw/s390x/css.h +#include hw/s390x/sclp.h +#include qemu/error-report.h +#include s390-pci-bus.h + +/* #define DEBUG_S390PCI_BUS */ +#ifdef DEBUG_S390PCI_BUS +#define DPRINTF(fmt, ...) \ +do { fprintf(stderr, S390pci-bus: fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ +do { } while (0) +#endif + +static QTAILQ_HEAD(, SeiContainer) pending_sei = +QTAILQ_HEAD_INITIALIZER(pending_sei); +static QTAILQ_HEAD(, S390PCIBusDevice) device_list = +QTAILQ_HEAD_INITIALIZER(device_list); + +int chsc_sei_nt2_get_event(void *res) +{ +ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res; +PciCcdfAvail *accdf; +PciCcdfErr *eccdf; +int rc = 1; +SeiContainer *sei_cont; + +sei_cont = QTAILQ_FIRST(pending_sei); +if (sei_cont) { +QTAILQ_REMOVE(pending_sei, sei_cont, link); +nt2_res-nt = 2; +nt2_res-cc = sei_cont-cc; +switch (sei_cont-cc) { +case 1: /* error event */ +eccdf = (PciCcdfErr *)nt2_res-ccdf; +eccdf-fid = cpu_to_be32(sei_cont-fid); +eccdf-fh = cpu_to_be32(sei_cont-fh); +break; +case 2: /* availability event */ +accdf = (PciCcdfAvail *)nt2_res-ccdf; +accdf-fid = cpu_to_be32(sei_cont-fid); +accdf-fh = cpu_to_be32(sei_cont-fh); +accdf-pec = cpu_to_be16(sei_cont-pec); +break; +default: +abort(); +} +g_free(sei_cont); +rc = 0; +} + +return rc; +} + +int chsc_sei_nt2_have_event(void) +{ +return !QTAILQ_EMPTY(pending_sei); +} + +static S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid) +{ +S390PCIBusDevice *pbdev; + +QTAILQ_FOREACH(pbdev, device_list, next) { +if (pbdev-fid == fid) { +return pbdev; +} +} +return NULL; +} + +void s390_pci_sclp_configure(int configure, SCCB *sccb) +{ +PciCfgSccb *psccb = (PciCfgSccb *)sccb; +S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(be32_to_cpu(psccb-aid)); +uint16_t rc; + +if (pbdev) { +if ((configure == 1 pbdev-configured == true) || +(configure == 0 pbdev-configured == false)) { +rc = SCLP_RC_NO_ACTION_REQUIRED; +} else { +pbdev-configured