All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/13] basic channel IO passthrough infrastructure based on vfio
@ 2017-04-28 13:09 ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

The patch series introduce a basic channel I/O passthrough
infrastructure based on vfio.
- Focus on supporting dasd-eckd(cu_type/dev_type = 0x3990/0x3390) as
  the target device. 
- Support new qemu parameters in the style of:
    -machine s390-ccw-virtio(,s390-squash-mcss=on|off) \
    -device vfio-ccw,sysfsdev=$MDEV_PATH
  We want to support real (i.e. not virtual) channel devices even for
  guests that do not support MCSS-E (where guests may see devices from
  any channel subsystem image at once). As all virtio-ccw devices are in
  css 0xfe (and show up in the default css 0 for guests not activating
  MCSS-E), we need an option to squash e.g. passed-through channel devices
  from their real css (0-3, or 0 for hosts not activating MCSS-E) into
  the default css, that is what the new machine option s390-squash-css is
  added.

Build and install:
1. kernel configuration
  CONFIG_S390_CCW_IOMMU=m
  CONFIG_VFIO=m
  CONFIG_VFIO_MDEV=m
  CONFIG_VFIO_MDEV_DEVICE=m
  CONFIG_VFIO_CCW=m
2. modules required
  modprobe vfio.ko
  modprobe mdev.ko
  modprobe vfio_mdev.ko
  modprobe vfio_iommu_type1.ko
  modprobe vfio_ccw.ko
3. find a subchannel(0.0."%schid") of a DASD-ECKD device and bind it to
  vfio_ccw driver
  #find the dasd you can use with lsdasd on your host. e.g.:
  devno="7e52"
  schid="16ca"
  #unbind the ccw device from the subchannel
  echo 0.0."$devno" > /sys/bus/ccw/devices/0.0."$devno"/driver/unbind
  #unbind the subchannel from io_subchannel driver
  echo 0.0."$schid" > /sys/bus/css/devices/0.0."$schid"/driver/unbind
  #bind the subchannel with vfio_ccw driver
  echo 0.0."$schid" > /sys/bus/css/drivers/vfio_ccw/bind
4. create a mediated device
  #generate a uuid with uuidgen. e.g.:
  uuid="6dfd3ec5-e8b3-4e18-a6fe-57bc9eceb920"
  echo "$uuid" > \
  /sys/bus/css/devices/0.0."$schid"/mdev_supported_types/vfio_ccw-io/create
5. pass-through this device to a vm
  -M s390-ccw-virtio,s390-squash-css=on \
  -device vfio-ccw,sysfsdev=/sys/bus/mdev/devices/$uuid \
  ... ...

Change log:
v5 -> v6:
1. Rebase against git://github.com/cohuck/qemu s390-next.
2. Patch #6: correct error message: -vfio-ccw --> -device vfio-ccw
3. Patch #7:
   Rewrite vfio_ccw_get_group by:
     - removing unnecessary checking of path existance;
     - removing useless 'path' variable;
   Fix a typo: s/operationis/operations/
   In vfio_ccw_unrealize, move cdc->unrealize to the end.

v4 -> v5:
1. Rebase to git://github.com/cohuck/qemu s390-next.
2. New patch #1: update-linux-headers.
3. Patch #6: update s390_ccw_realize according to the new code base.
4. New patch #13: add maintainer for vfio-ccw.

v3 -> v4:
1. Adjustments of the s-o-b chains for some patches.

v2 -> v3:
1. Move vfio_ccw.h to uapi.
2. Adopt the vfio-ccw cmdline interface as vfio-pci with mdev devices.
3. Rename s390-map-css to s390-squash-mcss (patch 2), and update devno
   generation method (patch 5).
4. Patch 7: correct the validation of num_regions.
5. Patch 8: correct the validation of num_irqs.

v1 -> v2:
1. Rebase the implementation to the mdev framework approach.
2. Use pread and pwrite on an I/O region to issue I/O requests and
   receive results.

Dong Jia Shi (8):
  update-linux-headers: update for vfio-ccw
  vfio: linux-headers update for vfio-ccw
  s390x/css: realize css_create_sch
  s390x/css: device support for s390-ccw passthrough
  vfio/ccw: get io region info
  vfio/ccw: get irqs info and set the eventfd fd
  vfio/ccw: update sense data if a unit check is pending
  MAINTAINERS: Add vfio-ccw maintainer

Xiao Feng Ren (5):
  s390x/css: add s390-squash-mcss machine option
  s390x/css: realize css_sch_build_schib
  vfio/ccw: vfio based subchannel passthrough driver
  s390x/css: introduce and realize ccw-request callback
  s390x/css: ccw translation infrastructure

 MAINTAINERS                        |   5 +
 default-configs/s390x-softmmu.mak  |   1 +
 hw/s390x/Makefile.objs             |   1 +
 hw/s390x/css-bridge.c              |   2 +
 hw/s390x/css.c                     | 290 +++++++++++++++++++++++--
 hw/s390x/s390-ccw.c                | 147 +++++++++++++
 hw/s390x/s390-ccw.h                |  39 ++++
 hw/s390x/s390-virtio-ccw.c         |  33 ++-
 hw/s390x/virtio-ccw.c              |   7 +-
 hw/vfio/Makefile.objs              |   1 +
 hw/vfio/ccw.c                      | 423 +++++++++++++++++++++++++++++++++++++
 include/hw/s390x/css-bridge.h      |   1 +
 include/hw/s390x/css.h             |  67 +++---
 include/hw/s390x/s390-virtio-ccw.h |   1 +
 include/hw/vfio/vfio-common.h      |   1 +
 linux-headers/linux/vfio.h         |  17 ++
 linux-headers/linux/vfio_ccw.h     |  28 +++
 qemu-options.hx                    |   6 +-
 scripts/update-linux-headers.sh    |   2 +-
 target/s390x/cpu.h                 |  10 +
 target/s390x/ioinst.c              |   9 +
 21 files changed, 1042 insertions(+), 49 deletions(-)
 create mode 100644 hw/s390x/s390-ccw.c
 create mode 100644 hw/s390x/s390-ccw.h
 create mode 100644 hw/vfio/ccw.c
 create mode 100644 linux-headers/linux/vfio_ccw.h

-- 
2.10.2

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 00/13] basic channel IO passthrough infrastructure based on vfio
@ 2017-04-28 13:09 ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

The patch series introduce a basic channel I/O passthrough
infrastructure based on vfio.
- Focus on supporting dasd-eckd(cu_type/dev_type = 0x3990/0x3390) as
  the target device. 
- Support new qemu parameters in the style of:
    -machine s390-ccw-virtio(,s390-squash-mcss=on|off) \
    -device vfio-ccw,sysfsdev=$MDEV_PATH
  We want to support real (i.e. not virtual) channel devices even for
  guests that do not support MCSS-E (where guests may see devices from
  any channel subsystem image at once). As all virtio-ccw devices are in
  css 0xfe (and show up in the default css 0 for guests not activating
  MCSS-E), we need an option to squash e.g. passed-through channel devices
  from their real css (0-3, or 0 for hosts not activating MCSS-E) into
  the default css, that is what the new machine option s390-squash-css is
  added.

Build and install:
1. kernel configuration
  CONFIG_S390_CCW_IOMMU=m
  CONFIG_VFIO=m
  CONFIG_VFIO_MDEV=m
  CONFIG_VFIO_MDEV_DEVICE=m
  CONFIG_VFIO_CCW=m
2. modules required
  modprobe vfio.ko
  modprobe mdev.ko
  modprobe vfio_mdev.ko
  modprobe vfio_iommu_type1.ko
  modprobe vfio_ccw.ko
3. find a subchannel(0.0."%schid") of a DASD-ECKD device and bind it to
  vfio_ccw driver
  #find the dasd you can use with lsdasd on your host. e.g.:
  devno="7e52"
  schid="16ca"
  #unbind the ccw device from the subchannel
  echo 0.0."$devno" > /sys/bus/ccw/devices/0.0."$devno"/driver/unbind
  #unbind the subchannel from io_subchannel driver
  echo 0.0."$schid" > /sys/bus/css/devices/0.0."$schid"/driver/unbind
  #bind the subchannel with vfio_ccw driver
  echo 0.0."$schid" > /sys/bus/css/drivers/vfio_ccw/bind
4. create a mediated device
  #generate a uuid with uuidgen. e.g.:
  uuid="6dfd3ec5-e8b3-4e18-a6fe-57bc9eceb920"
  echo "$uuid" > \
  /sys/bus/css/devices/0.0."$schid"/mdev_supported_types/vfio_ccw-io/create
5. pass-through this device to a vm
  -M s390-ccw-virtio,s390-squash-css=on \
  -device vfio-ccw,sysfsdev=/sys/bus/mdev/devices/$uuid \
  ... ...

Change log:
v5 -> v6:
1. Rebase against git://github.com/cohuck/qemu s390-next.
2. Patch #6: correct error message: -vfio-ccw --> -device vfio-ccw
3. Patch #7:
   Rewrite vfio_ccw_get_group by:
     - removing unnecessary checking of path existance;
     - removing useless 'path' variable;
   Fix a typo: s/operationis/operations/
   In vfio_ccw_unrealize, move cdc->unrealize to the end.

v4 -> v5:
1. Rebase to git://github.com/cohuck/qemu s390-next.
2. New patch #1: update-linux-headers.
3. Patch #6: update s390_ccw_realize according to the new code base.
4. New patch #13: add maintainer for vfio-ccw.

v3 -> v4:
1. Adjustments of the s-o-b chains for some patches.

v2 -> v3:
1. Move vfio_ccw.h to uapi.
2. Adopt the vfio-ccw cmdline interface as vfio-pci with mdev devices.
3. Rename s390-map-css to s390-squash-mcss (patch 2), and update devno
   generation method (patch 5).
4. Patch 7: correct the validation of num_regions.
5. Patch 8: correct the validation of num_irqs.

v1 -> v2:
1. Rebase the implementation to the mdev framework approach.
2. Use pread and pwrite on an I/O region to issue I/O requests and
   receive results.

Dong Jia Shi (8):
  update-linux-headers: update for vfio-ccw
  vfio: linux-headers update for vfio-ccw
  s390x/css: realize css_create_sch
  s390x/css: device support for s390-ccw passthrough
  vfio/ccw: get io region info
  vfio/ccw: get irqs info and set the eventfd fd
  vfio/ccw: update sense data if a unit check is pending
  MAINTAINERS: Add vfio-ccw maintainer

Xiao Feng Ren (5):
  s390x/css: add s390-squash-mcss machine option
  s390x/css: realize css_sch_build_schib
  vfio/ccw: vfio based subchannel passthrough driver
  s390x/css: introduce and realize ccw-request callback
  s390x/css: ccw translation infrastructure

 MAINTAINERS                        |   5 +
 default-configs/s390x-softmmu.mak  |   1 +
 hw/s390x/Makefile.objs             |   1 +
 hw/s390x/css-bridge.c              |   2 +
 hw/s390x/css.c                     | 290 +++++++++++++++++++++++--
 hw/s390x/s390-ccw.c                | 147 +++++++++++++
 hw/s390x/s390-ccw.h                |  39 ++++
 hw/s390x/s390-virtio-ccw.c         |  33 ++-
 hw/s390x/virtio-ccw.c              |   7 +-
 hw/vfio/Makefile.objs              |   1 +
 hw/vfio/ccw.c                      | 423 +++++++++++++++++++++++++++++++++++++
 include/hw/s390x/css-bridge.h      |   1 +
 include/hw/s390x/css.h             |  67 +++---
 include/hw/s390x/s390-virtio-ccw.h |   1 +
 include/hw/vfio/vfio-common.h      |   1 +
 linux-headers/linux/vfio.h         |  17 ++
 linux-headers/linux/vfio_ccw.h     |  28 +++
 qemu-options.hx                    |   6 +-
 scripts/update-linux-headers.sh    |   2 +-
 target/s390x/cpu.h                 |  10 +
 target/s390x/ioinst.c              |   9 +
 21 files changed, 1042 insertions(+), 49 deletions(-)
 create mode 100644 hw/s390x/s390-ccw.c
 create mode 100644 hw/s390x/s390-ccw.h
 create mode 100644 hw/vfio/ccw.c
 create mode 100644 linux-headers/linux/vfio_ccw.h

-- 
2.10.2

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 01/13] update-linux-headers: update for vfio-ccw
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Add vfio_ccw.h.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 scripts/update-linux-headers.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index 6a370a8..2f906c4 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -113,7 +113,7 @@ done
 
 rm -rf "$output/linux-headers/linux"
 mkdir -p "$output/linux-headers/linux"
-for header in kvm.h kvm_para.h vfio.h vhost.h \
+for header in kvm.h kvm_para.h vfio.h vfio_ccw.h vhost.h \
               psci.h userfaultfd.h; do
     cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
 done
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 01/13] update-linux-headers: update for vfio-ccw
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Add vfio_ccw.h.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 scripts/update-linux-headers.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index 6a370a8..2f906c4 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -113,7 +113,7 @@ done
 
 rm -rf "$output/linux-headers/linux"
 mkdir -p "$output/linux-headers/linux"
-for header in kvm.h kvm_para.h vfio.h vhost.h \
+for header in kvm.h kvm_para.h vfio.h vfio_ccw.h vhost.h \
               psci.h userfaultfd.h; do
     cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
 done
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 02/13] vfio: linux-headers update for vfio-ccw
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

This is a placeholder for a linux-headers update.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 linux-headers/linux/vfio.h     | 17 +++++++++++++++++
 linux-headers/linux/vfio_ccw.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 linux-headers/linux/vfio_ccw.h

diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 531cb2e..39a1d3b 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -198,6 +198,7 @@ struct vfio_device_info {
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
 #define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 #define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)	/* vfio-amba device */
+#define VFIO_DEVICE_FLAGS_CCW   (1 << 4)	/* vfio-ccw device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
@@ -446,6 +447,22 @@ enum {
 	VFIO_PCI_NUM_IRQS
 };
 
+/*
+ * The VFIO-CCW bus driver makes use of the following fixed region and
+ * IRQ index mapping.  Unimplemented regions return a size of zero.
+ * Unimplemented IRQ types return a count of zero.
+ */
+
+enum {
+        VFIO_CCW_CONFIG_REGION_INDEX,
+        VFIO_CCW_NUM_REGIONS
+};
+
+enum {
+        VFIO_CCW_IO_IRQ_INDEX,
+        VFIO_CCW_NUM_IRQS
+};
+
 /**
  * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IORW(VFIO_TYPE, VFIO_BASE + 12,
  *					      struct vfio_pci_hot_reset_info)
diff --git a/linux-headers/linux/vfio_ccw.h b/linux-headers/linux/vfio_ccw.h
new file mode 100644
index 0000000..4ee74ae
--- /dev/null
+++ b/linux-headers/linux/vfio_ccw.h
@@ -0,0 +1,28 @@
+/*
+ * Interfaces for vfio-ccw
+ *
+ * Copyright IBM Corp. 2017
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ */
+
+#ifndef _VFIO_CCW_H_
+#define _VFIO_CCW_H_
+
+#include <linux/types.h>
+
+struct ccw_io_region {
+#define ORB_AREA_SIZE 12
+	__u8	orb_area[ORB_AREA_SIZE];
+#define SCSW_AREA_SIZE 12
+	__u8	scsw_area[SCSW_AREA_SIZE];
+#define IRB_AREA_SIZE 96
+	__u8	irb_area[IRB_AREA_SIZE];
+	__u32	ret_code;
+} __packed;
+
+#endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 02/13] vfio: linux-headers update for vfio-ccw
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

This is a placeholder for a linux-headers update.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 linux-headers/linux/vfio.h     | 17 +++++++++++++++++
 linux-headers/linux/vfio_ccw.h | 28 ++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+)
 create mode 100644 linux-headers/linux/vfio_ccw.h

diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
index 531cb2e..39a1d3b 100644
--- a/linux-headers/linux/vfio.h
+++ b/linux-headers/linux/vfio.h
@@ -198,6 +198,7 @@ struct vfio_device_info {
 #define VFIO_DEVICE_FLAGS_PCI	(1 << 1)	/* vfio-pci device */
 #define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)	/* vfio-platform device */
 #define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)	/* vfio-amba device */
+#define VFIO_DEVICE_FLAGS_CCW   (1 << 4)	/* vfio-ccw device */
 	__u32	num_regions;	/* Max region index + 1 */
 	__u32	num_irqs;	/* Max IRQ index + 1 */
 };
@@ -446,6 +447,22 @@ enum {
 	VFIO_PCI_NUM_IRQS
 };
 
+/*
+ * The VFIO-CCW bus driver makes use of the following fixed region and
+ * IRQ index mapping.  Unimplemented regions return a size of zero.
+ * Unimplemented IRQ types return a count of zero.
+ */
+
+enum {
+        VFIO_CCW_CONFIG_REGION_INDEX,
+        VFIO_CCW_NUM_REGIONS
+};
+
+enum {
+        VFIO_CCW_IO_IRQ_INDEX,
+        VFIO_CCW_NUM_IRQS
+};
+
 /**
  * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IORW(VFIO_TYPE, VFIO_BASE + 12,
  *					      struct vfio_pci_hot_reset_info)
diff --git a/linux-headers/linux/vfio_ccw.h b/linux-headers/linux/vfio_ccw.h
new file mode 100644
index 0000000..4ee74ae
--- /dev/null
+++ b/linux-headers/linux/vfio_ccw.h
@@ -0,0 +1,28 @@
+/*
+ * Interfaces for vfio-ccw
+ *
+ * Copyright IBM Corp. 2017
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ */
+
+#ifndef _VFIO_CCW_H_
+#define _VFIO_CCW_H_
+
+#include <linux/types.h>
+
+struct ccw_io_region {
+#define ORB_AREA_SIZE 12
+	__u8	orb_area[ORB_AREA_SIZE];
+#define SCSW_AREA_SIZE 12
+	__u8	scsw_area[SCSW_AREA_SIZE];
+#define IRB_AREA_SIZE 96
+	__u8	irb_area[IRB_AREA_SIZE];
+	__u32	ret_code;
+} __packed;
+
+#endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 03/13] s390x/css: add s390-squash-mcss machine option
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

We want to support real (i.e. not virtual) channel devices
even for guests that do not support MCSS-E (where guests may
see devices from any channel subsystem image at once). As all
virtio-ccw devices are in css 0xfe (and show up in the default
css 0 for guests not activating MCSS-E), we need an option to
squash both the virtio subchannels and e.g. passed-through
subchannels from their real css (0-3, or 0 for hosts not
activating MCSS-E) into the default css. This will be
exploited in a later patch.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/s390-virtio-ccw.c         | 21 +++++++++++++++++++++
 include/hw/s390x/s390-virtio-ccw.h |  1 +
 qemu-options.hx                    |  6 +++++-
 target/s390x/cpu.h                 | 10 ++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index fdd4384..cd007ca 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -303,6 +303,20 @@ static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
         ms->loadparm[i] = ' '; /* pad right with spaces */
     }
 }
+static inline bool machine_get_squash_mcss(Object *obj, Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+    return ms->s390_squash_mcss;
+}
+
+static inline void machine_set_squash_mcss(Object *obj, bool value,
+                                           Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+    ms->s390_squash_mcss = value;
+}
 
 static inline void s390_machine_initfn(Object *obj)
 {
@@ -328,6 +342,13 @@ static inline void s390_machine_initfn(Object *obj)
             " to upper case) to pass to machine loader, boot manager,"
             " and guest kernel",
             NULL);
+    object_property_add_bool(obj, "s390-squash-mcss",
+                             machine_get_squash_mcss,
+                             machine_set_squash_mcss, NULL);
+    object_property_set_description(obj, "s390-squash-mcss",
+            "enable/disable squashing subchannels into the default css",
+            NULL);
+    object_property_set_bool(obj, false, "s390-squash-mcss", NULL);
 }
 
 static const TypeInfo ccw_machine_info = {
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index 7b8a3e4..3027555 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -29,6 +29,7 @@ typedef struct S390CcwMachineState {
     bool aes_key_wrap;
     bool dea_key_wrap;
     uint8_t loadparm[8];
+    bool s390_squash_mcss;
 } S390CcwMachineState;
 
 typedef struct S390CcwMachineClass {
diff --git a/qemu-options.hx b/qemu-options.hx
index 9171bd5..2ba4379 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -42,7 +42,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
     "                dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
     "                suppress-vmdesc=on|off disables self-describing migration (default=off)\n"
     "                nvdimm=on|off controls NVDIMM support (default=off)\n"
-    "                enforce-config-section=on|off enforce configuration section migration (default=off)\n",
+    "                enforce-config-section=on|off enforce configuration section migration (default=off)\n"
+    "                s390-squash-mcss=on|off controls support for squashing into default css (default=off)\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -machine [type=]@var{name}[,prop=@var{value}[,...]]
@@ -81,6 +82,9 @@ controls whether DEA wrapping keys will be created to allow
 execution of DEA cryptographic functions.  The default is on.
 @item nvdimm=on|off
 Enables or disables NVDIMM support. The default is off.
+@item s390-squash-mcss=on|off
+Enables or disables squashing subchannels into the default css.
+The default is off.
 @end table
 ETEXI
 
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 058ddad..c367891 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -1250,6 +1250,16 @@ static inline void s390_crypto_reset(void)
     }
 }
 
+static inline bool s390_get_squash_mcss(void)
+{
+    if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
+                                 NULL)) {
+        return true;
+    }
+
+    return false;
+}
+
 /* machine check interruption code */
 
 /* subclasses */
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 03/13] s390x/css: add s390-squash-mcss machine option
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

We want to support real (i.e. not virtual) channel devices
even for guests that do not support MCSS-E (where guests may
see devices from any channel subsystem image at once). As all
virtio-ccw devices are in css 0xfe (and show up in the default
css 0 for guests not activating MCSS-E), we need an option to
squash both the virtio subchannels and e.g. passed-through
subchannels from their real css (0-3, or 0 for hosts not
activating MCSS-E) into the default css. This will be
exploited in a later patch.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/s390-virtio-ccw.c         | 21 +++++++++++++++++++++
 include/hw/s390x/s390-virtio-ccw.h |  1 +
 qemu-options.hx                    |  6 +++++-
 target/s390x/cpu.h                 | 10 ++++++++++
 4 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index fdd4384..cd007ca 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -303,6 +303,20 @@ static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
         ms->loadparm[i] = ' '; /* pad right with spaces */
     }
 }
+static inline bool machine_get_squash_mcss(Object *obj, Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+    return ms->s390_squash_mcss;
+}
+
+static inline void machine_set_squash_mcss(Object *obj, bool value,
+                                           Error **errp)
+{
+    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
+
+    ms->s390_squash_mcss = value;
+}
 
 static inline void s390_machine_initfn(Object *obj)
 {
@@ -328,6 +342,13 @@ static inline void s390_machine_initfn(Object *obj)
             " to upper case) to pass to machine loader, boot manager,"
             " and guest kernel",
             NULL);
+    object_property_add_bool(obj, "s390-squash-mcss",
+                             machine_get_squash_mcss,
+                             machine_set_squash_mcss, NULL);
+    object_property_set_description(obj, "s390-squash-mcss",
+            "enable/disable squashing subchannels into the default css",
+            NULL);
+    object_property_set_bool(obj, false, "s390-squash-mcss", NULL);
 }
 
 static const TypeInfo ccw_machine_info = {
diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h
index 7b8a3e4..3027555 100644
--- a/include/hw/s390x/s390-virtio-ccw.h
+++ b/include/hw/s390x/s390-virtio-ccw.h
@@ -29,6 +29,7 @@ typedef struct S390CcwMachineState {
     bool aes_key_wrap;
     bool dea_key_wrap;
     uint8_t loadparm[8];
+    bool s390_squash_mcss;
 } S390CcwMachineState;
 
 typedef struct S390CcwMachineClass {
diff --git a/qemu-options.hx b/qemu-options.hx
index 9171bd5..2ba4379 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -42,7 +42,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
     "                dea-key-wrap=on|off controls support for DEA key wrapping (default=on)\n"
     "                suppress-vmdesc=on|off disables self-describing migration (default=off)\n"
     "                nvdimm=on|off controls NVDIMM support (default=off)\n"
-    "                enforce-config-section=on|off enforce configuration section migration (default=off)\n",
+    "                enforce-config-section=on|off enforce configuration section migration (default=off)\n"
+    "                s390-squash-mcss=on|off controls support for squashing into default css (default=off)\n",
     QEMU_ARCH_ALL)
 STEXI
 @item -machine [type=]@var{name}[,prop=@var{value}[,...]]
@@ -81,6 +82,9 @@ controls whether DEA wrapping keys will be created to allow
 execution of DEA cryptographic functions.  The default is on.
 @item nvdimm=on|off
 Enables or disables NVDIMM support. The default is off.
+@item s390-squash-mcss=on|off
+Enables or disables squashing subchannels into the default css.
+The default is off.
 @end table
 ETEXI
 
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 058ddad..c367891 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -1250,6 +1250,16 @@ static inline void s390_crypto_reset(void)
     }
 }
 
+static inline bool s390_get_squash_mcss(void)
+{
+    if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
+                                 NULL)) {
+        return true;
+    }
+
+    return false;
+}
+
 /* machine check interruption code */
 
 /* subclasses */
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 04/13] s390x/css: realize css_sch_build_schib
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

The S390 virtual css support already has a mechanism to build virtual
Sub-Channel Information Block and provide virtual subchannels to the
guest. However, to pass-through subchannels to a guest, we need to
introduce a new mechanism to build its schib according to the real
device information. Thus we realize a new css_sch_build_schib function
to extract the path_masks, chpids, chpid type from sysfs. To reuse
the existing code, we refactor css_add_virtual_chpid to css_add_chpid.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         | 153 ++++++++++++++++++++++++++++++++++++++++++++++++-
 include/hw/s390x/css.h |  36 ++++++------
 2 files changed, 169 insertions(+), 20 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c03bb20..748e2ad 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -13,6 +13,7 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "hw/qdev.h"
+#include "qemu/error-report.h"
 #include "qemu/bitops.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
@@ -1302,7 +1303,8 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
                                  (MAX_SCHID + 1) / sizeof(unsigned long));
 }
 
-static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
+static int css_add_chpid(uint8_t cssid, uint8_t chpid, uint8_t type,
+                         bool is_virt)
 {
     CssImage *css;
 
@@ -1316,7 +1318,7 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
     }
     css->chpids[chpid].in_use = 1;
     css->chpids[chpid].type = type;
-    css->chpids[chpid].is_virtual = 1;
+    css->chpids[chpid].is_virtual = is_virt;
 
     css_generate_chp_crws(cssid, chpid);
 
@@ -1340,7 +1342,7 @@ void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
     p->pam = 0x80;
     p->chpid[0] = chpid;
     if (!css->chpids[chpid].in_use) {
-        css_add_virtual_chpid(sch->cssid, chpid, type);
+        css_add_chpid(sch->cssid, chpid, type, true);
     }
 
     memset(s, 0, sizeof(SCSW));
@@ -1954,3 +1956,148 @@ SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp)
     css_subch_assign(sch->cssid, sch->ssid, schid, sch->devno, sch);
     return sch;
 }
+
+static int css_sch_get_chpids(SubchDev *sch, CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+    uint32_t chpid[8];
+    int i;
+    PMCW *p = &sch->curr_status.pmcw;
+
+    fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/chpids",
+                               dev_id->cssid, dev_id->ssid, dev_id->devid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x %x %x %x %x %x %x %x",
+        &chpid[0], &chpid[1], &chpid[2], &chpid[3],
+        &chpid[4], &chpid[5], &chpid[6], &chpid[7]) != 8) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
+        p->chpid[i] = chpid[i];
+    }
+
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+static int css_sch_get_path_masks(SubchDev *sch, CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+    uint32_t pim, pam, pom;
+    PMCW *p = &sch->curr_status.pmcw;
+
+    fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/pimpampom",
+                               dev_id->cssid, dev_id->ssid, dev_id->devid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x %x %x", &pim, &pam, &pom) != 3) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    p->pim = pim;
+    p->pam = pam;
+    p->pom = pom;
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+static int css_sch_get_chpid_type(uint8_t chpid, uint32_t *type,
+                                  CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+
+    fid_path = g_strdup_printf("/sys/devices/css%x/chp0.%02x/type",
+                               dev_id->cssid, chpid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x", type) != 1) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+/*
+ * We currently retrieve the real device information from sysfs to build the
+ * guest subchannel information block without considering the migration feature.
+ * If migrate, it won't be sure to use the real device information directly,
+ * this point will be handled in the future.
+ */
+int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id)
+{
+    CssImage *css = channel_subsys.css[sch->cssid];
+    PMCW *p = &sch->curr_status.pmcw;
+    SCSW *s = &sch->curr_status.scsw;
+    uint32_t type;
+    int i, ret;
+
+    /* We are dealing with I/O subchannels only. */
+    assert(css != NULL);
+    memset(p, 0, sizeof(PMCW));
+    p->flags |= PMCW_FLAGS_MASK_DNV;
+    p->devno = sch->devno;
+
+    /* Grab path mask from sysfs. */
+    ret = css_sch_get_path_masks(sch, dev_id);
+    if (ret) {
+        return ret;
+    }
+
+    /* Grab chpids from sysfs. */
+    ret = css_sch_get_chpids(sch, dev_id);
+    if (ret) {
+        return ret;
+    }
+
+   /* Build chpid type. */
+    for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
+        if (p->chpid[i] && !css->chpids[p->chpid[i]].in_use) {
+            ret = css_sch_get_chpid_type(p->chpid[i], &type, dev_id);
+            if (ret) {
+                return ret;
+            }
+            css_add_chpid(sch->cssid, p->chpid[i], type, false);
+        }
+    }
+
+    memset(s, 0, sizeof(SCSW));
+    sch->curr_status.mba = 0;
+    for (i = 0; i < ARRAY_SIZE(sch->curr_status.mda); i++) {
+        sch->curr_status.mda[i] = 0;
+    }
+
+    return 0;
+}
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index f1f0d7f..868c6c7 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -94,6 +94,24 @@ struct SubchDev {
     void *driver_data;
 };
 
+/*
+ * Identify a device within the channel subsystem.
+ * Note that this can be used to identify either the subchannel or
+ * the attached I/O device, as there's always one I/O device per
+ * subchannel.
+ */
+typedef struct CssDevId {
+    uint8_t cssid;
+    uint8_t ssid;
+    uint16_t devid;
+    bool valid;
+} CssDevId;
+
+extern PropertyInfo css_devid_propinfo;
+
+#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
+
 typedef struct IndAddr {
     hwaddr addr;
     uint64_t map;
@@ -115,6 +133,7 @@ bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
 void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
                       uint16_t devno, SubchDev *sch);
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
 uint16_t css_build_subchannel_id(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
@@ -162,23 +181,6 @@ int css_do_rsch(SubchDev *sch);
 int css_do_rchp(uint8_t cssid, uint8_t chpid);
 bool css_present(uint8_t cssid);
 #endif
-/*
- * Identify a device within the channel subsystem.
- * Note that this can be used to identify either the subchannel or
- * the attached I/O device, as there's always one I/O device per
- * subchannel.
- */
-typedef struct CssDevId {
-    uint8_t cssid;
-    uint8_t ssid;
-    uint16_t devid;
-    bool valid;
-} CssDevId;
-
-extern PropertyInfo css_devid_propinfo;
-
-#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
 
 extern PropertyInfo css_devid_ro_propinfo;
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 04/13] s390x/css: realize css_sch_build_schib
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

The S390 virtual css support already has a mechanism to build virtual
Sub-Channel Information Block and provide virtual subchannels to the
guest. However, to pass-through subchannels to a guest, we need to
introduce a new mechanism to build its schib according to the real
device information. Thus we realize a new css_sch_build_schib function
to extract the path_masks, chpids, chpid type from sysfs. To reuse
the existing code, we refactor css_add_virtual_chpid to css_add_chpid.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         | 153 ++++++++++++++++++++++++++++++++++++++++++++++++-
 include/hw/s390x/css.h |  36 ++++++------
 2 files changed, 169 insertions(+), 20 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c03bb20..748e2ad 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -13,6 +13,7 @@
 #include "qapi/error.h"
 #include "qapi/visitor.h"
 #include "hw/qdev.h"
+#include "qemu/error-report.h"
 #include "qemu/bitops.h"
 #include "exec/address-spaces.h"
 #include "cpu.h"
@@ -1302,7 +1303,8 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
                                  (MAX_SCHID + 1) / sizeof(unsigned long));
 }
 
-static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
+static int css_add_chpid(uint8_t cssid, uint8_t chpid, uint8_t type,
+                         bool is_virt)
 {
     CssImage *css;
 
@@ -1316,7 +1318,7 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
     }
     css->chpids[chpid].in_use = 1;
     css->chpids[chpid].type = type;
-    css->chpids[chpid].is_virtual = 1;
+    css->chpids[chpid].is_virtual = is_virt;
 
     css_generate_chp_crws(cssid, chpid);
 
@@ -1340,7 +1342,7 @@ void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
     p->pam = 0x80;
     p->chpid[0] = chpid;
     if (!css->chpids[chpid].in_use) {
-        css_add_virtual_chpid(sch->cssid, chpid, type);
+        css_add_chpid(sch->cssid, chpid, type, true);
     }
 
     memset(s, 0, sizeof(SCSW));
@@ -1954,3 +1956,148 @@ SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp)
     css_subch_assign(sch->cssid, sch->ssid, schid, sch->devno, sch);
     return sch;
 }
+
+static int css_sch_get_chpids(SubchDev *sch, CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+    uint32_t chpid[8];
+    int i;
+    PMCW *p = &sch->curr_status.pmcw;
+
+    fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/chpids",
+                               dev_id->cssid, dev_id->ssid, dev_id->devid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x %x %x %x %x %x %x %x",
+        &chpid[0], &chpid[1], &chpid[2], &chpid[3],
+        &chpid[4], &chpid[5], &chpid[6], &chpid[7]) != 8) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
+        p->chpid[i] = chpid[i];
+    }
+
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+static int css_sch_get_path_masks(SubchDev *sch, CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+    uint32_t pim, pam, pom;
+    PMCW *p = &sch->curr_status.pmcw;
+
+    fid_path = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/pimpampom",
+                               dev_id->cssid, dev_id->ssid, dev_id->devid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x %x %x", &pim, &pam, &pom) != 3) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    p->pim = pim;
+    p->pam = pam;
+    p->pom = pom;
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+static int css_sch_get_chpid_type(uint8_t chpid, uint32_t *type,
+                                  CssDevId *dev_id)
+{
+    char *fid_path;
+    FILE *fd;
+
+    fid_path = g_strdup_printf("/sys/devices/css%x/chp0.%02x/type",
+                               dev_id->cssid, chpid);
+    fd = fopen(fid_path, "r");
+    if (fd == NULL) {
+        error_report("%s: open %s failed", __func__, fid_path);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    if (fscanf(fd, "%x", type) != 1) {
+        fclose(fd);
+        g_free(fid_path);
+        return -EINVAL;
+    }
+
+    fclose(fd);
+    g_free(fid_path);
+
+    return 0;
+}
+
+/*
+ * We currently retrieve the real device information from sysfs to build the
+ * guest subchannel information block without considering the migration feature.
+ * If migrate, it won't be sure to use the real device information directly,
+ * this point will be handled in the future.
+ */
+int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id)
+{
+    CssImage *css = channel_subsys.css[sch->cssid];
+    PMCW *p = &sch->curr_status.pmcw;
+    SCSW *s = &sch->curr_status.scsw;
+    uint32_t type;
+    int i, ret;
+
+    /* We are dealing with I/O subchannels only. */
+    assert(css != NULL);
+    memset(p, 0, sizeof(PMCW));
+    p->flags |= PMCW_FLAGS_MASK_DNV;
+    p->devno = sch->devno;
+
+    /* Grab path mask from sysfs. */
+    ret = css_sch_get_path_masks(sch, dev_id);
+    if (ret) {
+        return ret;
+    }
+
+    /* Grab chpids from sysfs. */
+    ret = css_sch_get_chpids(sch, dev_id);
+    if (ret) {
+        return ret;
+    }
+
+   /* Build chpid type. */
+    for (i = 0; i < ARRAY_SIZE(p->chpid); i++) {
+        if (p->chpid[i] && !css->chpids[p->chpid[i]].in_use) {
+            ret = css_sch_get_chpid_type(p->chpid[i], &type, dev_id);
+            if (ret) {
+                return ret;
+            }
+            css_add_chpid(sch->cssid, p->chpid[i], type, false);
+        }
+    }
+
+    memset(s, 0, sizeof(SCSW));
+    sch->curr_status.mba = 0;
+    for (i = 0; i < ARRAY_SIZE(sch->curr_status.mda); i++) {
+        sch->curr_status.mda[i] = 0;
+    }
+
+    return 0;
+}
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index f1f0d7f..868c6c7 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -94,6 +94,24 @@ struct SubchDev {
     void *driver_data;
 };
 
+/*
+ * Identify a device within the channel subsystem.
+ * Note that this can be used to identify either the subchannel or
+ * the attached I/O device, as there's always one I/O device per
+ * subchannel.
+ */
+typedef struct CssDevId {
+    uint8_t cssid;
+    uint8_t ssid;
+    uint16_t devid;
+    bool valid;
+} CssDevId;
+
+extern PropertyInfo css_devid_propinfo;
+
+#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
+    DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
+
 typedef struct IndAddr {
     hwaddr addr;
     uint64_t map;
@@ -115,6 +133,7 @@ bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
 void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
                       uint16_t devno, SubchDev *sch);
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
 uint16_t css_build_subchannel_id(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
@@ -162,23 +181,6 @@ int css_do_rsch(SubchDev *sch);
 int css_do_rchp(uint8_t cssid, uint8_t chpid);
 bool css_present(uint8_t cssid);
 #endif
-/*
- * Identify a device within the channel subsystem.
- * Note that this can be used to identify either the subchannel or
- * the attached I/O device, as there's always one I/O device per
- * subchannel.
- */
-typedef struct CssDevId {
-    uint8_t cssid;
-    uint8_t ssid;
-    uint16_t devid;
-    bool valid;
-} CssDevId;
-
-extern PropertyInfo css_devid_propinfo;
-
-#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
-    DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
 
 extern PropertyInfo css_devid_ro_propinfo;
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 05/13] s390x/css: realize css_create_sch
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

The S390 virtual css support already has a mechanism to create a
virtual subchannel and provide it to the guest. However, to
pass-through subchannels to a guest, we need to introduce a new
mechanism to create the subchannel according to the real device
information. Thus we reconstruct css_create_virtual_sch to a new
css_create_sch function to handl all these cases and do allocation
and initialization of the subchannel according to the device type
and machine configuration.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css-bridge.c         |  2 ++
 hw/s390x/css.c                | 45 ++++++++++++++++++++++++++++++++++++-------
 hw/s390x/s390-virtio-ccw.c    | 12 +++++++++---
 hw/s390x/virtio-ccw.c         |  6 +++++-
 include/hw/s390x/css-bridge.h |  1 +
 include/hw/s390x/css.h        | 25 ++++++++++++++++--------
 6 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index b54ac01..823747f 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -17,6 +17,7 @@
 #include "hw/s390x/css.h"
 #include "ccw-device.h"
 #include "hw/s390x/css-bridge.h"
+#include "cpu.h"
 
 /*
  * Invoke device-specific unplug handler, disable the subchannel
@@ -103,6 +104,7 @@ VirtualCssBus *virtual_css_bus_init(void)
     /* Create bus on bridge device */
     bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
     cbus = VIRTUAL_CSS_BUS(bus);
+    cbus->squash_mcss = s390_get_squash_mcss();
 
     /* Enable hotplugging */
     qbus_set_hotplug_handler(bus, dev, &error_abort);
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 748e2ad..1052eea 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1924,28 +1924,59 @@ PropertyInfo css_devid_ro_propinfo = {
     .get = get_css_devid,
 };
 
-SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp)
+SubchDev *css_create_sch(CssDevId bus_id, bool is_virtio, bool squash_mcss,
+                         Error **errp)
 {
     uint16_t schid = 0;
     SubchDev *sch;
 
     if (bus_id.valid) {
-        /* Enforce use of virtual cssid. */
-        if (bus_id.cssid != VIRTUAL_CSSID) {
-            error_setg(errp, "cssid %hhx not valid for virtual devices",
-                       bus_id.cssid);
+        if (is_virtio != (bus_id.cssid == VIRTUAL_CSSID)) {
+            error_setg(errp, "cssid %hhx not valid for %s devices",
+                       bus_id.cssid,
+                       (is_virtio ? "virtio" : "non-virtio"));
             return NULL;
         }
+    }
+
+    if (bus_id.valid) {
+        if (squash_mcss) {
+            bus_id.cssid = channel_subsys.default_cssid;
+        } else if (!channel_subsys.css[bus_id.cssid]) {
+            css_create_css_image(bus_id.cssid, false);
+        }
+
         if (!css_find_free_subch_for_devno(bus_id.cssid, bus_id.ssid,
                                            bus_id.devid, &schid, errp)) {
             return NULL;
         }
-    } else {
-        bus_id.cssid = VIRTUAL_CSSID;
+    } else if (squash_mcss || is_virtio) {
+        bus_id.cssid = channel_subsys.default_cssid;
+
         if (!css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid,
                                            &bus_id.devid, &schid, errp)) {
             return NULL;
         }
+    } else {
+        for (bus_id.cssid = 0; bus_id.cssid < MAX_CSSID; ++bus_id.cssid) {
+            if (bus_id.cssid == VIRTUAL_CSSID) {
+                continue;
+            }
+
+            if (!channel_subsys.css[bus_id.cssid]) {
+                css_create_css_image(bus_id.cssid, false);
+            }
+
+            if   (css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid,
+                                                &bus_id.devid, &schid,
+                                                NULL)) {
+                break  ;
+            }
+            if (bus_id.cssid == MAX_CSSID) {
+                error_setg(errp, "Virtual channel subsystem is full!");
+                return NULL;
+            }
+        }
     }
 
     sch = g_malloc0(sizeof(*sch));
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index cd007ca..735d66d 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -136,10 +136,16 @@ static void ccw_init(MachineState *machine)
         kvm_s390_enable_css_support(s390_cpu_addr2state(0));
     }
     /*
-     * Create virtual css and set it as default so that non mcss-e
-     * enabled guests only see virtio devices.
+     * Non mcss-e enabled guests only see the devices from the default
+     * css, which is determined by the value of the squash_mcss property.
+     * Note: we must not squash non virtio devices to css 0xFE, since
+     * it's reserved for virtio devices only.
      */
-    ret = css_create_css_image(VIRTUAL_CSSID, true);
+    if (css_bus->squash_mcss) {
+        ret = css_create_css_image(0, true);
+    } else {
+        ret = css_create_css_image(VIRTUAL_CSSID, true);
+    }
     assert(ret == 0);
 
     /* Create VirtIO network adapters */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e7167e3..4e386e9 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -680,9 +680,13 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
     CcwDevice *ccw_dev = CCW_DEVICE(dev);
     CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
-    SubchDev *sch = css_create_virtual_sch(ccw_dev->devno, errp);
+    DeviceState *parent = DEVICE(ccw_dev);
+    BusState *qbus = qdev_get_parent_bus(parent);
+    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
+    SubchDev *sch;
     Error *err = NULL;
 
+    sch = css_create_sch(ccw_dev->devno, true, cbus->squash_mcss, errp);
     if (!sch) {
         return;
     }
diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h
index 5a0203b..cf08604 100644
--- a/include/hw/s390x/css-bridge.h
+++ b/include/hw/s390x/css-bridge.h
@@ -28,6 +28,7 @@ typedef struct VirtualCssBridge {
 /* virtual css bus type */
 typedef struct VirtualCssBus {
     BusState parent_obj;
+    bool squash_mcss;
 } VirtualCssBus;
 
 #define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus"
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 868c6c7..a8bf1db 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -190,16 +190,25 @@ extern PropertyInfo css_devid_ro_propinfo;
 /**
  * Create a subchannel for the given bus id.
  *
- * If @p bus_id is valid, verify that it uses the virtual channel
- * subsystem id and is not already in use, and find a free subchannel
- * id for it. If @p bus_id is not valid, find a free subchannel id and
- * device number across all subchannel sets. If either of the former
- * actions succeed, allocate a subchannel structure, initialise it
- * with the bus id, subchannel id and device number, register it with
- * the CSS and return it. Otherwise return NULL.
+ * If @p bus_id is valid, and @p squash_mcss is true, verify that it is
+ * not already in use in the default css, and find a free devno from the
+ * default css image for it.
+ * If @p bus_id is valid, and @p squash_mcss is false, verify that it is
+ * not already in use, and find a free devno for it.
+ * If @p bus_id is not valid, and if either @p squash_mcss or @p is_virtio
+ * is true, find a free subchannel id and device number across all
+ * subchannel sets from the default css image.
+ * If @p bus_id is not valid, and if both @p squash_mcss and @p is_virtio
+ * are false, find a non-full css image and find a free subchannel id and
+ * device number across all subchannel sets from it.
+ *
+ * If either of the former actions succeed, allocate a subchannel structure,
+ * initialise it with the bus id, subchannel id and device number, register
+ * it with the CSS and return it. Otherwise return NULL.
  *
  * The caller becomes owner of the returned subchannel structure and
  * is responsible for unregistering and freeing it.
  */
-SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp);
+SubchDev *css_create_sch(CssDevId bus_id, bool is_virtio, bool squash_mcss,
+                         Error **errp);
 #endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 05/13] s390x/css: realize css_create_sch
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

The S390 virtual css support already has a mechanism to create a
virtual subchannel and provide it to the guest. However, to
pass-through subchannels to a guest, we need to introduce a new
mechanism to create the subchannel according to the real device
information. Thus we reconstruct css_create_virtual_sch to a new
css_create_sch function to handl all these cases and do allocation
and initialization of the subchannel according to the device type
and machine configuration.

Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css-bridge.c         |  2 ++
 hw/s390x/css.c                | 45 ++++++++++++++++++++++++++++++++++++-------
 hw/s390x/s390-virtio-ccw.c    | 12 +++++++++---
 hw/s390x/virtio-ccw.c         |  6 +++++-
 include/hw/s390x/css-bridge.h |  1 +
 include/hw/s390x/css.h        | 25 ++++++++++++++++--------
 6 files changed, 72 insertions(+), 19 deletions(-)

diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index b54ac01..823747f 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -17,6 +17,7 @@
 #include "hw/s390x/css.h"
 #include "ccw-device.h"
 #include "hw/s390x/css-bridge.h"
+#include "cpu.h"
 
 /*
  * Invoke device-specific unplug handler, disable the subchannel
@@ -103,6 +104,7 @@ VirtualCssBus *virtual_css_bus_init(void)
     /* Create bus on bridge device */
     bus = qbus_create(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
     cbus = VIRTUAL_CSS_BUS(bus);
+    cbus->squash_mcss = s390_get_squash_mcss();
 
     /* Enable hotplugging */
     qbus_set_hotplug_handler(bus, dev, &error_abort);
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 748e2ad..1052eea 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1924,28 +1924,59 @@ PropertyInfo css_devid_ro_propinfo = {
     .get = get_css_devid,
 };
 
-SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp)
+SubchDev *css_create_sch(CssDevId bus_id, bool is_virtio, bool squash_mcss,
+                         Error **errp)
 {
     uint16_t schid = 0;
     SubchDev *sch;
 
     if (bus_id.valid) {
-        /* Enforce use of virtual cssid. */
-        if (bus_id.cssid != VIRTUAL_CSSID) {
-            error_setg(errp, "cssid %hhx not valid for virtual devices",
-                       bus_id.cssid);
+        if (is_virtio != (bus_id.cssid == VIRTUAL_CSSID)) {
+            error_setg(errp, "cssid %hhx not valid for %s devices",
+                       bus_id.cssid,
+                       (is_virtio ? "virtio" : "non-virtio"));
             return NULL;
         }
+    }
+
+    if (bus_id.valid) {
+        if (squash_mcss) {
+            bus_id.cssid = channel_subsys.default_cssid;
+        } else if (!channel_subsys.css[bus_id.cssid]) {
+            css_create_css_image(bus_id.cssid, false);
+        }
+
         if (!css_find_free_subch_for_devno(bus_id.cssid, bus_id.ssid,
                                            bus_id.devid, &schid, errp)) {
             return NULL;
         }
-    } else {
-        bus_id.cssid = VIRTUAL_CSSID;
+    } else if (squash_mcss || is_virtio) {
+        bus_id.cssid = channel_subsys.default_cssid;
+
         if (!css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid,
                                            &bus_id.devid, &schid, errp)) {
             return NULL;
         }
+    } else {
+        for (bus_id.cssid = 0; bus_id.cssid < MAX_CSSID; ++bus_id.cssid) {
+            if (bus_id.cssid == VIRTUAL_CSSID) {
+                continue;
+            }
+
+            if (!channel_subsys.css[bus_id.cssid]) {
+                css_create_css_image(bus_id.cssid, false);
+            }
+
+            if   (css_find_free_subch_and_devno(bus_id.cssid, &bus_id.ssid,
+                                                &bus_id.devid, &schid,
+                                                NULL)) {
+                break  ;
+            }
+            if (bus_id.cssid == MAX_CSSID) {
+                error_setg(errp, "Virtual channel subsystem is full!");
+                return NULL;
+            }
+        }
     }
 
     sch = g_malloc0(sizeof(*sch));
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index cd007ca..735d66d 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -136,10 +136,16 @@ static void ccw_init(MachineState *machine)
         kvm_s390_enable_css_support(s390_cpu_addr2state(0));
     }
     /*
-     * Create virtual css and set it as default so that non mcss-e
-     * enabled guests only see virtio devices.
+     * Non mcss-e enabled guests only see the devices from the default
+     * css, which is determined by the value of the squash_mcss property.
+     * Note: we must not squash non virtio devices to css 0xFE, since
+     * it's reserved for virtio devices only.
      */
-    ret = css_create_css_image(VIRTUAL_CSSID, true);
+    if (css_bus->squash_mcss) {
+        ret = css_create_css_image(0, true);
+    } else {
+        ret = css_create_css_image(VIRTUAL_CSSID, true);
+    }
     assert(ret == 0);
 
     /* Create VirtIO network adapters */
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e7167e3..4e386e9 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -680,9 +680,13 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
     CcwDevice *ccw_dev = CCW_DEVICE(dev);
     CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
-    SubchDev *sch = css_create_virtual_sch(ccw_dev->devno, errp);
+    DeviceState *parent = DEVICE(ccw_dev);
+    BusState *qbus = qdev_get_parent_bus(parent);
+    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
+    SubchDev *sch;
     Error *err = NULL;
 
+    sch = css_create_sch(ccw_dev->devno, true, cbus->squash_mcss, errp);
     if (!sch) {
         return;
     }
diff --git a/include/hw/s390x/css-bridge.h b/include/hw/s390x/css-bridge.h
index 5a0203b..cf08604 100644
--- a/include/hw/s390x/css-bridge.h
+++ b/include/hw/s390x/css-bridge.h
@@ -28,6 +28,7 @@ typedef struct VirtualCssBridge {
 /* virtual css bus type */
 typedef struct VirtualCssBus {
     BusState parent_obj;
+    bool squash_mcss;
 } VirtualCssBus;
 
 #define TYPE_VIRTUAL_CSS_BUS "virtual-css-bus"
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 868c6c7..a8bf1db 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -190,16 +190,25 @@ extern PropertyInfo css_devid_ro_propinfo;
 /**
  * Create a subchannel for the given bus id.
  *
- * If @p bus_id is valid, verify that it uses the virtual channel
- * subsystem id and is not already in use, and find a free subchannel
- * id for it. If @p bus_id is not valid, find a free subchannel id and
- * device number across all subchannel sets. If either of the former
- * actions succeed, allocate a subchannel structure, initialise it
- * with the bus id, subchannel id and device number, register it with
- * the CSS and return it. Otherwise return NULL.
+ * If @p bus_id is valid, and @p squash_mcss is true, verify that it is
+ * not already in use in the default css, and find a free devno from the
+ * default css image for it.
+ * If @p bus_id is valid, and @p squash_mcss is false, verify that it is
+ * not already in use, and find a free devno for it.
+ * If @p bus_id is not valid, and if either @p squash_mcss or @p is_virtio
+ * is true, find a free subchannel id and device number across all
+ * subchannel sets from the default css image.
+ * If @p bus_id is not valid, and if both @p squash_mcss and @p is_virtio
+ * are false, find a non-full css image and find a free subchannel id and
+ * device number across all subchannel sets from it.
+ *
+ * If either of the former actions succeed, allocate a subchannel structure,
+ * initialise it with the bus id, subchannel id and device number, register
+ * it with the CSS and return it. Otherwise return NULL.
  *
  * The caller becomes owner of the returned subchannel structure and
  * is responsible for unregistering and freeing it.
  */
-SubchDev *css_create_virtual_sch(CssDevId bus_id, Error **errp);
+SubchDev *css_create_sch(CssDevId bus_id, bool is_virtio, bool squash_mcss,
+                         Error **errp);
 #endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

In order to support subchannels pass-through, we introduce a s390
subchannel device called "s390-ccw" to hold the real subchannel info.
The s390-ccw devices inherit from the abstract CcwDevice which connect
to the existing virtual-css-bus.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/Makefile.objs |   1 +
 hw/s390x/s390-ccw.c    | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/s390-ccw.h    |  38 ++++++++++++++
 3 files changed, 174 insertions(+)
 create mode 100644 hw/s390x/s390-ccw.c
 create mode 100644 hw/s390x/s390-ccw.h

diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index 41ac4ec..72a3d37 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -13,3 +13,4 @@ obj-y += ccw-device.o
 obj-y += s390-pci-bus.o s390-pci-inst.o
 obj-y += s390-skeys.o
 obj-$(CONFIG_KVM) += s390-skeys-kvm.o
+obj-y += s390-ccw.o
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
new file mode 100644
index 0000000..8b4b9cf
--- /dev/null
+++ b/hw/s390x/s390-ccw.c
@@ -0,0 +1,135 @@
+/*
+ * s390 CCW Assignment Support
+ *
+ * Copyright 2017 IBM Corp
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "libgen.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/css-bridge.h"
+#include "s390-ccw.h"
+
+static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
+                                  char *sysfsdev,
+                                  Error **errp)
+{
+    unsigned int cssid, ssid, devid;
+    char dev_path[PATH_MAX] = {0}, *tmp;
+
+    if (!sysfsdev) {
+        error_setg(errp, "No host device provided");
+        error_append_hint(errp,
+                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
+        return;
+    }
+
+    if (!realpath(sysfsdev, dev_path)) {
+        error_setg(errp, "Host device '%s' not found", sysfsdev);
+        return;
+    }
+
+    cdev->mdevid = g_strdup(basename(dev_path));
+
+    tmp = basename(dirname(dev_path));
+    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
+
+    cdev->hostid.cssid = cssid;
+    cdev->hostid.ssid = ssid;
+    cdev->hostid.devid = devid;
+    cdev->hostid.valid = true;
+}
+
+static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
+    DeviceState *parent = DEVICE(ccw_dev);
+    BusState *qbus = qdev_get_parent_bus(parent);
+    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
+    SubchDev *sch;
+    int ret;
+    Error *err = NULL;
+
+    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
+    if (*errp) {
+        return;
+    }
+
+    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
+    if (!sch) {
+        return;
+    }
+    sch->driver_data = cdev;
+
+    ccw_dev->sch = sch;
+    ret = css_sch_build_schib(sch, &cdev->hostid);
+    if (ret) {
+        error_setg(&err, "%s: Failed to build initial schib: %d",
+                   __func__, ret);
+        goto out_err;
+    }
+
+    ck->realize(ccw_dev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
+                          parent->hotplugged, 1);
+    return;
+
+out_err:
+    error_propagate(errp, err);
+    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+    ccw_dev->sch = NULL;
+    g_free(sch);
+}
+
+static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    SubchDev *sch = ccw_dev->sch;
+
+    if (sch) {
+        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+        g_free(sch);
+        ccw_dev->sch = NULL;
+    }
+
+    g_free(cdev->mdevid);
+}
+
+static void s390_ccw_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_CLASS(klass);
+
+    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
+    cdc->realize = s390_ccw_realize;
+    cdc->unrealize = s390_ccw_unrealize;
+}
+
+static const TypeInfo s390_ccw_info = {
+    .name          = TYPE_S390_CCW,
+    .parent        = TYPE_CCW_DEVICE,
+    .instance_size = sizeof(S390CCWDevice),
+    .class_size    = sizeof(S390CCWDeviceClass),
+    .class_init    = s390_ccw_class_init,
+    .abstract      = true,
+};
+
+static void register_s390_ccw_type(void)
+{
+    type_register_static(&s390_ccw_info);
+}
+
+type_init(register_s390_ccw_type)
diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
new file mode 100644
index 0000000..b58d8e9
--- /dev/null
+++ b/hw/s390x/s390-ccw.h
@@ -0,0 +1,38 @@
+/*
+ * s390 CCW Assignment Support
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.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.
+ */
+
+#ifndef HW_S390_CCW_H
+#define HW_S390_CCW_H
+
+#include "hw/s390x/ccw-device.h"
+
+#define TYPE_S390_CCW "s390-ccw"
+#define S390_CCW_DEVICE(obj) \
+    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
+#define S390_CCW_DEVICE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
+#define S390_CCW_DEVICE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
+
+typedef struct S390CCWDevice {
+    CcwDevice parent_obj;
+    CssDevId hostid;
+    char *mdevid;
+} S390CCWDevice;
+
+typedef struct S390CCWDeviceClass {
+    CCWDeviceClass parent_class;
+    void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
+    void (*unrealize)(S390CCWDevice *dev, Error **errp);
+} S390CCWDeviceClass;
+
+#endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

In order to support subchannels pass-through, we introduce a s390
subchannel device called "s390-ccw" to hold the real subchannel info.
The s390-ccw devices inherit from the abstract CcwDevice which connect
to the existing virtual-css-bus.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/Makefile.objs |   1 +
 hw/s390x/s390-ccw.c    | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/s390-ccw.h    |  38 ++++++++++++++
 3 files changed, 174 insertions(+)
 create mode 100644 hw/s390x/s390-ccw.c
 create mode 100644 hw/s390x/s390-ccw.h

diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index 41ac4ec..72a3d37 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -13,3 +13,4 @@ obj-y += ccw-device.o
 obj-y += s390-pci-bus.o s390-pci-inst.o
 obj-y += s390-skeys.o
 obj-$(CONFIG_KVM) += s390-skeys-kvm.o
+obj-y += s390-ccw.o
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
new file mode 100644
index 0000000..8b4b9cf
--- /dev/null
+++ b/hw/s390x/s390-ccw.c
@@ -0,0 +1,135 @@
+/*
+ * s390 CCW Assignment Support
+ *
+ * Copyright 2017 IBM Corp
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "libgen.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/css-bridge.h"
+#include "s390-ccw.h"
+
+static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
+                                  char *sysfsdev,
+                                  Error **errp)
+{
+    unsigned int cssid, ssid, devid;
+    char dev_path[PATH_MAX] = {0}, *tmp;
+
+    if (!sysfsdev) {
+        error_setg(errp, "No host device provided");
+        error_append_hint(errp,
+                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
+        return;
+    }
+
+    if (!realpath(sysfsdev, dev_path)) {
+        error_setg(errp, "Host device '%s' not found", sysfsdev);
+        return;
+    }
+
+    cdev->mdevid = g_strdup(basename(dev_path));
+
+    tmp = basename(dirname(dev_path));
+    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
+
+    cdev->hostid.cssid = cssid;
+    cdev->hostid.ssid = ssid;
+    cdev->hostid.devid = devid;
+    cdev->hostid.valid = true;
+}
+
+static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
+    DeviceState *parent = DEVICE(ccw_dev);
+    BusState *qbus = qdev_get_parent_bus(parent);
+    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
+    SubchDev *sch;
+    int ret;
+    Error *err = NULL;
+
+    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
+    if (*errp) {
+        return;
+    }
+
+    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
+    if (!sch) {
+        return;
+    }
+    sch->driver_data = cdev;
+
+    ccw_dev->sch = sch;
+    ret = css_sch_build_schib(sch, &cdev->hostid);
+    if (ret) {
+        error_setg(&err, "%s: Failed to build initial schib: %d",
+                   __func__, ret);
+        goto out_err;
+    }
+
+    ck->realize(ccw_dev, &err);
+    if (err) {
+        goto out_err;
+    }
+
+    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
+                          parent->hotplugged, 1);
+    return;
+
+out_err:
+    error_propagate(errp, err);
+    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+    ccw_dev->sch = NULL;
+    g_free(sch);
+}
+
+static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
+{
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    SubchDev *sch = ccw_dev->sch;
+
+    if (sch) {
+        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+        g_free(sch);
+        ccw_dev->sch = NULL;
+    }
+
+    g_free(cdev->mdevid);
+}
+
+static void s390_ccw_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_CLASS(klass);
+
+    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
+    cdc->realize = s390_ccw_realize;
+    cdc->unrealize = s390_ccw_unrealize;
+}
+
+static const TypeInfo s390_ccw_info = {
+    .name          = TYPE_S390_CCW,
+    .parent        = TYPE_CCW_DEVICE,
+    .instance_size = sizeof(S390CCWDevice),
+    .class_size    = sizeof(S390CCWDeviceClass),
+    .class_init    = s390_ccw_class_init,
+    .abstract      = true,
+};
+
+static void register_s390_ccw_type(void)
+{
+    type_register_static(&s390_ccw_info);
+}
+
+type_init(register_s390_ccw_type)
diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
new file mode 100644
index 0000000..b58d8e9
--- /dev/null
+++ b/hw/s390x/s390-ccw.h
@@ -0,0 +1,38 @@
+/*
+ * s390 CCW Assignment Support
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.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.
+ */
+
+#ifndef HW_S390_CCW_H
+#define HW_S390_CCW_H
+
+#include "hw/s390x/ccw-device.h"
+
+#define TYPE_S390_CCW "s390-ccw"
+#define S390_CCW_DEVICE(obj) \
+    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
+#define S390_CCW_DEVICE_CLASS(klass) \
+    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
+#define S390_CCW_DEVICE_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
+
+typedef struct S390CCWDevice {
+    CcwDevice parent_obj;
+    CssDevId hostid;
+    char *mdevid;
+} S390CCWDevice;
+
+typedef struct S390CCWDeviceClass {
+    CCWDeviceClass parent_class;
+    void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
+    void (*unrealize)(S390CCWDevice *dev, Error **errp);
+} S390CCWDeviceClass;
+
+#endif
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

We use the IOMMU_TYPE1 of VFIO to realize the subchannels
passthrough, implement a vfio based subchannels passthrough
driver called "vfio-ccw".

Support qemu parameters in the style of:
"-device vfio-ccw,sysfsdev=$mdev_file_path,devno=xx.x.xxxx'

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 default-configs/s390x-softmmu.mak |   1 +
 hw/vfio/Makefile.objs             |   1 +
 hw/vfio/ccw.c                     | 189 ++++++++++++++++++++++++++++++++++++++
 include/hw/vfio/vfio-common.h     |   1 +
 4 files changed, 192 insertions(+)
 create mode 100644 hw/vfio/ccw.c

diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 36e15de..5576b0a 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -4,4 +4,5 @@ CONFIG_VIRTIO=y
 CONFIG_SCLPCONSOLE=y
 CONFIG_S390_FLIC=y
 CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
+CONFIG_VFIO_CCW=$(CONFIG_LINUX)
 CONFIG_WDT_DIAG288=y
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index 05e7fbb..c3ab909 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -1,6 +1,7 @@
 ifeq ($(CONFIG_LINUX), y)
 obj-$(CONFIG_SOFTMMU) += common.o
 obj-$(CONFIG_PCI) += pci.o pci-quirks.o
+obj-$(CONFIG_VFIO_CCW) += ccw.o
 obj-$(CONFIG_SOFTMMU) += platform.o
 obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o
 obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
new file mode 100644
index 0000000..cd4dfe8
--- /dev/null
+++ b/hw/vfio/ccw.c
@@ -0,0 +1,189 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ *            Pierre Morel <pmorel@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or(at
+ * your option) any version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include <linux/vfio.h>
+#include <sys/ioctl.h>
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "hw/vfio/vfio.h"
+#include "hw/vfio/vfio-common.h"
+#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/ccw-device.h"
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+typedef struct VFIOCCWDevice {
+    S390CCWDevice cdev;
+    VFIODevice vdev;
+} VFIOCCWDevice;
+
+static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
+{
+    vdev->needs_reset = false;
+}
+
+/*
+ * We don't need vfio_hot_reset_multi and vfio_eoi operations for
+ * vfio_ccw device now.
+ */
+struct VFIODeviceOps vfio_ccw_ops = {
+    .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
+};
+
+static void vfio_ccw_reset(DeviceState *dev)
+{
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+
+    ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
+}
+
+static void vfio_put_device(VFIOCCWDevice *vcdev)
+{
+    g_free(vcdev->vdev.name);
+    vfio_put_base_device(&vcdev->vdev);
+}
+
+static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp)
+{
+    char *tmp, group_path[PATH_MAX];
+    ssize_t len;
+    int groupid;
+
+    tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group",
+                          cdev->hostid.cssid, cdev->hostid.ssid,
+                          cdev->hostid.devid, cdev->mdevid);
+    len = readlink(tmp, group_path, sizeof(group_path));
+    g_free(tmp);
+
+    if (len <= 0 || len >= sizeof(group_path)) {
+        error_setg(errp, "vfio: no iommu_group found");
+        return NULL;
+    }
+
+    group_path[len] = 0;
+
+    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
+        error_setg(errp, "vfio: failed to read %s", group_path);
+        return NULL;
+    }
+
+    return vfio_get_group(groupid, &address_space_memory, errp);
+}
+
+static void vfio_ccw_put_group(VFIOGroup *group)
+{
+    vfio_put_group(group);
+}
+
+static void vfio_ccw_realize(DeviceState *dev, Error **errp)
+{
+    VFIODevice *vbasedev;
+    VFIOGroup *group;
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
+
+    /* Call the class init function for subchannel. */
+    if (cdc->realize) {
+        cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
+        if (*errp) {
+            return;
+        }
+    }
+
+    group = vfio_ccw_get_group(cdev, errp);
+    if (!group) {
+        goto out_group_err;
+    }
+
+    vcdev->vdev.ops = &vfio_ccw_ops;
+    vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW;
+    vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid,
+                                       cdev->hostid.ssid, cdev->hostid.devid);
+    QLIST_FOREACH(vbasedev, &group->device_list, next) {
+        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
+            error_setg(errp, "vfio: subchannel %s has already been attached",
+                       vcdev->vdev.name);
+            goto out_device_err;
+        }
+    }
+
+    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) {
+        goto out_device_err;
+    }
+
+    return;
+
+out_device_err:
+    vfio_ccw_put_group(group);
+out_group_err:
+    if (cdc->unrealize) {
+        cdc->unrealize(cdev, errp);
+    }
+}
+
+static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
+{
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
+    VFIOGroup *group = vcdev->vdev.group;
+
+    vfio_put_device(vcdev);
+    vfio_put_group(group);
+
+    if (cdc->unrealize) {
+        cdc->unrealize(cdev, errp);
+    }
+}
+
+static Property vfio_ccw_properties[] = {
+    DEFINE_PROP_STRING("sysfsdev", VFIOCCWDevice, vdev.sysfsdev),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription vfio_ccw_vmstate = {
+    .name = TYPE_VFIO_CCW,
+    .unmigratable = 1,
+};
+
+static void vfio_ccw_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = vfio_ccw_properties;
+    dc->vmsd = &vfio_ccw_vmstate;
+    dc->desc = "VFIO-based subchannel assignment";
+    dc->realize = vfio_ccw_realize;
+    dc->unrealize = vfio_ccw_unrealize;
+    dc->reset = vfio_ccw_reset;
+}
+
+static const TypeInfo vfio_ccw_info = {
+    .name = TYPE_VFIO_CCW,
+    .parent = TYPE_S390_CCW,
+    .instance_size = sizeof(VFIOCCWDevice),
+    .class_init = vfio_ccw_class_init,
+};
+
+static void register_vfio_ccw_type(void)
+{
+    type_register_static(&vfio_ccw_info);
+}
+
+type_init(register_vfio_ccw_type)
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index c582de1..9521013 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -45,6 +45,7 @@
 enum {
     VFIO_DEVICE_TYPE_PCI = 0,
     VFIO_DEVICE_TYPE_PLATFORM = 1,
+    VFIO_DEVICE_TYPE_CCW = 2,
 };
 
 typedef struct VFIOMmap {
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

We use the IOMMU_TYPE1 of VFIO to realize the subchannels
passthrough, implement a vfio based subchannels passthrough
driver called "vfio-ccw".

Support qemu parameters in the style of:
"-device vfio-ccw,sysfsdev=$mdev_file_path,devno=xx.x.xxxx'

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 default-configs/s390x-softmmu.mak |   1 +
 hw/vfio/Makefile.objs             |   1 +
 hw/vfio/ccw.c                     | 189 ++++++++++++++++++++++++++++++++++++++
 include/hw/vfio/vfio-common.h     |   1 +
 4 files changed, 192 insertions(+)
 create mode 100644 hw/vfio/ccw.c

diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 36e15de..5576b0a 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -4,4 +4,5 @@ CONFIG_VIRTIO=y
 CONFIG_SCLPCONSOLE=y
 CONFIG_S390_FLIC=y
 CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
+CONFIG_VFIO_CCW=$(CONFIG_LINUX)
 CONFIG_WDT_DIAG288=y
diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index 05e7fbb..c3ab909 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -1,6 +1,7 @@
 ifeq ($(CONFIG_LINUX), y)
 obj-$(CONFIG_SOFTMMU) += common.o
 obj-$(CONFIG_PCI) += pci.o pci-quirks.o
+obj-$(CONFIG_VFIO_CCW) += ccw.o
 obj-$(CONFIG_SOFTMMU) += platform.o
 obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o
 obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
new file mode 100644
index 0000000..cd4dfe8
--- /dev/null
+++ b/hw/vfio/ccw.c
@@ -0,0 +1,189 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ *            Pierre Morel <pmorel@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or(at
+ * your option) any version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include <linux/vfio.h>
+#include <sys/ioctl.h>
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "hw/vfio/vfio.h"
+#include "hw/vfio/vfio-common.h"
+#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/ccw-device.h"
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+typedef struct VFIOCCWDevice {
+    S390CCWDevice cdev;
+    VFIODevice vdev;
+} VFIOCCWDevice;
+
+static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
+{
+    vdev->needs_reset = false;
+}
+
+/*
+ * We don't need vfio_hot_reset_multi and vfio_eoi operations for
+ * vfio_ccw device now.
+ */
+struct VFIODeviceOps vfio_ccw_ops = {
+    .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
+};
+
+static void vfio_ccw_reset(DeviceState *dev)
+{
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+
+    ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
+}
+
+static void vfio_put_device(VFIOCCWDevice *vcdev)
+{
+    g_free(vcdev->vdev.name);
+    vfio_put_base_device(&vcdev->vdev);
+}
+
+static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp)
+{
+    char *tmp, group_path[PATH_MAX];
+    ssize_t len;
+    int groupid;
+
+    tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group",
+                          cdev->hostid.cssid, cdev->hostid.ssid,
+                          cdev->hostid.devid, cdev->mdevid);
+    len = readlink(tmp, group_path, sizeof(group_path));
+    g_free(tmp);
+
+    if (len <= 0 || len >= sizeof(group_path)) {
+        error_setg(errp, "vfio: no iommu_group found");
+        return NULL;
+    }
+
+    group_path[len] = 0;
+
+    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
+        error_setg(errp, "vfio: failed to read %s", group_path);
+        return NULL;
+    }
+
+    return vfio_get_group(groupid, &address_space_memory, errp);
+}
+
+static void vfio_ccw_put_group(VFIOGroup *group)
+{
+    vfio_put_group(group);
+}
+
+static void vfio_ccw_realize(DeviceState *dev, Error **errp)
+{
+    VFIODevice *vbasedev;
+    VFIOGroup *group;
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
+
+    /* Call the class init function for subchannel. */
+    if (cdc->realize) {
+        cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
+        if (*errp) {
+            return;
+        }
+    }
+
+    group = vfio_ccw_get_group(cdev, errp);
+    if (!group) {
+        goto out_group_err;
+    }
+
+    vcdev->vdev.ops = &vfio_ccw_ops;
+    vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW;
+    vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid,
+                                       cdev->hostid.ssid, cdev->hostid.devid);
+    QLIST_FOREACH(vbasedev, &group->device_list, next) {
+        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
+            error_setg(errp, "vfio: subchannel %s has already been attached",
+                       vcdev->vdev.name);
+            goto out_device_err;
+        }
+    }
+
+    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) {
+        goto out_device_err;
+    }
+
+    return;
+
+out_device_err:
+    vfio_ccw_put_group(group);
+out_group_err:
+    if (cdc->unrealize) {
+        cdc->unrealize(cdev, errp);
+    }
+}
+
+static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
+{
+    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
+    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
+    VFIOGroup *group = vcdev->vdev.group;
+
+    vfio_put_device(vcdev);
+    vfio_put_group(group);
+
+    if (cdc->unrealize) {
+        cdc->unrealize(cdev, errp);
+    }
+}
+
+static Property vfio_ccw_properties[] = {
+    DEFINE_PROP_STRING("sysfsdev", VFIOCCWDevice, vdev.sysfsdev),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static const VMStateDescription vfio_ccw_vmstate = {
+    .name = TYPE_VFIO_CCW,
+    .unmigratable = 1,
+};
+
+static void vfio_ccw_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = vfio_ccw_properties;
+    dc->vmsd = &vfio_ccw_vmstate;
+    dc->desc = "VFIO-based subchannel assignment";
+    dc->realize = vfio_ccw_realize;
+    dc->unrealize = vfio_ccw_unrealize;
+    dc->reset = vfio_ccw_reset;
+}
+
+static const TypeInfo vfio_ccw_info = {
+    .name = TYPE_VFIO_CCW,
+    .parent = TYPE_S390_CCW,
+    .instance_size = sizeof(VFIOCCWDevice),
+    .class_init = vfio_ccw_class_init,
+};
+
+static void register_vfio_ccw_type(void)
+{
+    type_register_static(&vfio_ccw_info);
+}
+
+type_init(register_vfio_ccw_type)
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index c582de1..9521013 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -45,6 +45,7 @@
 enum {
     VFIO_DEVICE_TYPE_PCI = 0,
     VFIO_DEVICE_TYPE_PLATFORM = 1,
+    VFIO_DEVICE_TYPE_CCW = 2,
 };
 
 typedef struct VFIOMmap {
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 08/13] vfio/ccw: get io region info
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

vfio-ccw provides an MMIO region for I/O operations. We fetch its
information via ioctls here, then we can use it performing I/O
instructions and retrieving I/O results later on.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index cd4dfe8..a285b23 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/vfio.h>
+#include <linux/vfio_ccw.h>
 #include <sys/ioctl.h>
 
 #include "qemu/osdep.h"
@@ -26,6 +27,9 @@
 typedef struct VFIOCCWDevice {
     S390CCWDevice cdev;
     VFIODevice vdev;
+    uint64_t io_region_size;
+    uint64_t io_region_offset;
+    struct ccw_io_region *io_region;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -50,6 +54,46 @@ static void vfio_ccw_reset(DeviceState *dev)
     ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
 }
 
+static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
+{
+    VFIODevice *vdev = &vcdev->vdev;
+    struct vfio_region_info *info;
+    int ret;
+
+    /* Sanity check device */
+    if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) {
+        error_setg(errp, "vfio: Um, this isn't a vfio-ccw device");
+        return;
+    }
+
+    if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
+        error_setg(errp, "vfio: Unexpected number of the I/O region %u",
+                   vdev->num_regions);
+        return;
+    }
+
+    ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
+    if (ret) {
+        error_setg(errp, "vfio: Error getting config info: %d", ret);
+        return;
+    }
+
+    vcdev->io_region_size = info->size;
+    if (sizeof(*vcdev->io_region) != vcdev->io_region_size) {
+        error_setg(errp, "vfio: Unexpected size of the I/O region");
+        return;
+    }
+    vcdev->io_region_offset = info->offset;
+    vcdev->io_region = g_malloc0(info->size);
+
+    g_free(info);
+}
+
+static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
+{
+    g_free(vcdev->io_region);
+}
+
 static void vfio_put_device(VFIOCCWDevice *vcdev)
 {
     g_free(vcdev->vdev.name);
@@ -126,8 +170,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
         goto out_device_err;
     }
 
+    vfio_ccw_get_region(vcdev, errp);
+    if (*errp) {
+        goto out_region_err;
+    }
+
     return;
 
+out_region_err:
+    vfio_put_device(vcdev);
 out_device_err:
     vfio_ccw_put_group(group);
 out_group_err:
@@ -144,6 +195,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
     VFIOGroup *group = vcdev->vdev.group;
 
+    vfio_ccw_put_region(vcdev);
     vfio_put_device(vcdev);
     vfio_put_group(group);
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 08/13] vfio/ccw: get io region info
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

vfio-ccw provides an MMIO region for I/O operations. We fetch its
information via ioctls here, then we can use it performing I/O
instructions and retrieving I/O results later on.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index cd4dfe8..a285b23 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/vfio.h>
+#include <linux/vfio_ccw.h>
 #include <sys/ioctl.h>
 
 #include "qemu/osdep.h"
@@ -26,6 +27,9 @@
 typedef struct VFIOCCWDevice {
     S390CCWDevice cdev;
     VFIODevice vdev;
+    uint64_t io_region_size;
+    uint64_t io_region_offset;
+    struct ccw_io_region *io_region;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -50,6 +54,46 @@ static void vfio_ccw_reset(DeviceState *dev)
     ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
 }
 
+static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
+{
+    VFIODevice *vdev = &vcdev->vdev;
+    struct vfio_region_info *info;
+    int ret;
+
+    /* Sanity check device */
+    if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) {
+        error_setg(errp, "vfio: Um, this isn't a vfio-ccw device");
+        return;
+    }
+
+    if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
+        error_setg(errp, "vfio: Unexpected number of the I/O region %u",
+                   vdev->num_regions);
+        return;
+    }
+
+    ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
+    if (ret) {
+        error_setg(errp, "vfio: Error getting config info: %d", ret);
+        return;
+    }
+
+    vcdev->io_region_size = info->size;
+    if (sizeof(*vcdev->io_region) != vcdev->io_region_size) {
+        error_setg(errp, "vfio: Unexpected size of the I/O region");
+        return;
+    }
+    vcdev->io_region_offset = info->offset;
+    vcdev->io_region = g_malloc0(info->size);
+
+    g_free(info);
+}
+
+static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
+{
+    g_free(vcdev->io_region);
+}
+
 static void vfio_put_device(VFIOCCWDevice *vcdev)
 {
     g_free(vcdev->vdev.name);
@@ -126,8 +170,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
         goto out_device_err;
     }
 
+    vfio_ccw_get_region(vcdev, errp);
+    if (*errp) {
+        goto out_region_err;
+    }
+
     return;
 
+out_region_err:
+    vfio_put_device(vcdev);
 out_device_err:
     vfio_ccw_put_group(group);
 out_group_err:
@@ -144,6 +195,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
     VFIOGroup *group = vcdev->vdev.group;
 
+    vfio_ccw_put_region(vcdev);
     vfio_put_device(vcdev);
     vfio_put_group(group);
 
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

vfio-ccw resorts to the eventfd mechanism to communicate with userspace.
We fetch the irqs info via the ioctl VFIO_DEVICE_GET_IRQ_INFO,
register a event notifier to get the eventfd fd which is sent
to kernel via the ioctl VFIO_DEVICE_SET_IRQS, then we can implement
read operation once kernel sends the signal.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index a285b23..cda3057 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -22,6 +22,7 @@
 #include "hw/vfio/vfio-common.h"
 #include "hw/s390x/s390-ccw.h"
 #include "hw/s390x/ccw-device.h"
+#include "qemu/error-report.h"
 
 #define TYPE_VFIO_CCW "vfio-ccw"
 typedef struct VFIOCCWDevice {
@@ -30,6 +31,7 @@ typedef struct VFIOCCWDevice {
     uint64_t io_region_size;
     uint64_t io_region_offset;
     struct ccw_io_region *io_region;
+    EventNotifier io_notifier;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -54,6 +56,98 @@ static void vfio_ccw_reset(DeviceState *dev)
     ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
 }
 
+static void vfio_ccw_io_notifier_handler(void *opaque)
+{
+    VFIOCCWDevice *vcdev = opaque;
+
+    if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
+        return;
+    }
+}
+
+static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
+{
+    VFIODevice *vdev = &vcdev->vdev;
+    struct vfio_irq_info *irq_info;
+    struct vfio_irq_set *irq_set;
+    size_t argsz;
+    int32_t *pfd;
+
+    if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) {
+        error_setg(errp, "vfio: unexpected number of io irqs %u",
+                   vdev->num_irqs);
+        return;
+    }
+
+    argsz = sizeof(*irq_set);
+    irq_info = g_malloc0(argsz);
+    irq_info->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_info->argsz = argsz;
+    if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
+              irq_info) < 0 || irq_info->count < 1) {
+        error_setg(errp, "vfio: Error getting irq info");
+        goto get_error;
+    }
+
+    if (event_notifier_init(&vcdev->io_notifier, 0)) {
+        error_setg(errp, "vfio: Unable to init event notifier for IO");
+        goto get_error;
+    }
+
+    argsz = sizeof(*irq_set) + sizeof(*pfd);
+    irq_set = g_malloc0(argsz);
+    irq_set->argsz = argsz;
+    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+                     VFIO_IRQ_SET_ACTION_TRIGGER;
+    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_set->start = 0;
+    irq_set->count = 1;
+    pfd = (int32_t *) &irq_set->data;
+
+    *pfd = event_notifier_get_fd(&vcdev->io_notifier);
+    qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev);
+    if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
+        error_setg(errp, "vfio: Failed to set up io notification");
+        qemu_set_fd_handler(*pfd, NULL, NULL, vcdev);
+        event_notifier_cleanup(&vcdev->io_notifier);
+        goto set_error;
+    }
+
+set_error:
+    g_free(irq_set);
+
+get_error:
+    g_free(irq_info);
+}
+
+static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
+{
+    struct vfio_irq_set *irq_set;
+    size_t argsz;
+    int32_t *pfd;
+
+    argsz = sizeof(*irq_set) + sizeof(*pfd);
+    irq_set = g_malloc0(argsz);
+    irq_set->argsz = argsz;
+    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+                     VFIO_IRQ_SET_ACTION_TRIGGER;
+    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_set->start = 0;
+    irq_set->count = 1;
+    pfd = (int32_t *) &irq_set->data;
+    *pfd = -1;
+
+    if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
+        error_report("vfio: Failed to de-assign device io fd");
+    }
+
+    qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier),
+                        NULL, NULL, vcdev);
+    event_notifier_cleanup(&vcdev->io_notifier);
+
+    g_free(irq_set);
+}
+
 static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
 {
     VFIODevice *vdev = &vcdev->vdev;
@@ -175,8 +269,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
         goto out_region_err;
     }
 
+    vfio_ccw_register_io_notifier(vcdev, errp);
+    if (*errp) {
+        goto out_notifier_err;
+    }
+
     return;
 
+out_notifier_err:
+    vfio_ccw_put_region(vcdev);
 out_region_err:
     vfio_put_device(vcdev);
 out_device_err:
@@ -195,6 +296,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
     VFIOGroup *group = vcdev->vdev.group;
 
+    vfio_ccw_unregister_io_notifier(vcdev);
     vfio_ccw_put_region(vcdev);
     vfio_put_device(vcdev);
     vfio_put_group(group);
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

vfio-ccw resorts to the eventfd mechanism to communicate with userspace.
We fetch the irqs info via the ioctl VFIO_DEVICE_GET_IRQ_INFO,
register a event notifier to get the eventfd fd which is sent
to kernel via the ioctl VFIO_DEVICE_SET_IRQS, then we can implement
read operation once kernel sends the signal.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index a285b23..cda3057 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -22,6 +22,7 @@
 #include "hw/vfio/vfio-common.h"
 #include "hw/s390x/s390-ccw.h"
 #include "hw/s390x/ccw-device.h"
+#include "qemu/error-report.h"
 
 #define TYPE_VFIO_CCW "vfio-ccw"
 typedef struct VFIOCCWDevice {
@@ -30,6 +31,7 @@ typedef struct VFIOCCWDevice {
     uint64_t io_region_size;
     uint64_t io_region_offset;
     struct ccw_io_region *io_region;
+    EventNotifier io_notifier;
 } VFIOCCWDevice;
 
 static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
@@ -54,6 +56,98 @@ static void vfio_ccw_reset(DeviceState *dev)
     ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
 }
 
+static void vfio_ccw_io_notifier_handler(void *opaque)
+{
+    VFIOCCWDevice *vcdev = opaque;
+
+    if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
+        return;
+    }
+}
+
+static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
+{
+    VFIODevice *vdev = &vcdev->vdev;
+    struct vfio_irq_info *irq_info;
+    struct vfio_irq_set *irq_set;
+    size_t argsz;
+    int32_t *pfd;
+
+    if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) {
+        error_setg(errp, "vfio: unexpected number of io irqs %u",
+                   vdev->num_irqs);
+        return;
+    }
+
+    argsz = sizeof(*irq_set);
+    irq_info = g_malloc0(argsz);
+    irq_info->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_info->argsz = argsz;
+    if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
+              irq_info) < 0 || irq_info->count < 1) {
+        error_setg(errp, "vfio: Error getting irq info");
+        goto get_error;
+    }
+
+    if (event_notifier_init(&vcdev->io_notifier, 0)) {
+        error_setg(errp, "vfio: Unable to init event notifier for IO");
+        goto get_error;
+    }
+
+    argsz = sizeof(*irq_set) + sizeof(*pfd);
+    irq_set = g_malloc0(argsz);
+    irq_set->argsz = argsz;
+    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+                     VFIO_IRQ_SET_ACTION_TRIGGER;
+    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_set->start = 0;
+    irq_set->count = 1;
+    pfd = (int32_t *) &irq_set->data;
+
+    *pfd = event_notifier_get_fd(&vcdev->io_notifier);
+    qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev);
+    if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
+        error_setg(errp, "vfio: Failed to set up io notification");
+        qemu_set_fd_handler(*pfd, NULL, NULL, vcdev);
+        event_notifier_cleanup(&vcdev->io_notifier);
+        goto set_error;
+    }
+
+set_error:
+    g_free(irq_set);
+
+get_error:
+    g_free(irq_info);
+}
+
+static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
+{
+    struct vfio_irq_set *irq_set;
+    size_t argsz;
+    int32_t *pfd;
+
+    argsz = sizeof(*irq_set) + sizeof(*pfd);
+    irq_set = g_malloc0(argsz);
+    irq_set->argsz = argsz;
+    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
+                     VFIO_IRQ_SET_ACTION_TRIGGER;
+    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
+    irq_set->start = 0;
+    irq_set->count = 1;
+    pfd = (int32_t *) &irq_set->data;
+    *pfd = -1;
+
+    if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
+        error_report("vfio: Failed to de-assign device io fd");
+    }
+
+    qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier),
+                        NULL, NULL, vcdev);
+    event_notifier_cleanup(&vcdev->io_notifier);
+
+    g_free(irq_set);
+}
+
 static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
 {
     VFIODevice *vdev = &vcdev->vdev;
@@ -175,8 +269,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
         goto out_region_err;
     }
 
+    vfio_ccw_register_io_notifier(vcdev, errp);
+    if (*errp) {
+        goto out_notifier_err;
+    }
+
     return;
 
+out_notifier_err:
+    vfio_ccw_put_region(vcdev);
 out_region_err:
     vfio_put_device(vcdev);
 out_device_err:
@@ -195,6 +296,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
     VFIOGroup *group = vcdev->vdev.group;
 
+    vfio_ccw_unregister_io_notifier(vcdev);
     vfio_ccw_put_region(vcdev);
     vfio_put_device(vcdev);
     vfio_put_group(group);
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

Introduce a new callback on subchannel to handle ccw-request.
Realize the callback in vfio-ccw device. Besides, resort to
the event notifier handler to handling the ccw-request results.
1. Pread the I/O results via MMIO region.
2. Update the scsw info to guest.
3. Inject an I/O interrupt to notify guest the I/O result.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         |  4 +--
 hw/s390x/s390-ccw.h    |  1 +
 hw/vfio/ccw.c          | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/s390x/css.h |  2 ++
 4 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1052eea..507c60f 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -259,7 +259,7 @@ uint16_t css_build_subchannel_id(SubchDev *sch)
     return css_do_build_subchannel_id(sch->cssid, sch->ssid);
 }
 
-static void css_inject_io_interrupt(SubchDev *sch)
+void css_inject_io_interrupt(SubchDev *sch)
 {
     uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
 
@@ -668,7 +668,7 @@ static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
     dest->chars = cpu_to_be32(src->chars);
 }
 
-static void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
+void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
 {
     dest->flags = cpu_to_be16(src->flags);
     dest->ctrl = cpu_to_be16(src->ctrl);
diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
index b58d8e9..4e2fa65 100644
--- a/hw/s390x/s390-ccw.h
+++ b/hw/s390x/s390-ccw.h
@@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
     CcwDevice parent_obj;
     CssDevId hostid;
     char *mdevid;
+    int (*handle_request) (ORB *, SCSW *, void *);
 } S390CCWDevice;
 
 typedef struct S390CCWDeviceClass {
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index cda3057..3ff78c5 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -47,6 +47,36 @@ struct VFIODeviceOps vfio_ccw_ops = {
     .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
 };
 
+static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
+{
+    S390CCWDevice *cdev = data;
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    struct ccw_io_region *region = vcdev->io_region;
+    int ret;
+
+    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));
+    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));
+    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));
+
+    memset(region, 0, sizeof(*region));
+
+    memcpy(region->orb_area, orb, sizeof(ORB));
+    memcpy(region->scsw_area, scsw, sizeof(SCSW));
+
+again:
+    ret = pwrite(vcdev->vdev.fd, region,
+                 vcdev->io_region_size, vcdev->io_region_offset);
+    if (ret != vcdev->io_region_size) {
+        if (errno == EAGAIN) {
+            goto again;
+        }
+        error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);
+        return -errno;
+    }
+
+    return region->ret_code;
+}
+
 static void vfio_ccw_reset(DeviceState *dev)
 {
     CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
@@ -59,10 +89,52 @@ static void vfio_ccw_reset(DeviceState *dev)
 static void vfio_ccw_io_notifier_handler(void *opaque)
 {
     VFIOCCWDevice *vcdev = opaque;
+    struct ccw_io_region *region = vcdev->io_region;
+    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    SubchDev *sch = ccw_dev->sch;
+    SCSW *s = &sch->curr_status.scsw;
+    IRB irb;
 
     if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
         return;
     }
+
+    if (pread(vcdev->vdev.fd, region,
+              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
+        switch (errno) {
+        case ENODEV:
+            /* Generate a deferred cc 3 condition. */
+            s->flags |= SCSW_FLAGS_MASK_CC;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
+            goto read_err;
+        case EFAULT:
+            /* memory problem, generate channel data check */
+            s->ctrl &= ~SCSW_ACTL_START_PEND;
+            s->cstat = SCSW_CSTAT_DATA_CHECK;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+            goto read_err;
+        default:
+            /* error, generate channel program check */
+            s->ctrl &= ~SCSW_ACTL_START_PEND;
+            s->cstat = SCSW_CSTAT_PROG_CHECK;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+            goto read_err;
+        }
+    }
+
+    memcpy(&irb, region->irb_area, sizeof(IRB));
+
+    /* Update control block via irb. */
+    copy_scsw_to_guest(s, &irb.scsw);
+
+read_err:
+    css_inject_io_interrupt(sch);
 }
 
 static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
@@ -235,6 +307,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
     VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
 
+    cdev->handle_request = vfio_ccw_handle_request;
     /* Call the class init function for subchannel. */
     if (cdc->realize) {
         cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index a8bf1db..c8c283a 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -135,6 +135,8 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
 int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
 uint16_t css_build_subchannel_id(SubchDev *sch);
+void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
+void css_inject_io_interrupt(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
 void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

Introduce a new callback on subchannel to handle ccw-request.
Realize the callback in vfio-ccw device. Besides, resort to
the event notifier handler to handling the ccw-request results.
1. Pread the I/O results via MMIO region.
2. Update the scsw info to guest.
3. Inject an I/O interrupt to notify guest the I/O result.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         |  4 +--
 hw/s390x/s390-ccw.h    |  1 +
 hw/vfio/ccw.c          | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/s390x/css.h |  2 ++
 4 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1052eea..507c60f 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -259,7 +259,7 @@ uint16_t css_build_subchannel_id(SubchDev *sch)
     return css_do_build_subchannel_id(sch->cssid, sch->ssid);
 }
 
-static void css_inject_io_interrupt(SubchDev *sch)
+void css_inject_io_interrupt(SubchDev *sch)
 {
     uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
 
@@ -668,7 +668,7 @@ static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
     dest->chars = cpu_to_be32(src->chars);
 }
 
-static void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
+void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
 {
     dest->flags = cpu_to_be16(src->flags);
     dest->ctrl = cpu_to_be16(src->ctrl);
diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
index b58d8e9..4e2fa65 100644
--- a/hw/s390x/s390-ccw.h
+++ b/hw/s390x/s390-ccw.h
@@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
     CcwDevice parent_obj;
     CssDevId hostid;
     char *mdevid;
+    int (*handle_request) (ORB *, SCSW *, void *);
 } S390CCWDevice;
 
 typedef struct S390CCWDeviceClass {
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index cda3057..3ff78c5 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -47,6 +47,36 @@ struct VFIODeviceOps vfio_ccw_ops = {
     .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
 };
 
+static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
+{
+    S390CCWDevice *cdev = data;
+    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
+    struct ccw_io_region *region = vcdev->io_region;
+    int ret;
+
+    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));
+    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));
+    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));
+
+    memset(region, 0, sizeof(*region));
+
+    memcpy(region->orb_area, orb, sizeof(ORB));
+    memcpy(region->scsw_area, scsw, sizeof(SCSW));
+
+again:
+    ret = pwrite(vcdev->vdev.fd, region,
+                 vcdev->io_region_size, vcdev->io_region_offset);
+    if (ret != vcdev->io_region_size) {
+        if (errno == EAGAIN) {
+            goto again;
+        }
+        error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);
+        return -errno;
+    }
+
+    return region->ret_code;
+}
+
 static void vfio_ccw_reset(DeviceState *dev)
 {
     CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
@@ -59,10 +89,52 @@ static void vfio_ccw_reset(DeviceState *dev)
 static void vfio_ccw_io_notifier_handler(void *opaque)
 {
     VFIOCCWDevice *vcdev = opaque;
+    struct ccw_io_region *region = vcdev->io_region;
+    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
+    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
+    SubchDev *sch = ccw_dev->sch;
+    SCSW *s = &sch->curr_status.scsw;
+    IRB irb;
 
     if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
         return;
     }
+
+    if (pread(vcdev->vdev.fd, region,
+              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
+        switch (errno) {
+        case ENODEV:
+            /* Generate a deferred cc 3 condition. */
+            s->flags |= SCSW_FLAGS_MASK_CC;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
+            goto read_err;
+        case EFAULT:
+            /* memory problem, generate channel data check */
+            s->ctrl &= ~SCSW_ACTL_START_PEND;
+            s->cstat = SCSW_CSTAT_DATA_CHECK;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+            goto read_err;
+        default:
+            /* error, generate channel program check */
+            s->ctrl &= ~SCSW_ACTL_START_PEND;
+            s->cstat = SCSW_CSTAT_PROG_CHECK;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+            goto read_err;
+        }
+    }
+
+    memcpy(&irb, region->irb_area, sizeof(IRB));
+
+    /* Update control block via irb. */
+    copy_scsw_to_guest(s, &irb.scsw);
+
+read_err:
+    css_inject_io_interrupt(sch);
 }
 
 static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
@@ -235,6 +307,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
     VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
     S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
 
+    cdev->handle_request = vfio_ccw_handle_request;
     /* Call the class init function for subchannel. */
     if (cdc->realize) {
         cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index a8bf1db..c8c283a 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -135,6 +135,8 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
 void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
 int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
 uint16_t css_build_subchannel_id(SubchDev *sch);
+void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
+void css_inject_io_interrupt(SubchDev *sch);
 void css_reset(void);
 void css_reset_sch(SubchDev *sch);
 void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 11/13] s390x/css: ccw translation infrastructure
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

Implement a basic infrastructure of handling channel I/O instruction
interception for passed through subchannels:
1. Branch the code path of instruction interception handling by
   SubChannel type.
2. For a passed-through subchannel, issue the ORB to kernel to do ccw
   translation and perform an I/O operation.
3. Assign different condition code based on the I/O result, or
   trigger a program check.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         | 88 ++++++++++++++++++++++++++++++++++++++++++++++----
 hw/s390x/s390-ccw.c    | 12 +++++++
 hw/s390x/virtio-ccw.c  |  1 +
 include/hw/s390x/css.h |  4 +++
 target/s390x/ioinst.c  |  9 ++++++
 5 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 507c60f..0979867 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -524,7 +524,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
     return ret;
 }
 
-static void sch_handle_start_func(SubchDev *sch, ORB *orb)
+static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb)
 {
 
     PMCW *p = &sch->curr_status.pmcw;
@@ -623,13 +623,57 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
 
 }
 
+static int sch_handle_start_func_passthrough(SubchDev *sch, ORB *orb)
+{
+
+    PMCW *p = &sch->curr_status.pmcw;
+    SCSW *s = &sch->curr_status.scsw;
+    int ret;
+
+    if (!(s->ctrl & SCSW_ACTL_SUSP)) {
+        assert(orb != NULL);
+        p->intparm = orb->intparm;
+    }
+
+    /*
+     * Only support prefetch enable mode.
+     * Only support 64bit addressing idal.
+     */
+    if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
+        !(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
+        return -EINVAL;
+    }
+
+    ret = s390_ccw_cmd_request(orb, s, sch->driver_data);
+    switch (ret) {
+    /* Currently we don't update control block and just return the cc code. */
+    case 0:
+        break;
+    case -EBUSY:
+        break;
+    case -ENODEV:
+        break;
+    case -EACCES:
+        /* Let's reflect an inaccessible host device by cc 3. */
+        ret = -ENODEV;
+        break;
+    default:
+       /* All other return codes will trigger a program check,
+        * or set cc to 1.
+        */
+       break;
+    };
+
+    return ret;
+}
+
 /*
  * On real machines, this would run asynchronously to the main vcpus.
  * We might want to make some parts of the ssch handling (interpreting
  * read/writes) asynchronous later on if we start supporting more than
  * our current very simple devices.
  */
-static void do_subchannel_work(SubchDev *sch, ORB *orb)
+int do_subchannel_work_virtual(SubchDev *sch, ORB *orb)
 {
 
     SCSW *s = &sch->curr_status.scsw;
@@ -640,12 +684,45 @@ static void do_subchannel_work(SubchDev *sch, ORB *orb)
         sch_handle_halt_func(sch);
     } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
         /* Triggered by both ssch and rsch. */
-        sch_handle_start_func(sch, orb);
+        sch_handle_start_func_virtual(sch, orb);
     } else {
         /* Cannot happen. */
-        return;
+        return 0;
     }
     css_inject_io_interrupt(sch);
+    return 0;
+}
+
+int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb)
+{
+    int ret;
+    SCSW *s = &sch->curr_status.scsw;
+
+    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
+        /* TODO: Clear handling */
+        sch_handle_clear_func(sch);
+        ret = 0;
+    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
+        /* TODO: Halt handling */
+        sch_handle_halt_func(sch);
+        ret = 0;
+    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
+        ret = sch_handle_start_func_passthrough(sch, orb);
+    } else {
+        /* Cannot happen. */
+        return -ENODEV;
+    }
+
+    return ret;
+}
+
+static int do_subchannel_work(SubchDev *sch, ORB *orb)
+{
+    if (sch->do_subchannel_work) {
+        return sch->do_subchannel_work(sch, orb);
+    } else {
+        return -EINVAL;
+    }
 }
 
 static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
@@ -964,8 +1041,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
     s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
     s->flags &= ~SCSW_FLAGS_MASK_PNO;
 
-    do_subchannel_work(sch, orb);
-    ret = 0;
+    ret = do_subchannel_work(sch, orb);
 
 out:
     return ret;
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 8b4b9cf..f8175bf 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -18,6 +18,17 @@
 #include "hw/s390x/css-bridge.h"
 #include "s390-ccw.h"
 
+int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data)
+{
+    S390CCWDevice *cdev = data;
+
+    if (cdev->handle_request) {
+        return cdev->handle_request(orb, scsw, data);
+    } else {
+        return -ENOSYS;
+    }
+}
+
 static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
                                   char *sysfsdev,
                                   Error **errp)
@@ -69,6 +80,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
         return;
     }
     sch->driver_data = cdev;
+    sch->do_subchannel_work = do_subchannel_work_passthrough;
 
     ccw_dev->sch = sch;
     ret = css_sch_build_schib(sch, &cdev->hostid);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4e386e9..e6a6f74 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -701,6 +701,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
     sch->disable_cb = virtio_sch_disable_cb;
     sch->id.reserved = 0xff;
     sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
+    sch->do_subchannel_work = do_subchannel_work_virtual;
     ccw_dev->sch = sch;
     dev->indicators = NULL;
     dev->revision = -1;
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index c8c283a..ae687c5 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -90,6 +90,7 @@ struct SubchDev {
     /* transport-provided data: */
     int (*ccw_cb) (SubchDev *, CCW1);
     void (*disable_cb)(SubchDev *);
+    int (*do_subchannel_work) (SubchDev *, ORB *);
     SenseId id;
     void *driver_data;
 };
@@ -146,6 +147,9 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 void css_generate_css_crws(uint8_t cssid);
 void css_clear_sei_pending(void);
 void css_adapter_interrupt(uint8_t isc);
+int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data);
+int do_subchannel_work_virtual(SubchDev *sub, ORB *orb);
+int do_subchannel_work_passthrough(SubchDev *sub, ORB *orb);
 
 typedef enum {
     CSS_IO_ADAPTER_VIRTIO = 0,
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index 590bfa4..62a7771 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -244,6 +244,15 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
     case -EBUSY:
         cc = 2;
         break;
+    case -EFAULT:
+        /*
+         * TODO:
+         * I'm wondering whether there is something better
+         * to do for us here (like setting some device or
+         * subchannel status).
+         */
+        program_interrupt(env, PGM_ADDRESSING, 4);
+        return;
     case 0:
         cc = 0;
         break;
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 11/13] s390x/css: ccw translation infrastructure
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson,
	Xiao Feng Ren

From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>

Implement a basic infrastructure of handling channel I/O instruction
interception for passed through subchannels:
1. Branch the code path of instruction interception handling by
   SubChannel type.
2. For a passed-through subchannel, issue the ORB to kernel to do ccw
   translation and perform an I/O operation.
3. Assign different condition code based on the I/O result, or
   trigger a program check.

Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/s390x/css.c         | 88 ++++++++++++++++++++++++++++++++++++++++++++++----
 hw/s390x/s390-ccw.c    | 12 +++++++
 hw/s390x/virtio-ccw.c  |  1 +
 include/hw/s390x/css.h |  4 +++
 target/s390x/ioinst.c  |  9 ++++++
 5 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 507c60f..0979867 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -524,7 +524,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
     return ret;
 }
 
-static void sch_handle_start_func(SubchDev *sch, ORB *orb)
+static void sch_handle_start_func_virtual(SubchDev *sch, ORB *orb)
 {
 
     PMCW *p = &sch->curr_status.pmcw;
@@ -623,13 +623,57 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb)
 
 }
 
+static int sch_handle_start_func_passthrough(SubchDev *sch, ORB *orb)
+{
+
+    PMCW *p = &sch->curr_status.pmcw;
+    SCSW *s = &sch->curr_status.scsw;
+    int ret;
+
+    if (!(s->ctrl & SCSW_ACTL_SUSP)) {
+        assert(orb != NULL);
+        p->intparm = orb->intparm;
+    }
+
+    /*
+     * Only support prefetch enable mode.
+     * Only support 64bit addressing idal.
+     */
+    if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
+        !(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
+        return -EINVAL;
+    }
+
+    ret = s390_ccw_cmd_request(orb, s, sch->driver_data);
+    switch (ret) {
+    /* Currently we don't update control block and just return the cc code. */
+    case 0:
+        break;
+    case -EBUSY:
+        break;
+    case -ENODEV:
+        break;
+    case -EACCES:
+        /* Let's reflect an inaccessible host device by cc 3. */
+        ret = -ENODEV;
+        break;
+    default:
+       /* All other return codes will trigger a program check,
+        * or set cc to 1.
+        */
+       break;
+    };
+
+    return ret;
+}
+
 /*
  * On real machines, this would run asynchronously to the main vcpus.
  * We might want to make some parts of the ssch handling (interpreting
  * read/writes) asynchronous later on if we start supporting more than
  * our current very simple devices.
  */
-static void do_subchannel_work(SubchDev *sch, ORB *orb)
+int do_subchannel_work_virtual(SubchDev *sch, ORB *orb)
 {
 
     SCSW *s = &sch->curr_status.scsw;
@@ -640,12 +684,45 @@ static void do_subchannel_work(SubchDev *sch, ORB *orb)
         sch_handle_halt_func(sch);
     } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
         /* Triggered by both ssch and rsch. */
-        sch_handle_start_func(sch, orb);
+        sch_handle_start_func_virtual(sch, orb);
     } else {
         /* Cannot happen. */
-        return;
+        return 0;
     }
     css_inject_io_interrupt(sch);
+    return 0;
+}
+
+int do_subchannel_work_passthrough(SubchDev *sch, ORB *orb)
+{
+    int ret;
+    SCSW *s = &sch->curr_status.scsw;
+
+    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
+        /* TODO: Clear handling */
+        sch_handle_clear_func(sch);
+        ret = 0;
+    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
+        /* TODO: Halt handling */
+        sch_handle_halt_func(sch);
+        ret = 0;
+    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
+        ret = sch_handle_start_func_passthrough(sch, orb);
+    } else {
+        /* Cannot happen. */
+        return -ENODEV;
+    }
+
+    return ret;
+}
+
+static int do_subchannel_work(SubchDev *sch, ORB *orb)
+{
+    if (sch->do_subchannel_work) {
+        return sch->do_subchannel_work(sch, orb);
+    } else {
+        return -EINVAL;
+    }
 }
 
 static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
@@ -964,8 +1041,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
     s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
     s->flags &= ~SCSW_FLAGS_MASK_PNO;
 
-    do_subchannel_work(sch, orb);
-    ret = 0;
+    ret = do_subchannel_work(sch, orb);
 
 out:
     return ret;
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 8b4b9cf..f8175bf 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -18,6 +18,17 @@
 #include "hw/s390x/css-bridge.h"
 #include "s390-ccw.h"
 
+int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data)
+{
+    S390CCWDevice *cdev = data;
+
+    if (cdev->handle_request) {
+        return cdev->handle_request(orb, scsw, data);
+    } else {
+        return -ENOSYS;
+    }
+}
+
 static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
                                   char *sysfsdev,
                                   Error **errp)
@@ -69,6 +80,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
         return;
     }
     sch->driver_data = cdev;
+    sch->do_subchannel_work = do_subchannel_work_passthrough;
 
     ccw_dev->sch = sch;
     ret = css_sch_build_schib(sch, &cdev->hostid);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4e386e9..e6a6f74 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -701,6 +701,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
     sch->disable_cb = virtio_sch_disable_cb;
     sch->id.reserved = 0xff;
     sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
+    sch->do_subchannel_work = do_subchannel_work_virtual;
     ccw_dev->sch = sch;
     dev->indicators = NULL;
     dev->revision = -1;
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index c8c283a..ae687c5 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -90,6 +90,7 @@ struct SubchDev {
     /* transport-provided data: */
     int (*ccw_cb) (SubchDev *, CCW1);
     void (*disable_cb)(SubchDev *);
+    int (*do_subchannel_work) (SubchDev *, ORB *);
     SenseId id;
     void *driver_data;
 };
@@ -146,6 +147,9 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 void css_generate_css_crws(uint8_t cssid);
 void css_clear_sei_pending(void);
 void css_adapter_interrupt(uint8_t isc);
+int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data);
+int do_subchannel_work_virtual(SubchDev *sub, ORB *orb);
+int do_subchannel_work_passthrough(SubchDev *sub, ORB *orb);
 
 typedef enum {
     CSS_IO_ADAPTER_VIRTIO = 0,
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index 590bfa4..62a7771 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -244,6 +244,15 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb)
     case -EBUSY:
         cc = 2;
         break;
+    case -EFAULT:
+        /*
+         * TODO:
+         * I'm wondering whether there is something better
+         * to do for us here (like setting some device or
+         * subchannel status).
+         */
+        program_interrupt(env, PGM_ADDRESSING, 4);
+        return;
     case 0:
         cc = 0;
         break;
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 12/13] vfio/ccw: update sense data if a unit check is pending
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Concurrent-sense data is currently not delivered. This patch stores
the concurrent-sense data to the subchannel if a unit check is pending
and the concurrent-sense bit is enabled. Then a TSCH can retreive the
right IRB data back to the guest.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 3ff78c5..03687a8 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -94,6 +94,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
     CcwDevice *ccw_dev = CCW_DEVICE(cdev);
     SubchDev *sch = ccw_dev->sch;
     SCSW *s = &sch->curr_status.scsw;
+    PMCW *p = &sch->curr_status.pmcw;
     IRB irb;
 
     if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
@@ -133,6 +134,12 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
     /* Update control block via irb. */
     copy_scsw_to_guest(s, &irb.scsw);
 
+    /* If a uint check is pending, copy sense data. */
+    if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
+        (p->chars & PMCW_CHARS_MASK_CSENSE)) {
+        memcpy(sch->sense_data, irb.ecw, sizeof(irb.ecw));
+    }
+
 read_err:
     css_inject_io_interrupt(sch);
 }
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 12/13] vfio/ccw: update sense data if a unit check is pending
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Concurrent-sense data is currently not delivered. This patch stores
the concurrent-sense data to the subchannel if a unit check is pending
and the concurrent-sense bit is enabled. Then a TSCH can retreive the
right IRB data back to the guest.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 hw/vfio/ccw.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 3ff78c5..03687a8 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -94,6 +94,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
     CcwDevice *ccw_dev = CCW_DEVICE(cdev);
     SubchDev *sch = ccw_dev->sch;
     SCSW *s = &sch->curr_status.scsw;
+    PMCW *p = &sch->curr_status.pmcw;
     IRB irb;
 
     if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
@@ -133,6 +134,12 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
     /* Update control block via irb. */
     copy_scsw_to_guest(s, &irb.scsw);
 
+    /* If a uint check is pending, copy sense data. */
+    if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
+        (p->chars & PMCW_CHARS_MASK_CSENSE)) {
+        memcpy(sch->sense_data, irb.ecw, sizeof(irb.ecw));
+    }
+
 read_err:
     css_inject_io_interrupt(sch);
 }
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 13/13] MAINTAINERS: Add vfio-ccw maintainer
  2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
@ 2017-04-28 13:09   ` Dong Jia Shi
  -1 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Add Cornelia Huck as the vfio-ccw maintainer.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index cae3b09..c1f9917 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -999,6 +999,11 @@ S: Supported
 F: hw/vfio/*
 F: include/hw/vfio/
 
+vfio-ccw
+M: Cornelia Huck <cornelia.huck@de.ibm.com>
+S: Supported
+F: hw/vfio/ccw.c
+
 vhost
 M: Michael S. Tsirkin <mst@redhat.com>
 S: Supported
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [Qemu-devel] [PATCH v6 13/13] MAINTAINERS: Add vfio-ccw maintainer
@ 2017-04-28 13:09   ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-04-28 13:09 UTC (permalink / raw)
  To: kvm, linux-s390, qemu-devel
  Cc: bjsdjshi, cornelia.huck, borntraeger, agraf, alex.williamson

Add Cornelia Huck as the vfio-ccw maintainer.

Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index cae3b09..c1f9917 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -999,6 +999,11 @@ S: Supported
 F: hw/vfio/*
 F: include/hw/vfio/
 
+vfio-ccw
+M: Cornelia Huck <cornelia.huck@de.ibm.com>
+S: Supported
+F: hw/vfio/ccw.c
+
 vhost
 M: Michael S. Tsirkin <mst@redhat.com>
 S: Supported
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
@ 2017-05-01 11:08   ` Auger Eric
  2017-05-02  2:37     ` Dong Jia Shi
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:08 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: cornelia.huck, borntraeger, alex.williamson, agraf

Hi Dong,

On 28/04/2017 15:09, Dong Jia Shi wrote:
> In order to support subchannels pass-through, we introduce a s390
> subchannel device called "s390-ccw" to hold the real subchannel info.
> The s390-ccw devices inherit from the abstract CcwDevice which connect
> to the existing virtual-css-bus.
> 
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  hw/s390x/Makefile.objs |   1 +
>  hw/s390x/s390-ccw.c    | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/s390x/s390-ccw.h    |  38 ++++++++++++++
>  3 files changed, 174 insertions(+)
>  create mode 100644 hw/s390x/s390-ccw.c
>  create mode 100644 hw/s390x/s390-ccw.h
> 
> diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
> index 41ac4ec..72a3d37 100644
> --- a/hw/s390x/Makefile.objs
> +++ b/hw/s390x/Makefile.objs
> @@ -13,3 +13,4 @@ obj-y += ccw-device.o
>  obj-y += s390-pci-bus.o s390-pci-inst.o
>  obj-y += s390-skeys.o
>  obj-$(CONFIG_KVM) += s390-skeys-kvm.o
> +obj-y += s390-ccw.o
> diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
> new file mode 100644
> index 0000000..8b4b9cf
> --- /dev/null
> +++ b/hw/s390x/s390-ccw.c
> @@ -0,0 +1,135 @@
> +/*
> + * s390 CCW Assignment Support
> + *
> + * Copyright 2017 IBM Corp
> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> + *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> + *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/sysbus.h"
> +#include "libgen.h"
> +#include "hw/s390x/css.h"
> +#include "hw/s390x/css-bridge.h"
> +#include "s390-ccw.h"
> +
> +static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
> +                                  char *sysfsdev,
> +                                  Error **errp)
> +{
> +    unsigned int cssid, ssid, devid;
> +    char dev_path[PATH_MAX] = {0}, *tmp;
> +
> +    if (!sysfsdev) {
> +        error_setg(errp, "No host device provided");
> +        error_append_hint(errp,
> +                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
> +        return;
> +    }
> +
> +    if (!realpath(sysfsdev, dev_path)) {
> +        error_setg(errp, "Host device '%s' not found", sysfsdev);
nit: error_setg_errno may be used instead.
> +        return;
> +    }
> +
> +    cdev->mdevid = g_strdup(basename(dev_path));
> +
> +    tmp = basename(dirname(dev_path));
> +    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
I guess this is safe and you don't need to test the operation succeeded?
> +
> +    cdev->hostid.cssid = cssid;
> +    cdev->hostid.ssid = ssid;
> +    cdev->hostid.devid = devid;
> +    cdev->hostid.valid = true;
> +}
> +
> +static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
> +{
> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> +    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
> +    DeviceState *parent = DEVICE(ccw_dev);
> +    BusState *qbus = qdev_get_parent_bus(parent);
> +    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
> +    SubchDev *sch;
> +    int ret;
> +    Error *err = NULL;
> +
> +    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
> +    if (*errp) {
I was told in the past dereferencing errp is unclean in general because
callers may pass null to ignore errors, although the qdev core doesn't.
you may use local err in that case.
> +        return;
> +    }
> +
> +    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
> +    if (!sch) {
> +        return;
> +    }
> +    sch->driver_data = cdev;
> +
> +    ccw_dev->sch = sch;
> +    ret = css_sch_build_schib(sch, &cdev->hostid);
> +    if (ret) {
> +        error_setg(&err, "%s: Failed to build initial schib: %d",
> +                   __func__, ret);
> +        goto out_err;
> +    }
> +
> +    ck->realize(ccw_dev, &err);
> +    if (err) {
> +        goto out_err;
> +    }
> +
> +    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
> +                          parent->hotplugged, 1);
> +    return;
> +
> +out_err:
> +    error_propagate(errp, err);
> +    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> +    ccw_dev->sch = NULL;
> +    g_free(sch);
don't you need to free cdev->mdevid too?

Thanks

Eric
> +}
> +
> +static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
> +{
> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> +    SubchDev *sch = ccw_dev->sch;
> +
> +    if (sch) {
> +        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> +        g_free(sch);
> +        ccw_dev->sch = NULL;
> +    }
> +
> +    g_free(cdev->mdevid);
> +}
> +
> +static void s390_ccw_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_CLASS(klass);
> +
> +    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
> +    cdc->realize = s390_ccw_realize;
> +    cdc->unrealize = s390_ccw_unrealize;
> +}
> +
> +static const TypeInfo s390_ccw_info = {
> +    .name          = TYPE_S390_CCW,
> +    .parent        = TYPE_CCW_DEVICE,
> +    .instance_size = sizeof(S390CCWDevice),
> +    .class_size    = sizeof(S390CCWDeviceClass),
> +    .class_init    = s390_ccw_class_init,
> +    .abstract      = true,
> +};
> +
> +static void register_s390_ccw_type(void)
> +{
> +    type_register_static(&s390_ccw_info);
> +}
> +
> +type_init(register_s390_ccw_type)
> diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
> new file mode 100644
> index 0000000..b58d8e9
> --- /dev/null
> +++ b/hw/s390x/s390-ccw.h
> @@ -0,0 +1,38 @@
> +/*
> + * s390 CCW Assignment Support
> + *
> + * Copyright 2017 IBM Corp.
> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> + *            Xiao Feng Ren <renxiaof@linux.vnet.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.
> + */
> +
> +#ifndef HW_S390_CCW_H
> +#define HW_S390_CCW_H
> +
> +#include "hw/s390x/ccw-device.h"
> +
> +#define TYPE_S390_CCW "s390-ccw"
> +#define S390_CCW_DEVICE(obj) \
> +    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
> +#define S390_CCW_DEVICE_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
> +#define S390_CCW_DEVICE_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
> +
> +typedef struct S390CCWDevice {
> +    CcwDevice parent_obj;
> +    CssDevId hostid;
> +    char *mdevid;
> +} S390CCWDevice;
> +
> +typedef struct S390CCWDeviceClass {
> +    CCWDeviceClass parent_class;
> +    void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
> +    void (*unrealize)(S390CCWDevice *dev, Error **errp);
> +} S390CCWDeviceClass;
> +
> +#endif
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
@ 2017-05-01 11:08   ` Auger Eric
  2017-05-02  5:07     ` Dong Jia Shi
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:08 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: borntraeger, alex.williamson, Xiao Feng Ren, cornelia.huck, agraf

Hi Dong,

On 28/04/2017 15:09, Dong Jia Shi wrote:
> From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> 
> We use the IOMMU_TYPE1 of VFIO to realize the subchannels
> passthrough, implement a vfio based subchannels passthrough
> driver called "vfio-ccw".
> 
> Support qemu parameters in the style of:
> "-device vfio-ccw,sysfsdev=$mdev_file_path,devno=xx.x.xxxx'
> 
> Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  default-configs/s390x-softmmu.mak |   1 +
>  hw/vfio/Makefile.objs             |   1 +
>  hw/vfio/ccw.c                     | 189 ++++++++++++++++++++++++++++++++++++++
>  include/hw/vfio/vfio-common.h     |   1 +
>  4 files changed, 192 insertions(+)
>  create mode 100644 hw/vfio/ccw.c
> 
> diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
> index 36e15de..5576b0a 100644
> --- a/default-configs/s390x-softmmu.mak
> +++ b/default-configs/s390x-softmmu.mak
> @@ -4,4 +4,5 @@ CONFIG_VIRTIO=y
>  CONFIG_SCLPCONSOLE=y
>  CONFIG_S390_FLIC=y
>  CONFIG_S390_FLIC_KVM=$(CONFIG_KVM)
> +CONFIG_VFIO_CCW=$(CONFIG_LINUX)
>  CONFIG_WDT_DIAG288=y
> diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
> index 05e7fbb..c3ab909 100644
> --- a/hw/vfio/Makefile.objs
> +++ b/hw/vfio/Makefile.objs
> @@ -1,6 +1,7 @@
>  ifeq ($(CONFIG_LINUX), y)
>  obj-$(CONFIG_SOFTMMU) += common.o
>  obj-$(CONFIG_PCI) += pci.o pci-quirks.o
> +obj-$(CONFIG_VFIO_CCW) += ccw.o
>  obj-$(CONFIG_SOFTMMU) += platform.o
>  obj-$(CONFIG_VFIO_XGMAC) += calxeda-xgmac.o
>  obj-$(CONFIG_VFIO_AMD_XGBE) += amd-xgbe.o
> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> new file mode 100644
> index 0000000..cd4dfe8
> --- /dev/null
> +++ b/hw/vfio/ccw.c
> @@ -0,0 +1,189 @@
> +/*
> + * vfio based subchannel assignment support
> + *
> + * Copyright 2017 IBM Corp.
> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> + *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> + *            Pierre Morel <pmorel@linux.vnet.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or(at
> + * your option) any version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#include <linux/vfio.h>
> +#include <sys/ioctl.h>
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/sysbus.h"
> +#include "hw/vfio/vfio.h"
> +#include "hw/vfio/vfio-common.h"
> +#include "hw/s390x/s390-ccw.h"
> +#include "hw/s390x/ccw-device.h"
> +
> +#define TYPE_VFIO_CCW "vfio-ccw"
> +typedef struct VFIOCCWDevice {
> +    S390CCWDevice cdev;
> +    VFIODevice vdev;
> +} VFIOCCWDevice;
> +
> +static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
> +{
> +    vdev->needs_reset = false;
> +}
> +
> +/*
> + * We don't need vfio_hot_reset_multi and vfio_eoi operations for
> + * vfio_ccw device now.
> + */
> +struct VFIODeviceOps vfio_ccw_ops = {
> +    .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
> +};
> +
> +static void vfio_ccw_reset(DeviceState *dev)
> +{
> +    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> +    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
> +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> +
> +    ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
> +}
> +
> +static void vfio_put_device(VFIOCCWDevice *vcdev)
> +{
> +    g_free(vcdev->vdev.name);
> +    vfio_put_base_device(&vcdev->vdev);
> +}
> +
> +static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp)
> +{
> +    char *tmp, group_path[PATH_MAX];
> +    ssize_t len;
> +    int groupid;
> +
> +    tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group",
> +                          cdev->hostid.cssid, cdev->hostid.ssid,
> +                          cdev->hostid.devid, cdev->mdevid);
May be worth replacing this static function by a common
vfio_get_device_group(VFIODevice *vbasedev, Error **errp) in common.c
that would be used by vfio/pci devices? It would use the sysfsdev
populated before.
> +    len = readlink(tmp, group_path, sizeof(group_path));
> +    g_free(tmp);
> +
> +    if (len <= 0 || len >= sizeof(group_path)) {
> +        error_setg(errp, "vfio: no iommu_group found");
may be good to align the error message with pci/platform. I noticed the
case where len==0 is handled as ENAMETOOLONG on pci/platform which looks
bad. Maybe this is why you changed it.
> +        return NULL;
> +    }
> +
> +    group_path[len] = 0;
> +
> +    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
> +        error_setg(errp, "vfio: failed to read %s", group_path);
> +        return NULL;
> +    }
> +
> +    return vfio_get_group(groupid, &address_space_memory, errp);
> +}
> +
> +static void vfio_ccw_put_group(VFIOGroup *group)
Is it really needed?
> +{
> +    vfio_put_group(group);
> +}
> +
> +static void vfio_ccw_realize(DeviceState *dev, Error **errp)
> +{
> +    VFIODevice *vbasedev;
> +    VFIOGroup *group;
> +    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> +    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
> +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
> +
> +    /* Call the class init function for subchannel. */
> +    if (cdc->realize) {
> +        cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
> +        if (*errp) {
use local err?

Thanks

Eric
> +            return;
> +        }
> +    }
> +
> +    group = vfio_ccw_get_group(cdev, errp);
> +    if (!group) {
> +        goto out_group_err;
> +    }
> +
> +    vcdev->vdev.ops = &vfio_ccw_ops;
> +    vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW;
> +    vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid,
> +                                       cdev->hostid.ssid, cdev->hostid.devid);
> +    QLIST_FOREACH(vbasedev, &group->device_list, next) {
> +        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
> +            error_setg(errp, "vfio: subchannel %s has already been attached",
> +                       vcdev->vdev.name);
> +            goto out_device_err;
> +        }
> +    }
> +
> +    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) {
> +        goto out_device_err;
> +    }
> +
> +    return;
> +
> +out_device_err:
> +    vfio_ccw_put_group(group);
> +out_group_err:
> +    if (cdc->unrealize) {
> +        cdc->unrealize(cdev, errp);
> +    }
> +}
> +
> +static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
> +{
> +    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> +    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
> +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
> +    VFIOGroup *group = vcdev->vdev.group;
> +
> +    vfio_put_device(vcdev);
> +    vfio_put_group(group);
> +
> +    if (cdc->unrealize) {
> +        cdc->unrealize(cdev, errp);
> +    }
> +}
> +
> +static Property vfio_ccw_properties[] = {
> +    DEFINE_PROP_STRING("sysfsdev", VFIOCCWDevice, vdev.sysfsdev),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static const VMStateDescription vfio_ccw_vmstate = {
> +    .name = TYPE_VFIO_CCW,
> +    .unmigratable = 1,
> +};
> +
> +static void vfio_ccw_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->props = vfio_ccw_properties;
> +    dc->vmsd = &vfio_ccw_vmstate;
> +    dc->desc = "VFIO-based subchannel assignment";
> +    dc->realize = vfio_ccw_realize;
> +    dc->unrealize = vfio_ccw_unrealize;
> +    dc->reset = vfio_ccw_reset;
> +}
> +
> +static const TypeInfo vfio_ccw_info = {
> +    .name = TYPE_VFIO_CCW,
> +    .parent = TYPE_S390_CCW,
> +    .instance_size = sizeof(VFIOCCWDevice),
> +    .class_init = vfio_ccw_class_init,
> +};
> +
> +static void register_vfio_ccw_type(void)
> +{
> +    type_register_static(&vfio_ccw_info);
> +}
> +
> +type_init(register_vfio_ccw_type)
> diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
> index c582de1..9521013 100644
> --- a/include/hw/vfio/vfio-common.h
> +++ b/include/hw/vfio/vfio-common.h
> @@ -45,6 +45,7 @@
>  enum {
>      VFIO_DEVICE_TYPE_PCI = 0,
>      VFIO_DEVICE_TYPE_PLATFORM = 1,
> +    VFIO_DEVICE_TYPE_CCW = 2,
>  };
>  
>  typedef struct VFIOMmap {
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 08/13] vfio/ccw: get io region info
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
@ 2017-05-01 11:08   ` Auger Eric
  2017-05-02  5:16     ` Dong Jia Shi
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:08 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: cornelia.huck, borntraeger, alex.williamson, agraf

Hi,

On 28/04/2017 15:09, Dong Jia Shi wrote:
> vfio-ccw provides an MMIO region for I/O operations. We fetch its
> information via ioctls here, then we can use it performing I/O
> instructions and retrieving I/O results later on.
> 
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  hw/vfio/ccw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> index cd4dfe8..a285b23 100644
> --- a/hw/vfio/ccw.c
> +++ b/hw/vfio/ccw.c
> @@ -12,6 +12,7 @@
>   */
>  
>  #include <linux/vfio.h>
> +#include <linux/vfio_ccw.h>
>  #include <sys/ioctl.h>
>  
>  #include "qemu/osdep.h"
> @@ -26,6 +27,9 @@
>  typedef struct VFIOCCWDevice {
>      S390CCWDevice cdev;
>      VFIODevice vdev;
> +    uint64_t io_region_size;
> +    uint64_t io_region_offset;
> +    struct ccw_io_region *io_region;
>  } VFIOCCWDevice;
>  
>  static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
> @@ -50,6 +54,46 @@ static void vfio_ccw_reset(DeviceState *dev)
>      ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
>  }
>  
> +static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
> +{
> +    VFIODevice *vdev = &vcdev->vdev;
> +    struct vfio_region_info *info;
> +    int ret;
> +
> +    /* Sanity check device */
> +    if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) {
> +        error_setg(errp, "vfio: Um, this isn't a vfio-ccw device");
> +        return;
> +    }
> +
> +    if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
> +        error_setg(errp, "vfio: Unexpected number of the I/O region %u",
> +                   vdev->num_regions);
> +        return;
> +    }
> +
> +    ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
> +    if (ret) {
> +        error_setg(errp, "vfio: Error getting config info: %d", ret);
> +        return;
> +    }
> +
> +    vcdev->io_region_size = info->size;
> +    if (sizeof(*vcdev->io_region) != vcdev->io_region_size) {
> +        error_setg(errp, "vfio: Unexpected size of the I/O region");
g_free(info)
> +        return;
> +    }
> +    vcdev->io_region_offset = info->offset;
> +    vcdev->io_region = g_malloc0(info->size);
> +
> +    g_free(info);
> +}
> +
> +static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
> +{
> +    g_free(vcdev->io_region);
> +}
> +
>  static void vfio_put_device(VFIOCCWDevice *vcdev)
>  {
>      g_free(vcdev->vdev.name);
> @@ -126,8 +170,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
>          goto out_device_err;
>      }
>  
> +    vfio_ccw_get_region(vcdev, errp);
> +    if (*errp) {
local err?

Thanks

Eric
> +        goto out_region_err;
> +    }
> +
>      return;
>  
> +out_region_err:
> +    vfio_put_device(vcdev);
>  out_device_err:
>      vfio_ccw_put_group(group);
>  out_group_err:
> @@ -144,6 +195,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
>      S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
>      VFIOGroup *group = vcdev->vdev.group;
>  
> +    vfio_ccw_put_region(vcdev);
>      vfio_put_device(vcdev);
>      vfio_put_group(group);
>  
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
@ 2017-05-01 11:08   ` Auger Eric
  2017-05-02  5:37     ` Dong Jia Shi
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:08 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: cornelia.huck, borntraeger, alex.williamson, agraf

Hi,
On 28/04/2017 15:09, Dong Jia Shi wrote:
> vfio-ccw resorts to the eventfd mechanism to communicate with userspace.
> We fetch the irqs info via the ioctl VFIO_DEVICE_GET_IRQ_INFO,
> register a event notifier to get the eventfd fd which is sent
> to kernel via the ioctl VFIO_DEVICE_SET_IRQS, then we can implement
> read operation once kernel sends the signal.
> 
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  hw/vfio/ccw.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 102 insertions(+)
> 
> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> index a285b23..cda3057 100644
> --- a/hw/vfio/ccw.c
> +++ b/hw/vfio/ccw.c
> @@ -22,6 +22,7 @@
>  #include "hw/vfio/vfio-common.h"
>  #include "hw/s390x/s390-ccw.h"
>  #include "hw/s390x/ccw-device.h"
> +#include "qemu/error-report.h"
>  
>  #define TYPE_VFIO_CCW "vfio-ccw"
>  typedef struct VFIOCCWDevice {
> @@ -30,6 +31,7 @@ typedef struct VFIOCCWDevice {
>      uint64_t io_region_size;
>      uint64_t io_region_offset;
>      struct ccw_io_region *io_region;
> +    EventNotifier io_notifier;
>  } VFIOCCWDevice;
>  
>  static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
> @@ -54,6 +56,98 @@ static void vfio_ccw_reset(DeviceState *dev)
>      ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
>  }
>  
> +static void vfio_ccw_io_notifier_handler(void *opaque)
> +{
> +    VFIOCCWDevice *vcdev = opaque;
> +
> +    if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> +        return;
> +    }
> +}
> +
> +static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
> +{
> +    VFIODevice *vdev = &vcdev->vdev;
> +    struct vfio_irq_info *irq_info;
> +    struct vfio_irq_set *irq_set;
> +    size_t argsz;
> +    int32_t *pfd;
> +
> +    if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) {
> +        error_setg(errp, "vfio: unexpected number of io irqs %u",
> +                   vdev->num_irqs);
> +        return;
> +    }
> +
> +    argsz = sizeof(*irq_set);
> +    irq_info = g_malloc0(argsz);
> +    irq_info->index = VFIO_CCW_IO_IRQ_INDEX;
> +    irq_info->argsz = argsz;
> +    if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
> +              irq_info) < 0 || irq_info->count < 1) {
> +        error_setg(errp, "vfio: Error getting irq info");
nit: error_setg_errno?
> +        goto get_error;
> +    }
> +
> +    if (event_notifier_init(&vcdev->io_notifier, 0)) {
> +        error_setg(errp, "vfio: Unable to init event notifier for IO");
nit: same
> +        goto get_error;
> +    }
> +
> +    argsz = sizeof(*irq_set) + sizeof(*pfd);
> +    irq_set = g_malloc0(argsz);
> +    irq_set->argsz = argsz;
> +    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
> +                     VFIO_IRQ_SET_ACTION_TRIGGER;
> +    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
> +    irq_set->start = 0;
> +    irq_set->count = 1;
> +    pfd = (int32_t *) &irq_set->data;
> +
> +    *pfd = event_notifier_get_fd(&vcdev->io_notifier);
> +    qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev);
> +    if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
> +        error_setg(errp, "vfio: Failed to set up io notification");
> +        qemu_set_fd_handler(*pfd, NULL, NULL, vcdev);
> +        event_notifier_cleanup(&vcdev->io_notifier);
> +        goto set_error;
> +    }
> +
> +set_error:
> +    g_free(irq_set);
> +
> +get_error:
> +    g_free(irq_info);
> +}
> +
> +static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
> +{
> +    struct vfio_irq_set *irq_set;
> +    size_t argsz;
> +    int32_t *pfd;
> +
> +    argsz = sizeof(*irq_set) + sizeof(*pfd);
> +    irq_set = g_malloc0(argsz);
> +    irq_set->argsz = argsz;
> +    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
> +                     VFIO_IRQ_SET_ACTION_TRIGGER;
> +    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
> +    irq_set->start = 0;
> +    irq_set->count = 1;
> +    pfd = (int32_t *) &irq_set->data;
> +    *pfd = -1;
> +
> +    if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
> +        error_report("vfio: Failed to de-assign device io fd");
ditto
> +    }
> +
> +    qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier),
> +                        NULL, NULL, vcdev);
> +    event_notifier_cleanup(&vcdev->io_notifier);
> +
> +    g_free(irq_set);
> +}
> +
>  static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
>  {
>      VFIODevice *vdev = &vcdev->vdev;
> @@ -175,8 +269,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
>          goto out_region_err;
>      }
>  
> +    vfio_ccw_register_io_notifier(vcdev, errp);
> +    if (*errp) {
ditto

Thanks

Eric
> +        goto out_notifier_err;
> +    }
> +
>      return;
>  
> +out_notifier_err:
> +    vfio_ccw_put_region(vcdev);
>  out_region_err:
>      vfio_put_device(vcdev);
>  out_device_err:
> @@ -195,6 +296,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
>      S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
>      VFIOGroup *group = vcdev->vdev.group;
>  
> +    vfio_ccw_unregister_io_notifier(vcdev);
>      vfio_ccw_put_region(vcdev);
>      vfio_put_device(vcdev);
>      vfio_put_group(group);
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
  (?)
@ 2017-05-01 11:20   ` Auger Eric
  2017-05-01 11:24     ` Auger Eric
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:20 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: cornelia.huck, borntraeger, alex.williamson, agraf

Hi Dong,

On 28/04/2017 15:09, Dong Jia Shi wrote:
> In order to support subchannels pass-through, we introduce a s390
> subchannel device called "s390-ccw" to hold the real subchannel info.
> The s390-ccw devices inherit from the abstract CcwDevice which connect
> to the existing virtual-css-bus.
> 
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  hw/s390x/Makefile.objs |   1 +
>  hw/s390x/s390-ccw.c    | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/s390x/s390-ccw.h    |  38 ++++++++++++++
>  3 files changed, 174 insertions(+)
>  create mode 100644 hw/s390x/s390-ccw.c
>  create mode 100644 hw/s390x/s390-ccw.h
> 
> diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
> index 41ac4ec..72a3d37 100644
> --- a/hw/s390x/Makefile.objs
> +++ b/hw/s390x/Makefile.objs
> @@ -13,3 +13,4 @@ obj-y += ccw-device.o
>  obj-y += s390-pci-bus.o s390-pci-inst.o
>  obj-y += s390-skeys.o
>  obj-$(CONFIG_KVM) += s390-skeys-kvm.o
> +obj-y += s390-ccw.o
> diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
> new file mode 100644
> index 0000000..8b4b9cf
> --- /dev/null
> +++ b/hw/s390x/s390-ccw.c
> @@ -0,0 +1,135 @@
> +/*
> + * s390 CCW Assignment Support
> + *
> + * Copyright 2017 IBM Corp
> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> + *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> + *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "hw/sysbus.h"
> +#include "libgen.h"
> +#include "hw/s390x/css.h"
> +#include "hw/s390x/css-bridge.h"
> +#include "s390-ccw.h"
> +
> +static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
> +                                  char *sysfsdev,
> +                                  Error **errp)
> +{
> +    unsigned int cssid, ssid, devid;
> +    char dev_path[PATH_MAX] = {0}, *tmp;
> +
> +    if (!sysfsdev) {
> +        error_setg(errp, "No host device provided");
> +        error_append_hint(errp,
> +                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
> +        return;
> +    }
> +
> +    if (!realpath(sysfsdev, dev_path)) {
> +        error_setg(errp, "Host device '%s' not found", sysfsdev);
> +        return;
> +    }
> +
> +    cdev->mdevid = g_strdup(basename(dev_path));
> +
> +    tmp = basename(dirname(dev_path));
> +    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
I guess you don't need to check sscanf succeeded?
> +
> +    cdev->hostid.cssid = cssid;
> +    cdev->hostid.ssid = ssid;
> +    cdev->hostid.devid = devid;
> +    cdev->hostid.valid = true;
> +}
> +
> +static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
> +{
> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> +    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
> +    DeviceState *parent = DEVICE(ccw_dev);
> +    BusState *qbus = qdev_get_parent_bus(parent);
> +    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
> +    SubchDev *sch;
> +    int ret;
> +    Error *err = NULL;
> +
> +    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
> +    if (*errp) {
In the past, I was told by Markus that derefencing errp was not clean in
general since caller could pass NULL to ignore errors (although qdev
core doesn't). You may use a local error instead.
> +        return;
> +    }
> +
> +    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
> +    if (!sch) {
> +        return;
> +    }
> +    sch->driver_data = cdev;
> +
> +    ccw_dev->sch = sch;
> +    ret = css_sch_build_schib(sch, &cdev->hostid);
> +    if (ret) {
> +        error_setg(&err, "%s: Failed to build initial schib: %d",
> +                   __func__, ret);
> +        goto out_err;
> +    }
> +
> +    ck->realize(ccw_dev, &err);
> +    if (err) {
> +        goto out_err;
> +    }
> +
> +    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
> +                          parent->hotplugged, 1);
> +    return;
> +
> +out_err:
> +    error_propagate(errp, err);
> +    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> +    ccw_dev->sch = NULL;
> +    g_free(sch);
don't you want to free cdev->mdevid too?

Thanks

Eric
> +}
> +
> +static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
> +{
> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> +    SubchDev *sch = ccw_dev->sch;
> +
> +    if (sch) {
> +        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> +        g_free(sch);
> +        ccw_dev->sch = NULL;
> +    }
> +
> +    g_free(cdev->mdevid);
> +}
> +
> +static void s390_ccw_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_CLASS(klass);
> +
> +    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
> +    cdc->realize = s390_ccw_realize;
> +    cdc->unrealize = s390_ccw_unrealize;
> +}
> +
> +static const TypeInfo s390_ccw_info = {
> +    .name          = TYPE_S390_CCW,
> +    .parent        = TYPE_CCW_DEVICE,
> +    .instance_size = sizeof(S390CCWDevice),
> +    .class_size    = sizeof(S390CCWDeviceClass),
> +    .class_init    = s390_ccw_class_init,
> +    .abstract      = true,
> +};
> +
> +static void register_s390_ccw_type(void)
> +{
> +    type_register_static(&s390_ccw_info);
> +}
> +
> +type_init(register_s390_ccw_type)
> diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
> new file mode 100644
> index 0000000..b58d8e9
> --- /dev/null
> +++ b/hw/s390x/s390-ccw.h
> @@ -0,0 +1,38 @@
> +/*
> + * s390 CCW Assignment Support
> + *
> + * Copyright 2017 IBM Corp.
> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> + *            Xiao Feng Ren <renxiaof@linux.vnet.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.
> + */
> +
> +#ifndef HW_S390_CCW_H
> +#define HW_S390_CCW_H
> +
> +#include "hw/s390x/ccw-device.h"
> +
> +#define TYPE_S390_CCW "s390-ccw"
> +#define S390_CCW_DEVICE(obj) \
> +    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
> +#define S390_CCW_DEVICE_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
> +#define S390_CCW_DEVICE_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
> +
> +typedef struct S390CCWDevice {
> +    CcwDevice parent_obj;
> +    CssDevId hostid;
> +    char *mdevid;
> +} S390CCWDevice;
> +
> +typedef struct S390CCWDeviceClass {
> +    CCWDeviceClass parent_class;
> +    void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
> +    void (*unrealize)(S390CCWDevice *dev, Error **errp);
> +} S390CCWDeviceClass;
> +
> +#endif
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
  2017-05-01 11:20   ` Auger Eric
@ 2017-05-01 11:24     ` Auger Eric
  0 siblings, 0 replies; 45+ messages in thread
From: Auger Eric @ 2017-05-01 11:24 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel

Hi Dong,

On 01/05/2017 13:20, Auger Eric wrote:
> Hi Dong,
> 
> On 28/04/2017 15:09, Dong Jia Shi wrote:
>> In order to support subchannels pass-through, we introduce a s390
>> subchannel device called "s390-ccw" to hold the real subchannel info.
>> The s390-ccw devices inherit from the abstract CcwDevice which connect
>> to the existing virtual-css-bus.

Forget that one. Thought my first reply has not been sent.

Thanks

Eric
>>
>> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
>> ---
>>  hw/s390x/Makefile.objs |   1 +
>>  hw/s390x/s390-ccw.c    | 135 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  hw/s390x/s390-ccw.h    |  38 ++++++++++++++
>>  3 files changed, 174 insertions(+)
>>  create mode 100644 hw/s390x/s390-ccw.c
>>  create mode 100644 hw/s390x/s390-ccw.h
>>
>> diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
>> index 41ac4ec..72a3d37 100644
>> --- a/hw/s390x/Makefile.objs
>> +++ b/hw/s390x/Makefile.objs
>> @@ -13,3 +13,4 @@ obj-y += ccw-device.o
>>  obj-y += s390-pci-bus.o s390-pci-inst.o
>>  obj-y += s390-skeys.o
>>  obj-$(CONFIG_KVM) += s390-skeys-kvm.o
>> +obj-y += s390-ccw.o
>> diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
>> new file mode 100644
>> index 0000000..8b4b9cf
>> --- /dev/null
>> +++ b/hw/s390x/s390-ccw.c
>> @@ -0,0 +1,135 @@
>> +/*
>> + * s390 CCW Assignment Support
>> + *
>> + * Copyright 2017 IBM Corp
>> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
>> + *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
>> + *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "hw/sysbus.h"
>> +#include "libgen.h"
>> +#include "hw/s390x/css.h"
>> +#include "hw/s390x/css-bridge.h"
>> +#include "s390-ccw.h"
>> +
>> +static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
>> +                                  char *sysfsdev,
>> +                                  Error **errp)
>> +{
>> +    unsigned int cssid, ssid, devid;
>> +    char dev_path[PATH_MAX] = {0}, *tmp;
>> +
>> +    if (!sysfsdev) {
>> +        error_setg(errp, "No host device provided");
>> +        error_append_hint(errp,
>> +                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
>> +        return;
>> +    }
>> +
>> +    if (!realpath(sysfsdev, dev_path)) {
>> +        error_setg(errp, "Host device '%s' not found", sysfsdev);
>> +        return;
>> +    }
>> +
>> +    cdev->mdevid = g_strdup(basename(dev_path));
>> +
>> +    tmp = basename(dirname(dev_path));
>> +    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
> I guess you don't need to check sscanf succeeded?
>> +
>> +    cdev->hostid.cssid = cssid;
>> +    cdev->hostid.ssid = ssid;
>> +    cdev->hostid.devid = devid;
>> +    cdev->hostid.valid = true;
>> +}
>> +
>> +static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
>> +{
>> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
>> +    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
>> +    DeviceState *parent = DEVICE(ccw_dev);
>> +    BusState *qbus = qdev_get_parent_bus(parent);
>> +    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
>> +    SubchDev *sch;
>> +    int ret;
>> +    Error *err = NULL;
>> +
>> +    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
>> +    if (*errp) {
> In the past, I was told by Markus that derefencing errp was not clean in
> general since caller could pass NULL to ignore errors (although qdev
> core doesn't). You may use a local error instead.
>> +        return;
>> +    }
>> +
>> +    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
>> +    if (!sch) {
>> +        return;
>> +    }
>> +    sch->driver_data = cdev;
>> +
>> +    ccw_dev->sch = sch;
>> +    ret = css_sch_build_schib(sch, &cdev->hostid);
>> +    if (ret) {
>> +        error_setg(&err, "%s: Failed to build initial schib: %d",
>> +                   __func__, ret);
>> +        goto out_err;
>> +    }
>> +
>> +    ck->realize(ccw_dev, &err);
>> +    if (err) {
>> +        goto out_err;
>> +    }
>> +
>> +    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
>> +                          parent->hotplugged, 1);
>> +    return;
>> +
>> +out_err:
>> +    error_propagate(errp, err);
>> +    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
>> +    ccw_dev->sch = NULL;
>> +    g_free(sch);
> don't you want to free cdev->mdevid too?
> 
> Thanks
> 
> Eric
>> +}
>> +
>> +static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
>> +{
>> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
>> +    SubchDev *sch = ccw_dev->sch;
>> +
>> +    if (sch) {
>> +        css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
>> +        g_free(sch);
>> +        ccw_dev->sch = NULL;
>> +    }
>> +
>> +    g_free(cdev->mdevid);
>> +}
>> +
>> +static void s390_ccw_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_CLASS(klass);
>> +
>> +    dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
>> +    cdc->realize = s390_ccw_realize;
>> +    cdc->unrealize = s390_ccw_unrealize;
>> +}
>> +
>> +static const TypeInfo s390_ccw_info = {
>> +    .name          = TYPE_S390_CCW,
>> +    .parent        = TYPE_CCW_DEVICE,
>> +    .instance_size = sizeof(S390CCWDevice),
>> +    .class_size    = sizeof(S390CCWDeviceClass),
>> +    .class_init    = s390_ccw_class_init,
>> +    .abstract      = true,
>> +};
>> +
>> +static void register_s390_ccw_type(void)
>> +{
>> +    type_register_static(&s390_ccw_info);
>> +}
>> +
>> +type_init(register_s390_ccw_type)
>> diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
>> new file mode 100644
>> index 0000000..b58d8e9
>> --- /dev/null
>> +++ b/hw/s390x/s390-ccw.h
>> @@ -0,0 +1,38 @@
>> +/*
>> + * s390 CCW Assignment Support
>> + *
>> + * Copyright 2017 IBM Corp.
>> + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
>> + *            Xiao Feng Ren <renxiaof@linux.vnet.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.
>> + */
>> +
>> +#ifndef HW_S390_CCW_H
>> +#define HW_S390_CCW_H
>> +
>> +#include "hw/s390x/ccw-device.h"
>> +
>> +#define TYPE_S390_CCW "s390-ccw"
>> +#define S390_CCW_DEVICE(obj) \
>> +    OBJECT_CHECK(S390CCWDevice, (obj), TYPE_S390_CCW)
>> +#define S390_CCW_DEVICE_CLASS(klass) \
>> +    OBJECT_CLASS_CHECK(S390CCWDeviceClass, (klass), TYPE_S390_CCW)
>> +#define S390_CCW_DEVICE_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(S390CCWDeviceClass, (obj), TYPE_S390_CCW)
>> +
>> +typedef struct S390CCWDevice {
>> +    CcwDevice parent_obj;
>> +    CssDevId hostid;
>> +    char *mdevid;
>> +} S390CCWDevice;
>> +
>> +typedef struct S390CCWDeviceClass {
>> +    CCWDeviceClass parent_class;
>> +    void (*realize)(S390CCWDevice *dev, char *sysfsdev, Error **errp);
>> +    void (*unrealize)(S390CCWDevice *dev, Error **errp);
>> +} S390CCWDeviceClass;
>> +
>> +#endif
>>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
  (?)
@ 2017-05-01 17:28   ` Auger Eric
  2017-05-02  2:15     ` Dong Jia Shi
  -1 siblings, 1 reply; 45+ messages in thread
From: Auger Eric @ 2017-05-01 17:28 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel
  Cc: borntraeger, alex.williamson, Xiao Feng Ren, cornelia.huck, agraf

Hi Dong,

On 28/04/2017 15:09, Dong Jia Shi wrote:
> From: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> 
> Introduce a new callback on subchannel to handle ccw-request.
> Realize the callback in vfio-ccw device. Besides, resort to
> the event notifier handler to handling the ccw-request results.
> 1. Pread the I/O results via MMIO region.
> 2. Update the scsw info to guest.
> 3. Inject an I/O interrupt to notify guest the I/O result.
> 
> Signed-off-by: Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> ---
>  hw/s390x/css.c         |  4 +--
>  hw/s390x/s390-ccw.h    |  1 +
>  hw/vfio/ccw.c          | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/s390x/css.h |  2 ++
>  4 files changed, 78 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 1052eea..507c60f 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -259,7 +259,7 @@ uint16_t css_build_subchannel_id(SubchDev *sch)
>      return css_do_build_subchannel_id(sch->cssid, sch->ssid);
>  }
>  
> -static void css_inject_io_interrupt(SubchDev *sch)
> +void css_inject_io_interrupt(SubchDev *sch)
>  {
>      uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
>  
> @@ -668,7 +668,7 @@ static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
>      dest->chars = cpu_to_be32(src->chars);
>  }
>  
> -static void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
> +void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
>  {
>      dest->flags = cpu_to_be16(src->flags);
>      dest->ctrl = cpu_to_be16(src->ctrl);
> diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
> index b58d8e9..4e2fa65 100644
> --- a/hw/s390x/s390-ccw.h
> +++ b/hw/s390x/s390-ccw.h
> @@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
>      CcwDevice parent_obj;
>      CssDevId hostid;
>      char *mdevid;
> +    int (*handle_request) (ORB *, SCSW *, void *);
shouldn't this callback be part of the class instead?

>  } S390CCWDevice;
>  
>  typedef struct S390CCWDeviceClass {
> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> index cda3057..3ff78c5 100644
> --- a/hw/vfio/ccw.c
> +++ b/hw/vfio/ccw.c
> @@ -47,6 +47,36 @@ struct VFIODeviceOps vfio_ccw_ops = {
>      .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
>  };
>  
> +static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
> +{
> +    S390CCWDevice *cdev = data;
> +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> +    struct ccw_io_region *region = vcdev->io_region;
> +    int ret;
> +
> +    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));
> +    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));
> +    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));
> +
> +    memset(region, 0, sizeof(*region));
> +
> +    memcpy(region->orb_area, orb, sizeof(ORB));
> +    memcpy(region->scsw_area, scsw, sizeof(SCSW));
> +
> +again:
> +    ret = pwrite(vcdev->vdev.fd, region,
> +                 vcdev->io_region_size, vcdev->io_region_offset);
> +    if (ret != vcdev->io_region_size) {
> +        if (errno == EAGAIN) {
> +            goto again;
> +        }
> +        error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);
> +        return -errno;
> +    }
> +
> +    return region->ret_code;
> +}
> +
>  static void vfio_ccw_reset(DeviceState *dev)
>  {
>      CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> @@ -59,10 +89,52 @@ static void vfio_ccw_reset(DeviceState *dev)
>  static void vfio_ccw_io_notifier_handler(void *opaque)
>  {
>      VFIOCCWDevice *vcdev = opaque;
> +    struct ccw_io_region *region = vcdev->io_region;
> +    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
> +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> +    SubchDev *sch = ccw_dev->sch;
> +    SCSW *s = &sch->curr_status.scsw;
> +    IRB irb;
>  
>      if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
>          return;
>      }
> +
> +    if (pread(vcdev->vdev.fd, region,
> +              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
is it possible to read less bytes than requested?

Thanks

Eric
> +        switch (errno) {
> +        case ENODEV:
> +            /* Generate a deferred cc 3 condition. */
> +            s->flags |= SCSW_FLAGS_MASK_CC;
> +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> +            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
> +            goto read_err;
> +        case EFAULT:
> +            /* memory problem, generate channel data check */
> +            s->ctrl &= ~SCSW_ACTL_START_PEND;
> +            s->cstat = SCSW_CSTAT_DATA_CHECK;
> +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> +            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
> +                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
> +            goto read_err;
> +        default:
> +            /* error, generate channel program check */
> +            s->ctrl &= ~SCSW_ACTL_START_PEND;
> +            s->cstat = SCSW_CSTAT_PROG_CHECK;
> +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> +            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
> +                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
> +            goto read_err;
> +        }
> +    }
> +
> +    memcpy(&irb, region->irb_area, sizeof(IRB));
> +
> +    /* Update control block via irb. */
> +    copy_scsw_to_guest(s, &irb.scsw);
> +
> +read_err:
> +    css_inject_io_interrupt(sch);
>  }
>  
>  static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
> @@ -235,6 +307,7 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
>      VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
>      S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
>  
> +    cdev->handle_request = vfio_ccw_handle_request;
>      /* Call the class init function for subchannel. */
>      if (cdc->realize) {
>          cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
> diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
> index a8bf1db..c8c283a 100644
> --- a/include/hw/s390x/css.h
> +++ b/include/hw/s390x/css.h
> @@ -135,6 +135,8 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
>  void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
>  int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
>  uint16_t css_build_subchannel_id(SubchDev *sch);
> +void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
> +void css_inject_io_interrupt(SubchDev *sch);
>  void css_reset(void);
>  void css_reset_sch(SubchDev *sch);
>  void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-05-01 17:28   ` Auger Eric
@ 2017-05-02  2:15     ` Dong Jia Shi
  2017-05-02 16:04       ` Cornelia Huck
  0 siblings, 1 reply; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  2:15 UTC (permalink / raw)
  To: Auger Eric
  Cc: Dong Jia Shi, kvm, linux-s390, qemu-devel, borntraeger,
	alex.williamson, Xiao Feng Ren, cornelia.huck, agraf

* Auger Eric <eric.auger@redhat.com> [2017-05-01 19:28:23 +0200]:

Hi Eric,

> > diff --git a/hw/s390x/s390-ccw.h b/hw/s390x/s390-ccw.h
> > index b58d8e9..4e2fa65 100644
> > --- a/hw/s390x/s390-ccw.h
> > +++ b/hw/s390x/s390-ccw.h
> > @@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
> >      CcwDevice parent_obj;
> >      CssDevId hostid;
> >      char *mdevid;
> > +    int (*handle_request) (ORB *, SCSW *, void *);
> shouldn't this callback be part of the class instead?
Ok. This sounds more proper.

> 
> >  } S390CCWDevice;
> >  
> >  typedef struct S390CCWDeviceClass {
> > diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> > index cda3057..3ff78c5 100644
> > --- a/hw/vfio/ccw.c
> > +++ b/hw/vfio/ccw.c
> > @@ -47,6 +47,36 @@ struct VFIODeviceOps vfio_ccw_ops = {
> >      .vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
> >  };
> >  
> > +static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
> > +{
> > +    S390CCWDevice *cdev = data;
> > +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> > +    struct ccw_io_region *region = vcdev->io_region;
> > +    int ret;
> > +
> > +    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));
> > +    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));
> > +    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));
> > +
> > +    memset(region, 0, sizeof(*region));
> > +
> > +    memcpy(region->orb_area, orb, sizeof(ORB));
> > +    memcpy(region->scsw_area, scsw, sizeof(SCSW));
> > +
> > +again:
> > +    ret = pwrite(vcdev->vdev.fd, region,
> > +                 vcdev->io_region_size, vcdev->io_region_offset);
> > +    if (ret != vcdev->io_region_size) {
> > +        if (errno == EAGAIN) {
> > +            goto again;
> > +        }
> > +        error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);
> > +        return -errno;
> > +    }
> > +
> > +    return region->ret_code;
> > +}
> > +
> >  static void vfio_ccw_reset(DeviceState *dev)
> >  {
> >      CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> > @@ -59,10 +89,52 @@ static void vfio_ccw_reset(DeviceState *dev)
> >  static void vfio_ccw_io_notifier_handler(void *opaque)
> >  {
> >      VFIOCCWDevice *vcdev = opaque;
> > +    struct ccw_io_region *region = vcdev->io_region;
> > +    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
> > +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> > +    SubchDev *sch = ccw_dev->sch;
> > +    SCSW *s = &sch->curr_status.scsw;
> > +    IRB irb;
> >  
> >      if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> >          return;
> >      }
> > +
> > +    if (pread(vcdev->vdev.fd, region,
> > +              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
> is it possible to read less bytes than requested?
Currently, impossible. The kernel side returns either the full region,
or an error.
But we surely could make it more friendly for a partial return. I will
add a check for that case, and generate a channel program check for it.

> 
> Thanks
> 
> Eric
> > +        switch (errno) {
> > +        case ENODEV:
> > +            /* Generate a deferred cc 3 condition. */
> > +            s->flags |= SCSW_FLAGS_MASK_CC;
> > +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> > +            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
> > +            goto read_err;
> > +        case EFAULT:
> > +            /* memory problem, generate channel data check */
> > +            s->ctrl &= ~SCSW_ACTL_START_PEND;
> > +            s->cstat = SCSW_CSTAT_DATA_CHECK;
> > +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> > +            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
> > +                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
> > +            goto read_err;
> > +        default:
> > +            /* error, generate channel program check */
> > +            s->ctrl &= ~SCSW_ACTL_START_PEND;
> > +            s->cstat = SCSW_CSTAT_PROG_CHECK;
> > +            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
> > +            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
> > +                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
> > +            goto read_err;
> > +        }
> > +    }
> > +
> > +    memcpy(&irb, region->irb_area, sizeof(IRB));
> > +
> > +    /* Update control block via irb. */
> > +    copy_scsw_to_guest(s, &irb.scsw);
> > +
> > +read_err:
> > +    css_inject_io_interrupt(sch);
> >  }
> >  
> >  static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
[...]

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough
  2017-05-01 11:08   ` Auger Eric
@ 2017-05-02  2:37     ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  2:37 UTC (permalink / raw)
  To: Auger Eric
  Cc: Dong Jia Shi, kvm, linux-s390, qemu-devel, cornelia.huck,
	borntraeger, alex.williamson, agraf

* Auger Eric <eric.auger@redhat.com> [2017-05-01 13:08:01 +0200]:

Hi Eric,

[...]
> > diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
> > new file mode 100644
> > index 0000000..8b4b9cf
> > --- /dev/null
> > +++ b/hw/s390x/s390-ccw.c
> > @@ -0,0 +1,135 @@
> > +/*
> > + * s390 CCW Assignment Support
> > + *
> > + * Copyright 2017 IBM Corp
> > + * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > + *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
> > + *            Pierre Morel <pmorel@linux.vnet.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 "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "hw/sysbus.h"
> > +#include "libgen.h"
> > +#include "hw/s390x/css.h"
> > +#include "hw/s390x/css-bridge.h"
> > +#include "s390-ccw.h"
> > +
> > +static void s390_ccw_get_dev_info(S390CCWDevice *cdev,
> > +                                  char *sysfsdev,
> > +                                  Error **errp)
> > +{
> > +    unsigned int cssid, ssid, devid;
> > +    char dev_path[PATH_MAX] = {0}, *tmp;
> > +
> > +    if (!sysfsdev) {
> > +        error_setg(errp, "No host device provided");
> > +        error_append_hint(errp,
> > +                          "Use -device vfio-ccw,sysfsdev=PATH_TO_DEVICE\n");
> > +        return;
> > +    }
> > +
> > +    if (!realpath(sysfsdev, dev_path)) {
> > +        error_setg(errp, "Host device '%s' not found", sysfsdev);
> nit: error_setg_errno may be used instead.
Ok.

> > +        return;
> > +    }
> > +
> > +    cdev->mdevid = g_strdup(basename(dev_path));
> > +
> > +    tmp = basename(dirname(dev_path));
> > +    sscanf(tmp, "%2x.%1x.%4x", &cssid, &ssid, &devid);
> I guess this is safe and you don't need to test the operation succeeded?
Yes, it's safe, since the format of the input is an interface that the
kernel provides for the userland program.

> > +
> > +    cdev->hostid.cssid = cssid;
> > +    cdev->hostid.ssid = ssid;
> > +    cdev->hostid.devid = devid;
> > +    cdev->hostid.valid = true;
> > +}
> > +
> > +static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
> > +{
> > +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> > +    CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
> > +    DeviceState *parent = DEVICE(ccw_dev);
> > +    BusState *qbus = qdev_get_parent_bus(parent);
> > +    VirtualCssBus *cbus = VIRTUAL_CSS_BUS(qbus);
> > +    SubchDev *sch;
> > +    int ret;
> > +    Error *err = NULL;
> > +
> > +    s390_ccw_get_dev_info(cdev, sysfsdev, errp);
> > +    if (*errp) {
> I was told in the past dereferencing errp is unclean in general because
> callers may pass null to ignore errors, although the qdev core doesn't.
> you may use local err in that case.
Thanks for the reminding. I'm aware of that. ;>

To make the usage of the Error here more consistent, I will use the
local @err, and propagate to @errp once error happens.

> > +        return;
> > +    }
> > +
> > +    sch = css_create_sch(ccw_dev->devno, false, cbus->squash_mcss, errp);
> > +    if (!sch) {
> > +        return;
> > +    }
> > +    sch->driver_data = cdev;
> > +
> > +    ccw_dev->sch = sch;
> > +    ret = css_sch_build_schib(sch, &cdev->hostid);
> > +    if (ret) {
> > +        error_setg(&err, "%s: Failed to build initial schib: %d",
> > +                   __func__, ret);
> > +        goto out_err;
> > +    }
> > +
> > +    ck->realize(ccw_dev, &err);
> > +    if (err) {
> > +        goto out_err;
> > +    }
> > +
> > +    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
> > +                          parent->hotplugged, 1);
> > +    return;
> > +
> > +out_err:
> > +    error_propagate(errp, err);
> > +    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
> > +    ccw_dev->sch = NULL;
> > +    g_free(sch);
> don't you need to free cdev->mdevid too?
Yes, I should do that. Will fix!

> 
> Thanks
> 
> Eric
> > +}
> > +
[...]

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver
  2017-05-01 11:08   ` Auger Eric
@ 2017-05-02  5:07     ` Dong Jia Shi
  2017-05-02  6:48       ` Auger Eric
  0 siblings, 1 reply; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  5:07 UTC (permalink / raw)
  To: Auger Eric
  Cc: Dong Jia Shi, kvm, linux-s390, qemu-devel, borntraeger,
	alex.williamson, Xiao Feng Ren, cornelia.huck, agraf

* Auger Eric <eric.auger@redhat.com> [2017-05-01 13:08:05 +0200]:

Hi Eric,

[...]

> > diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> > new file mode 100644
> > index 0000000..cd4dfe8
> > --- /dev/null
> > +++ b/hw/vfio/ccw.c
[...]

> > +static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp)
> > +{
> > +    char *tmp, group_path[PATH_MAX];
> > +    ssize_t len;
> > +    int groupid;
> > +
> > +    tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group",
> > +                          cdev->hostid.cssid, cdev->hostid.ssid,
> > +                          cdev->hostid.devid, cdev->mdevid);
> May be worth replacing this static function by a common
> vfio_get_device_group(VFIODevice *vbasedev, Error **errp) in common.c
> that would be used by vfio/pci devices? It would use the sysfsdev
> populated before.
Are you propsing that we introduce a common interface for all of the
devices which use the quite alike logic of populating the sysfsdev?

I put this on my todo list, and prefer to defer it to a time after this
set upstreamed.

> > +    len = readlink(tmp, group_path, sizeof(group_path));
> > +    g_free(tmp);
> > +
> > +    if (len <= 0 || len >= sizeof(group_path)) {
> > +        error_setg(errp, "vfio: no iommu_group found");
> may be good to align the error message with pci/platform. I noticed the
> case where len==0 is handled as ENAMETOOLONG on pci/platform which looks
> bad. Maybe this is why you changed it.
I copy this from pci.c. :>

And I agree with you that, the error message is better to be aligned if
it's possible to do that.

> > +        return NULL;
> > +    }
> > +
> > +    group_path[len] = 0;
> > +
> > +    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
> > +        error_setg(errp, "vfio: failed to read %s", group_path);
> > +        return NULL;
> > +    }
> > +
> > +    return vfio_get_group(groupid, &address_space_memory, errp);
> > +}
> > +
> > +static void vfio_ccw_put_group(VFIOGroup *group)
> Is it really needed?
Ok. Removed.

> > +{
> > +    vfio_put_group(group);
> > +}
> > +
> > +static void vfio_ccw_realize(DeviceState *dev, Error **errp)
> > +{
> > +    VFIODevice *vbasedev;
> > +    VFIOGroup *group;
> > +    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
> > +    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
> > +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
> > +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
> > +
> > +    /* Call the class init function for subchannel. */
> > +    if (cdc->realize) {
> > +        cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
> > +        if (*errp) {
> use local err?
Ok.

> 
> Thanks
> 
> Eric
> > +            return;
> > +        }
> > +    }
> > +
> > +    group = vfio_ccw_get_group(cdev, errp);
> > +    if (!group) {
> > +        goto out_group_err;
> > +    }
> > +
> > +    vcdev->vdev.ops = &vfio_ccw_ops;
> > +    vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW;
> > +    vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid,
> > +                                       cdev->hostid.ssid, cdev->hostid.devid);
> > +    QLIST_FOREACH(vbasedev, &group->device_list, next) {
> > +        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
> > +            error_setg(errp, "vfio: subchannel %s has already been attached",
> > +                       vcdev->vdev.name);
> > +            goto out_device_err;
> > +        }
> > +    }
> > +
> > +    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) {
> > +        goto out_device_err;
> > +    }
> > +
> > +    return;
> > +
> > +out_device_err:
> > +    vfio_ccw_put_group(group);
> > +out_group_err:
> > +    if (cdc->unrealize) {
> > +        cdc->unrealize(cdev, errp);
> > +    }
> > +}
> > +
[...]

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 08/13] vfio/ccw: get io region info
  2017-05-01 11:08   ` Auger Eric
@ 2017-05-02  5:16     ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  5:16 UTC (permalink / raw)
  To: Auger Eric
  Cc: Dong Jia Shi, kvm, linux-s390, qemu-devel, cornelia.huck,
	borntraeger, alex.williamson, agraf

* Auger Eric <eric.auger@redhat.com> [2017-05-01 13:08:24 +0200]:

> Hi,
> 
> On 28/04/2017 15:09, Dong Jia Shi wrote:
> > vfio-ccw provides an MMIO region for I/O operations. We fetch its
> > information via ioctls here, then we can use it performing I/O
> > instructions and retrieving I/O results later on.
> > 
> > Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > ---
> >  hw/vfio/ccw.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 52 insertions(+)
> > 
> > diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> > index cd4dfe8..a285b23 100644
> > --- a/hw/vfio/ccw.c
> > +++ b/hw/vfio/ccw.c
> > @@ -12,6 +12,7 @@
> >   */
> >  
> >  #include <linux/vfio.h>
> > +#include <linux/vfio_ccw.h>
> >  #include <sys/ioctl.h>
> >  
> >  #include "qemu/osdep.h"
> > @@ -26,6 +27,9 @@
> >  typedef struct VFIOCCWDevice {
> >      S390CCWDevice cdev;
> >      VFIODevice vdev;
> > +    uint64_t io_region_size;
> > +    uint64_t io_region_offset;
> > +    struct ccw_io_region *io_region;
> >  } VFIOCCWDevice;
> >  
> >  static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
> > @@ -50,6 +54,46 @@ static void vfio_ccw_reset(DeviceState *dev)
> >      ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
> >  }
> >  
> > +static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
> > +{
> > +    VFIODevice *vdev = &vcdev->vdev;
> > +    struct vfio_region_info *info;
> > +    int ret;
> > +
> > +    /* Sanity check device */
> > +    if (!(vdev->flags & VFIO_DEVICE_FLAGS_CCW)) {
> > +        error_setg(errp, "vfio: Um, this isn't a vfio-ccw device");
> > +        return;
> > +    }
> > +
> > +    if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
> > +        error_setg(errp, "vfio: Unexpected number of the I/O region %u",
> > +                   vdev->num_regions);
> > +        return;
> > +    }
> > +
> > +    ret = vfio_get_region_info(vdev, VFIO_CCW_CONFIG_REGION_INDEX, &info);
> > +    if (ret) {
> > +        error_setg(errp, "vfio: Error getting config info: %d", ret);
> > +        return;
> > +    }
> > +
> > +    vcdev->io_region_size = info->size;
> > +    if (sizeof(*vcdev->io_region) != vcdev->io_region_size) {
> > +        error_setg(errp, "vfio: Unexpected size of the I/O region");
> g_free(info)
Good catch!

> > +        return;
> > +    }
> > +    vcdev->io_region_offset = info->offset;
> > +    vcdev->io_region = g_malloc0(info->size);
> > +
> > +    g_free(info);
> > +}
> > +
> > +static void vfio_ccw_put_region(VFIOCCWDevice *vcdev)
> > +{
> > +    g_free(vcdev->io_region);
> > +}
> > +
> >  static void vfio_put_device(VFIOCCWDevice *vcdev)
> >  {
> >      g_free(vcdev->vdev.name);
> > @@ -126,8 +170,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
> >          goto out_device_err;
> >      }
> >  
> > +    vfio_ccw_get_region(vcdev, errp);
> > +    if (*errp) {
> local err?
As replied on the previous thread, ok.

> 
> Thanks
> 
> Eric
> > +        goto out_region_err;
> > +    }
> > +
> >      return;
> >  
> > +out_region_err:
> > +    vfio_put_device(vcdev);
> >  out_device_err:
> >      vfio_ccw_put_group(group);
> >  out_group_err:
> > @@ -144,6 +195,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
> >      S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
> >      VFIOGroup *group = vcdev->vdev.group;
> >  
> > +    vfio_ccw_put_region(vcdev);
> >      vfio_put_device(vcdev);
> >      vfio_put_group(group);
> >  
> > 
> 

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd
  2017-05-01 11:08   ` Auger Eric
@ 2017-05-02  5:37     ` Dong Jia Shi
  2017-05-02  6:49       ` Dong Jia Shi
  0 siblings, 1 reply; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  5:37 UTC (permalink / raw)
  To: Auger Eric
  Cc: Dong Jia Shi, kvm, linux-s390, qemu-devel, cornelia.huck,
	borntraeger, alex.williamson, agraf

* Auger Eric <eric.auger@redhat.com> [2017-05-01 13:08:45 +0200]:

Hi Eric,

> Hi,
> On 28/04/2017 15:09, Dong Jia Shi wrote:
> > vfio-ccw resorts to the eventfd mechanism to communicate with userspace.
> > We fetch the irqs info via the ioctl VFIO_DEVICE_GET_IRQ_INFO,
> > register a event notifier to get the eventfd fd which is sent
> > to kernel via the ioctl VFIO_DEVICE_SET_IRQS, then we can implement
> > read operation once kernel sends the signal.
> > 
> > Signed-off-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
> > ---
> >  hw/vfio/ccw.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 102 insertions(+)
> > 
> > diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
> > index a285b23..cda3057 100644
> > --- a/hw/vfio/ccw.c
> > +++ b/hw/vfio/ccw.c
> > @@ -22,6 +22,7 @@
> >  #include "hw/vfio/vfio-common.h"
> >  #include "hw/s390x/s390-ccw.h"
> >  #include "hw/s390x/ccw-device.h"
> > +#include "qemu/error-report.h"
> >  
> >  #define TYPE_VFIO_CCW "vfio-ccw"
> >  typedef struct VFIOCCWDevice {
> > @@ -30,6 +31,7 @@ typedef struct VFIOCCWDevice {
> >      uint64_t io_region_size;
> >      uint64_t io_region_offset;
> >      struct ccw_io_region *io_region;
> > +    EventNotifier io_notifier;
> >  } VFIOCCWDevice;
> >  
> >  static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
> > @@ -54,6 +56,98 @@ static void vfio_ccw_reset(DeviceState *dev)
> >      ioctl(vcdev->vdev.fd, VFIO_DEVICE_RESET);
> >  }
> >  
> > +static void vfio_ccw_io_notifier_handler(void *opaque)
> > +{
> > +    VFIOCCWDevice *vcdev = opaque;
> > +
> > +    if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> > +        return;
> > +    }
> > +}
> > +
> > +static void vfio_ccw_register_io_notifier(VFIOCCWDevice *vcdev, Error **errp)
> > +{
> > +    VFIODevice *vdev = &vcdev->vdev;
> > +    struct vfio_irq_info *irq_info;
> > +    struct vfio_irq_set *irq_set;
> > +    size_t argsz;
> > +    int32_t *pfd;
> > +
> > +    if (vdev->num_irqs < VFIO_CCW_IO_IRQ_INDEX + 1) {
> > +        error_setg(errp, "vfio: unexpected number of io irqs %u",
> > +                   vdev->num_irqs);
> > +        return;
> > +    }
> > +
> > +    argsz = sizeof(*irq_set);
> > +    irq_info = g_malloc0(argsz);
> > +    irq_info->index = VFIO_CCW_IO_IRQ_INDEX;
> > +    irq_info->argsz = argsz;
> > +    if (ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO,
> > +              irq_info) < 0 || irq_info->count < 1) {
> > +        error_setg(errp, "vfio: Error getting irq info");
> nit: error_setg_errno?
Ok.

> > +        goto get_error;
> > +    }
> > +
> > +    if (event_notifier_init(&vcdev->io_notifier, 0)) {
> > +        error_setg(errp, "vfio: Unable to init event notifier for IO");
> nit: same
Ok.

> > +        goto get_error;
> > +    }
> > +
> > +    argsz = sizeof(*irq_set) + sizeof(*pfd);
> > +    irq_set = g_malloc0(argsz);
> > +    irq_set->argsz = argsz;
> > +    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
> > +                     VFIO_IRQ_SET_ACTION_TRIGGER;
> > +    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
> > +    irq_set->start = 0;
> > +    irq_set->count = 1;
> > +    pfd = (int32_t *) &irq_set->data;
> > +
> > +    *pfd = event_notifier_get_fd(&vcdev->io_notifier);
> > +    qemu_set_fd_handler(*pfd, vfio_ccw_io_notifier_handler, NULL, vcdev);
> > +    if (ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
> > +        error_setg(errp, "vfio: Failed to set up io notification");
> > +        qemu_set_fd_handler(*pfd, NULL, NULL, vcdev);
> > +        event_notifier_cleanup(&vcdev->io_notifier);
> > +        goto set_error;
> > +    }
> > +
> > +set_error:
> > +    g_free(irq_set);
> > +
> > +get_error:
> > +    g_free(irq_info);
> > +}
> > +
> > +static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
> > +{
> > +    struct vfio_irq_set *irq_set;
> > +    size_t argsz;
> > +    int32_t *pfd;
> > +
> > +    argsz = sizeof(*irq_set) + sizeof(*pfd);
> > +    irq_set = g_malloc0(argsz);
> > +    irq_set->argsz = argsz;
> > +    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
> > +                     VFIO_IRQ_SET_ACTION_TRIGGER;
> > +    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
> > +    irq_set->start = 0;
> > +    irq_set->count = 1;
> > +    pfd = (int32_t *) &irq_set->data;
> > +    *pfd = -1;
> > +
> > +    if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
> > +        error_report("vfio: Failed to de-assign device io fd");
> ditto

error_report("vfio: Failed to de-assign device io fd: %s",
             strerror(drrno));

> > +    }
> > +
> > +    qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier),
> > +                        NULL, NULL, vcdev);
> > +    event_notifier_cleanup(&vcdev->io_notifier);
> > +
> > +    g_free(irq_set);
> > +}
> > +
> >  static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
> >  {
> >      VFIODevice *vdev = &vcdev->vdev;
> > @@ -175,8 +269,15 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
> >          goto out_region_err;
> >      }
> >  
> > +    vfio_ccw_register_io_notifier(vcdev, errp);
> > +    if (*errp) {
> ditto
Ok.

> 
> Thanks
> 
> Eric
> > +        goto out_notifier_err;
> > +    }
> > +
> >      return;
> >  
> > +out_notifier_err:
> > +    vfio_ccw_put_region(vcdev);
> >  out_region_err:
> >      vfio_put_device(vcdev);
> >  out_device_err:
> > @@ -195,6 +296,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)
> >      S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
> >      VFIOGroup *group = vcdev->vdev.group;
> >  
> > +    vfio_ccw_unregister_io_notifier(vcdev);
> >      vfio_ccw_put_region(vcdev);
> >      vfio_put_device(vcdev);
> >      vfio_put_group(group);
> > 
> 

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver
  2017-05-02  5:07     ` Dong Jia Shi
@ 2017-05-02  6:48       ` Auger Eric
  0 siblings, 0 replies; 45+ messages in thread
From: Auger Eric @ 2017-05-02  6:48 UTC (permalink / raw)
  To: Dong Jia Shi, kvm, linux-s390, qemu-devel, borntraeger,
	alex.williamson, Xiao Feng Ren, cornelia.huck, agraf

Hi Dong,

On 02/05/2017 07:07, Dong Jia Shi wrote:
> * Auger Eric <eric.auger@redhat.com> [2017-05-01 13:08:05 +0200]:
> 
> Hi Eric,
> 
> [...]
> 
>>> diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
>>> new file mode 100644
>>> index 0000000..cd4dfe8
>>> --- /dev/null
>>> +++ b/hw/vfio/ccw.c
> [...]
> 
>>> +static VFIOGroup *vfio_ccw_get_group(S390CCWDevice *cdev, Error **errp)
>>> +{
>>> +    char *tmp, group_path[PATH_MAX];
>>> +    ssize_t len;
>>> +    int groupid;
>>> +
>>> +    tmp = g_strdup_printf("/sys/bus/css/devices/%x.%x.%04x/%s/iommu_group",
>>> +                          cdev->hostid.cssid, cdev->hostid.ssid,
>>> +                          cdev->hostid.devid, cdev->mdevid);
>> May be worth replacing this static function by a common
>> vfio_get_device_group(VFIODevice *vbasedev, Error **errp) in common.c
>> that would be used by vfio/pci devices? It would use the sysfsdev
>> populated before.
> Are you propsing that we introduce a common interface for all of the
> devices which use the quite alike logic of populating the sysfsdev?
Yes that's what I meant.
> 
> I put this on my todo list, and prefer to defer it to a time after this
> set upstreamed.
OK no worries.
> 
>>> +    len = readlink(tmp, group_path, sizeof(group_path));
>>> +    g_free(tmp);
>>> +
>>> +    if (len <= 0 || len >= sizeof(group_path)) {
>>> +        error_setg(errp, "vfio: no iommu_group found");
>> may be good to align the error message with pci/platform. I noticed the
>> case where len==0 is handled as ENAMETOOLONG on pci/platform which looks
>> bad. Maybe this is why you changed it.
> I copy this from pci.c. :>
yep I know ;-)

Thanks

Eric
> 
> And I agree with you that, the error message is better to be aligned if
> it's possible to do that.
> 
>>> +        return NULL;
>>> +    }
>>> +
>>> +    group_path[len] = 0;
>>> +
>>> +    if (sscanf(basename(group_path), "%d", &groupid) != 1) {
>>> +        error_setg(errp, "vfio: failed to read %s", group_path);
>>> +        return NULL;
>>> +    }
>>> +
>>> +    return vfio_get_group(groupid, &address_space_memory, errp);
>>> +}
>>> +
>>> +static void vfio_ccw_put_group(VFIOGroup *group)
>> Is it really needed?
> Ok. Removed.
> 
>>> +{
>>> +    vfio_put_group(group);
>>> +}
>>> +
>>> +static void vfio_ccw_realize(DeviceState *dev, Error **errp)
>>> +{
>>> +    VFIODevice *vbasedev;
>>> +    VFIOGroup *group;
>>> +    CcwDevice *ccw_dev = DO_UPCAST(CcwDevice, parent_obj, dev);
>>> +    S390CCWDevice *cdev = DO_UPCAST(S390CCWDevice, parent_obj, ccw_dev);
>>> +    VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
>>> +    S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev);
>>> +
>>> +    /* Call the class init function for subchannel. */
>>> +    if (cdc->realize) {
>>> +        cdc->realize(cdev, vcdev->vdev.sysfsdev, errp);
>>> +        if (*errp) {
>> use local err?
> Ok.
> 
>>
>> Thanks
>>
>> Eric
>>> +            return;
>>> +        }
>>> +    }
>>> +
>>> +    group = vfio_ccw_get_group(cdev, errp);
>>> +    if (!group) {
>>> +        goto out_group_err;
>>> +    }
>>> +
>>> +    vcdev->vdev.ops = &vfio_ccw_ops;
>>> +    vcdev->vdev.type = VFIO_DEVICE_TYPE_CCW;
>>> +    vcdev->vdev.name = g_strdup_printf("%x.%x.%04x", cdev->hostid.cssid,
>>> +                                       cdev->hostid.ssid, cdev->hostid.devid);
>>> +    QLIST_FOREACH(vbasedev, &group->device_list, next) {
>>> +        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
>>> +            error_setg(errp, "vfio: subchannel %s has already been attached",
>>> +                       vcdev->vdev.name);
>>> +            goto out_device_err;
>>> +        }
>>> +    }
>>> +
>>> +    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, errp)) {
>>> +        goto out_device_err;
>>> +    }
>>> +
>>> +    return;
>>> +
>>> +out_device_err:
>>> +    vfio_ccw_put_group(group);
>>> +out_group_err:
>>> +    if (cdc->unrealize) {
>>> +        cdc->unrealize(cdev, errp);
>>> +    }
>>> +}
>>> +
> [...]
> 

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd
  2017-05-02  5:37     ` Dong Jia Shi
@ 2017-05-02  6:49       ` Dong Jia Shi
  0 siblings, 0 replies; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-02  6:49 UTC (permalink / raw)
  To: Auger Eric, Dong Jia Shi, kvm, linux-s390, qemu-devel,
	cornelia.huck, borntraeger, alex.williamson, agraf

* Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> [2017-05-02 13:37:38 +0800]:

[...]
> > > +static void vfio_ccw_unregister_io_notifier(VFIOCCWDevice *vcdev)
> > > +{
> > > +    struct vfio_irq_set *irq_set;
> > > +    size_t argsz;
> > > +    int32_t *pfd;
> > > +
> > > +    argsz = sizeof(*irq_set) + sizeof(*pfd);
> > > +    irq_set = g_malloc0(argsz);
> > > +    irq_set->argsz = argsz;
> > > +    irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |
> > > +                     VFIO_IRQ_SET_ACTION_TRIGGER;
> > > +    irq_set->index = VFIO_CCW_IO_IRQ_INDEX;
> > > +    irq_set->start = 0;
> > > +    irq_set->count = 1;
> > > +    pfd = (int32_t *) &irq_set->data;
> > > +    *pfd = -1;
> > > +
> > > +    if (ioctl(vcdev->vdev.fd, VFIO_DEVICE_SET_IRQS, irq_set)) {
> > > +        error_report("vfio: Failed to de-assign device io fd");
> > ditto
> 
> error_report("vfio: Failed to de-assign device io fd: %s",
>              strerror(drrno));
> 
Or:
error_report("vfio: Failed to de-assign device io fd: %m");

> > > +    }
> > > +
> > > +    qemu_set_fd_handler(event_notifier_get_fd(&vcdev->io_notifier),
> > > +                        NULL, NULL, vcdev);
> > > +    event_notifier_cleanup(&vcdev->io_notifier);
> > > +
> > > +    g_free(irq_set);
> > > +}
> > > +
> > >  static void vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
> > >  {
> > >      VFIODevice *vdev = &vcdev->vdev;
[...]

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-05-02  2:15     ` Dong Jia Shi
@ 2017-05-02 16:04       ` Cornelia Huck
  2017-05-03  2:18         ` Dong Jia Shi
  0 siblings, 1 reply; 45+ messages in thread
From: Cornelia Huck @ 2017-05-02 16:04 UTC (permalink / raw)
  To: Dong Jia Shi
  Cc: Auger Eric, kvm, linux-s390, qemu-devel, borntraeger,
	alex.williamson, Xiao Feng Ren, agraf

On Tue, 2 May 2017 10:15:19 +0800
Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> wrote:

> * Auger Eric <eric.auger@redhat.com> [2017-05-01 19:28:23 +0200]:

> > >  static void vfio_ccw_io_notifier_handler(void *opaque)
> > >  {
> > >      VFIOCCWDevice *vcdev = opaque;
> > > +    struct ccw_io_region *region = vcdev->io_region;
> > > +    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
> > > +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> > > +    SubchDev *sch = ccw_dev->sch;
> > > +    SCSW *s = &sch->curr_status.scsw;
> > > +    IRB irb;
> > >  
> > >      if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> > >          return;
> > >      }
> > > +
> > > +    if (pread(vcdev->vdev.fd, region,
> > > +              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
> > is it possible to read less bytes than requested?
> Currently, impossible. The kernel side returns either the full region,
> or an error.
> But we surely could make it more friendly for a partial return. I will
> add a check for that case, and generate a channel program check for it.

I think a channel-control check would be more appropriate here.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-05-02 16:04       ` Cornelia Huck
@ 2017-05-03  2:18         ` Dong Jia Shi
  2017-05-03 11:14           ` Cornelia Huck
  0 siblings, 1 reply; 45+ messages in thread
From: Dong Jia Shi @ 2017-05-03  2:18 UTC (permalink / raw)
  To: Cornelia Huck
  Cc: Dong Jia Shi, linux-s390, kvm, borntraeger, qemu-devel,
	Auger Eric, alex.williamson, Xiao Feng Ren, agraf

* Cornelia Huck <cornelia.huck@de.ibm.com> [2017-05-02 18:04:07 +0200]:

> On Tue, 2 May 2017 10:15:19 +0800
> Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> wrote:
> 
> > * Auger Eric <eric.auger@redhat.com> [2017-05-01 19:28:23 +0200]:
> 
> > > >  static void vfio_ccw_io_notifier_handler(void *opaque)
> > > >  {
> > > >      VFIOCCWDevice *vcdev = opaque;
> > > > +    struct ccw_io_region *region = vcdev->io_region;
> > > > +    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
> > > > +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> > > > +    SubchDev *sch = ccw_dev->sch;
> > > > +    SCSW *s = &sch->curr_status.scsw;
> > > > +    IRB irb;
> > > >  
> > > >      if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> > > >          return;
> > > >      }
> > > > +
> > > > +    if (pread(vcdev->vdev.fd, region,
> > > > +              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
> > > is it possible to read less bytes than requested?
> > Currently, impossible. The kernel side returns either the full region,
> > or an error.
> > But we surely could make it more friendly for a partial return. I will
> > add a check for that case, and generate a channel program check for it.
> 
> I think a channel-control check would be more appropriate here.

Hi Conny,

After reading PoP 14-43, I think you are right.

Quotation from PoP:
------------------8<-----------------------------------
Channel-control check is caused by any machine
malfunction affecting channel-subsystem controls.
... ...

Channel-control check may also indicate that an
error has been detected in the information trans-
ferred to or from main storage during an I/O opera-
tion.
... ...

Detection of the channel-control-check condition
causes the current operation, if any, to be terminated
immediately. The subchannel is made status pending
with primary and alert status or with primary, second-
ary, and alert status as a function of the type of termi-
nation, the current subchannel state, and the device
status presented, if any. When the channel sub-
system recognizes a channel-control-check condi-
tion, any previously existing intermediate interruption
condition may or may not be recognized by the chan-
nel subsystem.
------------------>8-----------------------------------

So I decide to add this piece of code:
if (size != vcdev->io_region_size) {
    /* Information transfer error, generate channel-control check. */
    s->ctrl &= ~SCSW_ACTL_START_PEND;
    s->cstat = SCSW_CSTAT_CHN_CTRL_CHK;
    s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
    s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
               SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
    goto read_err;
}

-- 
Dong Jia Shi

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [Qemu-devel] [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback
  2017-05-03  2:18         ` Dong Jia Shi
@ 2017-05-03 11:14           ` Cornelia Huck
  0 siblings, 0 replies; 45+ messages in thread
From: Cornelia Huck @ 2017-05-03 11:14 UTC (permalink / raw)
  To: Dong Jia Shi
  Cc: linux-s390, kvm, borntraeger, qemu-devel, Auger Eric,
	alex.williamson, Xiao Feng Ren, agraf

On Wed, 3 May 2017 10:18:50 +0800
Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> wrote:

> * Cornelia Huck <cornelia.huck@de.ibm.com> [2017-05-02 18:04:07 +0200]:
> 
> > On Tue, 2 May 2017 10:15:19 +0800
> > Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> wrote:
> > 
> > > * Auger Eric <eric.auger@redhat.com> [2017-05-01 19:28:23 +0200]:
> > 
> > > > >  static void vfio_ccw_io_notifier_handler(void *opaque)
> > > > >  {
> > > > >      VFIOCCWDevice *vcdev = opaque;
> > > > > +    struct ccw_io_region *region = vcdev->io_region;
> > > > > +    S390CCWDevice *cdev = S390_CCW_DEVICE(vcdev);
> > > > > +    CcwDevice *ccw_dev = CCW_DEVICE(cdev);
> > > > > +    SubchDev *sch = ccw_dev->sch;
> > > > > +    SCSW *s = &sch->curr_status.scsw;
> > > > > +    IRB irb;
> > > > >  
> > > > >      if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
> > > > >          return;
> > > > >      }
> > > > > +
> > > > > +    if (pread(vcdev->vdev.fd, region,
> > > > > +              vcdev->io_region_size, vcdev->io_region_offset) == -1) {
> > > > is it possible to read less bytes than requested?
> > > Currently, impossible. The kernel side returns either the full region,
> > > or an error.
> > > But we surely could make it more friendly for a partial return. I will
> > > add a check for that case, and generate a channel program check for it.
> > 
> > I think a channel-control check would be more appropriate here.
> 
> Hi Conny,
> 
> After reading PoP 14-43, I think you are right.

(...)

> So I decide to add this piece of code:
> if (size != vcdev->io_region_size) {
>     /* Information transfer error, generate channel-control check. */
>     s->ctrl &= ~SCSW_ACTL_START_PEND;
>     s->cstat = SCSW_CSTAT_CHN_CTRL_CHK;
>     s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
>     s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
>                SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
>     goto read_err;
> }

Looks good.

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2017-05-03 11:14 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-28 13:09 [PATCH v6 00/13] basic channel IO passthrough infrastructure based on vfio Dong Jia Shi
2017-04-28 13:09 ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 01/13] update-linux-headers: update for vfio-ccw Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 02/13] vfio: linux-headers " Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 03/13] s390x/css: add s390-squash-mcss machine option Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 04/13] s390x/css: realize css_sch_build_schib Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 05/13] s390x/css: realize css_create_sch Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 06/13] s390x/css: device support for s390-ccw passthrough Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-05-01 11:08   ` Auger Eric
2017-05-02  2:37     ` Dong Jia Shi
2017-05-01 11:20   ` Auger Eric
2017-05-01 11:24     ` Auger Eric
2017-04-28 13:09 ` [PATCH v6 07/13] vfio/ccw: vfio based subchannel passthrough driver Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-05-01 11:08   ` Auger Eric
2017-05-02  5:07     ` Dong Jia Shi
2017-05-02  6:48       ` Auger Eric
2017-04-28 13:09 ` [PATCH v6 08/13] vfio/ccw: get io region info Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-05-01 11:08   ` Auger Eric
2017-05-02  5:16     ` Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 09/13] vfio/ccw: get irqs info and set the eventfd fd Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-05-01 11:08   ` Auger Eric
2017-05-02  5:37     ` Dong Jia Shi
2017-05-02  6:49       ` Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 10/13] s390x/css: introduce and realize ccw-request callback Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-05-01 17:28   ` Auger Eric
2017-05-02  2:15     ` Dong Jia Shi
2017-05-02 16:04       ` Cornelia Huck
2017-05-03  2:18         ` Dong Jia Shi
2017-05-03 11:14           ` Cornelia Huck
2017-04-28 13:09 ` [PATCH v6 11/13] s390x/css: ccw translation infrastructure Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 12/13] vfio/ccw: update sense data if a unit check is pending Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi
2017-04-28 13:09 ` [PATCH v6 13/13] MAINTAINERS: Add vfio-ccw maintainer Dong Jia Shi
2017-04-28 13:09   ` [Qemu-devel] " Dong Jia Shi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.