* [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data Cornelia Huck
` (19 subsequent siblings)
20 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, Cornelia Huck, qemu-devel
The following changes since commit 3284aa128153750f14a61e8a96fd085e6f2999b6:
Merge remote-tracking branch 'remotes/lersek/tags/edk2-pull-2019-04-22' into staging (2019-04-24 13:19:41 +0100)
are available in the Git repository at:
https://github.com/cohuck/qemu tags/s390x-20190425
for you to fetch changes up to 41c3d4269b1c18d12d33c5bf089dace25d08e82e:
Merge tag 's390-ccw-bios-2019-04-12' into s390-next-staging (2019-04-25 14:09:20 +0200)
----------------------------------------------------------------
- properly detect page size of initial memory
- support for IPL (boot) from ECKD DASD passed through via vfio-ccw
----------------------------------------------------------------
Cornelia Huck (1):
Merge tag 's390-ccw-bios-2019-04-12' into s390-next-staging
David Hildenbrand (2):
s390x/kvm: Configure page size after memory has actually been
initialized
exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize()
Jason J. Herne (16):
s390 vfio-ccw: Add bootindex property and IPLB data
s390-bios: decouple cio setup from virtio
s390-bios: decouple common boot logic from virtio
s390-bios: Clean up cio.h
s390-bios: Decouple channel i/o logic from virtio
s390-bios: Map low core memory
s390-bios: ptr2u32 and u32toptr
s390-bios: Support for running format-0/1 channel programs
s390-bios: cio error handling
s390-bios: Extend find_dev() for non-virtio devices
s390-bios: Factor finding boot device out of virtio code path
s390-bios: Refactor virtio to run channel programs via cio
s390-bios: Use control unit type to determine boot method
s390-bios: Add channel command codes/structs needed for dasd-ipl
s390-bios: Support booting from real dasd device
s390-bios: Use control unit type to find bootable devices
Thomas Huth (1):
pc-bios/s390: Update firmware images
--
2.17.2
^ permalink raw reply [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-30 16:54 ` Peter Maydell
2019-04-25 13:21 ` [Qemu-devel] [PULL 02/19] s390-bios: decouple cio setup from virtio Cornelia Huck
` (18 subsequent siblings)
20 siblings, 2 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add bootindex property and iplb data for vfio-ccw devices. This allows us to
forward boot information into the bios for vfio-ccw devices.
Refactor s390_get_ccw_device() to return device type. This prevents us from
having to use messy casting logic in several places.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-2-git-send-email-jjherne@linux.ibm.com>
[thuth: fixed "typedef struct VFIOCCWDevice" build failure with clang]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 1 +
hw/s390x/ipl.c | 61 ++++++++++++++++++++++++++++---------
hw/s390x/s390-ccw.c | 9 ++++++
hw/vfio/ccw.c | 6 ++--
include/hw/s390x/s390-ccw.h | 1 +
include/hw/s390x/vfio-ccw.h | 28 +++++++++++++++++
6 files changed, 88 insertions(+), 18 deletions(-)
create mode 100644 include/hw/s390x/vfio-ccw.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 56139ac8ab05..f7976aa43d0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1445,6 +1445,7 @@ S: Supported
F: hw/vfio/ccw.c
F: hw/s390x/s390-ccw.c
F: include/hw/s390x/s390-ccw.h
+F: include/hw/s390x/vfio-ccw.h
T: git https://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 51b272e190a9..d0cc06a05fd0 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -19,6 +19,7 @@
#include "hw/loader.h"
#include "hw/boards.h"
#include "hw/s390x/virtio-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "ipl.h"
@@ -303,16 +304,36 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time);
}
-static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
+#define CCW_DEVTYPE_NONE 0x00
+#define CCW_DEVTYPE_VIRTIO 0x01
+#define CCW_DEVTYPE_VIRTIO_NET 0x02
+#define CCW_DEVTYPE_SCSI 0x03
+#define CCW_DEVTYPE_VFIO 0x04
+
+static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
{
CcwDevice *ccw_dev = NULL;
+ int tmp_dt = CCW_DEVTYPE_NONE;
if (dev_st) {
+ VirtIONet *virtio_net_dev = (VirtIONet *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VIRTIO_NET);
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
TYPE_VIRTIO_CCW_DEVICE);
+ VFIOCCWDevice *vfio_ccw_dev = (VFIOCCWDevice *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VFIO_CCW);
+
if (virtio_ccw_dev) {
ccw_dev = CCW_DEVICE(virtio_ccw_dev);
+ if (virtio_net_dev) {
+ tmp_dt = CCW_DEVTYPE_VIRTIO_NET;
+ } else {
+ tmp_dt = CCW_DEVTYPE_VIRTIO;
+ }
+ } else if (vfio_ccw_dev) {
+ ccw_dev = CCW_DEVICE(vfio_ccw_dev);
+ tmp_dt = CCW_DEVTYPE_VFIO;
} else {
SCSIDevice *sd = (SCSIDevice *)
object_dynamic_cast(OBJECT(dev_st),
@@ -325,9 +346,13 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
TYPE_CCW_DEVICE);
+ tmp_dt = CCW_DEVTYPE_SCSI;
}
}
}
+ if (devtype) {
+ *devtype = tmp_dt;
+ }
return ccw_dev;
}
@@ -335,20 +360,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
DeviceState *dev_st;
CcwDevice *ccw_dev = NULL;
+ SCSIDevice *sd;
+ int devtype;
dev_st = get_boot_device(0);
if (dev_st) {
- ccw_dev = s390_get_ccw_device(dev_st);
+ ccw_dev = s390_get_ccw_device(dev_st, &devtype);
}
/*
* Currently allow IPL only from CCW devices.
*/
if (ccw_dev) {
- SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_SCSI_DEVICE);
-
- if (sd) {
+ switch (devtype) {
+ case CCW_DEVTYPE_SCSI:
+ sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
+ TYPE_SCSI_DEVICE);
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
@@ -358,20 +385,24 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
- } else {
- VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_VIRTIO_NET);
-
+ break;
+ case CCW_DEVTYPE_VFIO:
+ ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
+ ipl->iplb.pbt = S390_IPL_TYPE_CCW;
+ ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
+ ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
+ break;
+ case CCW_DEVTYPE_VIRTIO_NET:
+ ipl->netboot = true;
+ /* Fall through to CCW_DEVTYPE_VIRTIO case */
+ case CCW_DEVTYPE_VIRTIO:
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
-
- if (vn) {
- ipl->netboot = true;
- }
+ break;
}
if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
@@ -530,7 +561,7 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type)
!ipl->netboot &&
ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
is_virtio_scsi_device(&ipl->iplb)) {
- CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0));
+ CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0), NULL);
if (ccw_dev &&
cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index cad91ee62679..f5f025d1b6ca 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -124,6 +124,14 @@ static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
g_free(cdev->mdevid);
}
+static void s390_ccw_instance_init(Object *obj)
+{
+ S390CCWDevice *dev = S390_CCW_DEVICE(obj);
+
+ device_add_bootindex_property(obj, &dev->bootindex, "bootindex",
+ "/disk@0,0", DEVICE(obj), NULL);
+}
+
static void s390_ccw_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -137,6 +145,7 @@ static void s390_ccw_class_init(ObjectClass *klass, void *data)
static const TypeInfo s390_ccw_info = {
.name = TYPE_S390_CCW,
.parent = TYPE_CCW_DEVICE,
+ .instance_init = s390_ccw_instance_init,
.instance_size = sizeof(S390CCWDevice),
.class_size = sizeof(S390CCWDeviceClass),
.class_init = s390_ccw_class_init,
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index c44d13cc5081..31dd3a2a87b6 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -21,12 +21,12 @@
#include "hw/vfio/vfio.h"
#include "hw/vfio/vfio-common.h"
#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/ccw-device.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
-#define TYPE_VFIO_CCW "vfio-ccw"
-typedef struct VFIOCCWDevice {
+struct VFIOCCWDevice {
S390CCWDevice cdev;
VFIODevice vdev;
uint64_t io_region_size;
@@ -35,7 +35,7 @@ typedef struct VFIOCCWDevice {
EventNotifier io_notifier;
bool force_orb_pfch;
bool warned_orb_pfch;
-} VFIOCCWDevice;
+};
static inline void warn_once_pfch(VFIOCCWDevice *vcdev, SubchDev *sch,
const char *msg)
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index 7d15a1a5d41d..901d805d79a3 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
CcwDevice parent_obj;
CssDevId hostid;
char *mdevid;
+ int32_t bootindex;
} S390CCWDevice;
typedef struct S390CCWDeviceClass {
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
new file mode 100644
index 000000000000..ee5250d0d788
--- /dev/null
+++ b/include/hw/s390x/vfio-ccw.h
@@ -0,0 +1,28 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017, 2019 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.
+ */
+
+#ifndef HW_VFIO_CCW_H
+#define HW_VFIO_CCW_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"
+#define VFIO_CCW(obj) \
+ OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW)
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+typedef struct VFIOCCWDevice VFIOCCWDevice;
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-25 13:21 ` [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-30 16:54 ` Peter Maydell
1 sibling, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add bootindex property and iplb data for vfio-ccw devices. This allows us to
forward boot information into the bios for vfio-ccw devices.
Refactor s390_get_ccw_device() to return device type. This prevents us from
having to use messy casting logic in several places.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-2-git-send-email-jjherne@linux.ibm.com>
[thuth: fixed "typedef struct VFIOCCWDevice" build failure with clang]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 1 +
hw/s390x/ipl.c | 61 ++++++++++++++++++++++++++++---------
hw/s390x/s390-ccw.c | 9 ++++++
hw/vfio/ccw.c | 6 ++--
include/hw/s390x/s390-ccw.h | 1 +
include/hw/s390x/vfio-ccw.h | 28 +++++++++++++++++
6 files changed, 88 insertions(+), 18 deletions(-)
create mode 100644 include/hw/s390x/vfio-ccw.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 56139ac8ab05..f7976aa43d0a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1445,6 +1445,7 @@ S: Supported
F: hw/vfio/ccw.c
F: hw/s390x/s390-ccw.c
F: include/hw/s390x/s390-ccw.h
+F: include/hw/s390x/vfio-ccw.h
T: git https://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 51b272e190a9..d0cc06a05fd0 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -19,6 +19,7 @@
#include "hw/loader.h"
#include "hw/boards.h"
#include "hw/s390x/virtio-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "ipl.h"
@@ -303,16 +304,36 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time);
}
-static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
+#define CCW_DEVTYPE_NONE 0x00
+#define CCW_DEVTYPE_VIRTIO 0x01
+#define CCW_DEVTYPE_VIRTIO_NET 0x02
+#define CCW_DEVTYPE_SCSI 0x03
+#define CCW_DEVTYPE_VFIO 0x04
+
+static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
{
CcwDevice *ccw_dev = NULL;
+ int tmp_dt = CCW_DEVTYPE_NONE;
if (dev_st) {
+ VirtIONet *virtio_net_dev = (VirtIONet *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VIRTIO_NET);
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
TYPE_VIRTIO_CCW_DEVICE);
+ VFIOCCWDevice *vfio_ccw_dev = (VFIOCCWDevice *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VFIO_CCW);
+
if (virtio_ccw_dev) {
ccw_dev = CCW_DEVICE(virtio_ccw_dev);
+ if (virtio_net_dev) {
+ tmp_dt = CCW_DEVTYPE_VIRTIO_NET;
+ } else {
+ tmp_dt = CCW_DEVTYPE_VIRTIO;
+ }
+ } else if (vfio_ccw_dev) {
+ ccw_dev = CCW_DEVICE(vfio_ccw_dev);
+ tmp_dt = CCW_DEVTYPE_VFIO;
} else {
SCSIDevice *sd = (SCSIDevice *)
object_dynamic_cast(OBJECT(dev_st),
@@ -325,9 +346,13 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
TYPE_CCW_DEVICE);
+ tmp_dt = CCW_DEVTYPE_SCSI;
}
}
}
+ if (devtype) {
+ *devtype = tmp_dt;
+ }
return ccw_dev;
}
@@ -335,20 +360,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
DeviceState *dev_st;
CcwDevice *ccw_dev = NULL;
+ SCSIDevice *sd;
+ int devtype;
dev_st = get_boot_device(0);
if (dev_st) {
- ccw_dev = s390_get_ccw_device(dev_st);
+ ccw_dev = s390_get_ccw_device(dev_st, &devtype);
}
/*
* Currently allow IPL only from CCW devices.
*/
if (ccw_dev) {
- SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_SCSI_DEVICE);
-
- if (sd) {
+ switch (devtype) {
+ case CCW_DEVTYPE_SCSI:
+ sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
+ TYPE_SCSI_DEVICE);
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
@@ -358,20 +385,24 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
- } else {
- VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_VIRTIO_NET);
-
+ break;
+ case CCW_DEVTYPE_VFIO:
+ ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
+ ipl->iplb.pbt = S390_IPL_TYPE_CCW;
+ ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
+ ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
+ break;
+ case CCW_DEVTYPE_VIRTIO_NET:
+ ipl->netboot = true;
+ /* Fall through to CCW_DEVTYPE_VIRTIO case */
+ case CCW_DEVTYPE_VIRTIO:
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
-
- if (vn) {
- ipl->netboot = true;
- }
+ break;
}
if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
@@ -530,7 +561,7 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type)
!ipl->netboot &&
ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
is_virtio_scsi_device(&ipl->iplb)) {
- CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0));
+ CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0), NULL);
if (ccw_dev &&
cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index cad91ee62679..f5f025d1b6ca 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -124,6 +124,14 @@ static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
g_free(cdev->mdevid);
}
+static void s390_ccw_instance_init(Object *obj)
+{
+ S390CCWDevice *dev = S390_CCW_DEVICE(obj);
+
+ device_add_bootindex_property(obj, &dev->bootindex, "bootindex",
+ "/disk@0,0", DEVICE(obj), NULL);
+}
+
static void s390_ccw_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -137,6 +145,7 @@ static void s390_ccw_class_init(ObjectClass *klass, void *data)
static const TypeInfo s390_ccw_info = {
.name = TYPE_S390_CCW,
.parent = TYPE_CCW_DEVICE,
+ .instance_init = s390_ccw_instance_init,
.instance_size = sizeof(S390CCWDevice),
.class_size = sizeof(S390CCWDeviceClass),
.class_init = s390_ccw_class_init,
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index c44d13cc5081..31dd3a2a87b6 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -21,12 +21,12 @@
#include "hw/vfio/vfio.h"
#include "hw/vfio/vfio-common.h"
#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/ccw-device.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
-#define TYPE_VFIO_CCW "vfio-ccw"
-typedef struct VFIOCCWDevice {
+struct VFIOCCWDevice {
S390CCWDevice cdev;
VFIODevice vdev;
uint64_t io_region_size;
@@ -35,7 +35,7 @@ typedef struct VFIOCCWDevice {
EventNotifier io_notifier;
bool force_orb_pfch;
bool warned_orb_pfch;
-} VFIOCCWDevice;
+};
static inline void warn_once_pfch(VFIOCCWDevice *vcdev, SubchDev *sch,
const char *msg)
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index 7d15a1a5d41d..901d805d79a3 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
CcwDevice parent_obj;
CssDevId hostid;
char *mdevid;
+ int32_t bootindex;
} S390CCWDevice;
typedef struct S390CCWDeviceClass {
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
new file mode 100644
index 000000000000..ee5250d0d788
--- /dev/null
+++ b/include/hw/s390x/vfio-ccw.h
@@ -0,0 +1,28 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017, 2019 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.
+ */
+
+#ifndef HW_VFIO_CCW_H
+#define HW_VFIO_CCW_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"
+#define VFIO_CCW(obj) \
+ OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW)
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+typedef struct VFIOCCWDevice VFIOCCWDevice;
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-25 13:21 ` [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
@ 2019-04-30 16:54 ` Peter Maydell
2019-04-30 16:54 ` Peter Maydell
2019-04-30 20:30 ` Eduardo Habkost
1 sibling, 2 replies; 48+ messages in thread
From: Peter Maydell @ 2019-04-30 16:54 UTC (permalink / raw)
To: Cornelia Huck; +Cc: qemu-s390x, QEMU Developers, Jason J. Herne, Thomas Huth
On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
>
> From: "Jason J. Herne" <jjherne@linux.ibm.com>
>
> Add bootindex property and iplb data for vfio-ccw devices. This allows us to
> forward boot information into the bios for vfio-ccw devices.
>
> Refactor s390_get_ccw_device() to return device type. This prevents us from
> having to use messy casting logic in several places.
>
> Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
> Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> Message-Id: <1554388475-18329-2-git-send-email-jjherne@linux.ibm.com>
> [thuth: fixed "typedef struct VFIOCCWDevice" build failure with clang]
> Signed-off-by: Thomas Huth <thuth@redhat.com>
Hi; Coverity has a complaint (CID 1401098) about the use of
object_dynamic_cast() in this function. It looks like it's just
the result of code motion making it forget we'd dismissed the
warning before, but maybe we can avoid it entirely...
> @@ -335,20 +360,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
> {
> DeviceState *dev_st;
> CcwDevice *ccw_dev = NULL;
> + SCSIDevice *sd;
> + int devtype;
>
> dev_st = get_boot_device(0);
> if (dev_st) {
> - ccw_dev = s390_get_ccw_device(dev_st);
> + ccw_dev = s390_get_ccw_device(dev_st, &devtype);
> }
>
> /*
> * Currently allow IPL only from CCW devices.
> */
> if (ccw_dev) {
> - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> - TYPE_SCSI_DEVICE);
> -
> - if (sd) {
> + switch (devtype) {
> + case CCW_DEVTYPE_SCSI:
> + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> + TYPE_SCSI_DEVICE);
Coverity doesn't like the use of object_dynamic_cast() without a
check that the return value isn't NULL before we dereference
it a few lines further down.
I think that if we know this cast must always succeed, we
could instead just write
SCSIDevice *sd = SCSI_DEVICE(dev_st);
On the other hand if the cast might not succeed because dev_st
isn't necessarily of the right type, then we should check it
for NULL and handle that appropriately.
thanks
-- PMM
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-30 16:54 ` Peter Maydell
@ 2019-04-30 16:54 ` Peter Maydell
2019-04-30 20:30 ` Eduardo Habkost
1 sibling, 0 replies; 48+ messages in thread
From: Peter Maydell @ 2019-04-30 16:54 UTC (permalink / raw)
To: Cornelia Huck; +Cc: Jason J. Herne, qemu-s390x, QEMU Developers, Thomas Huth
On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
>
> From: "Jason J. Herne" <jjherne@linux.ibm.com>
>
> Add bootindex property and iplb data for vfio-ccw devices. This allows us to
> forward boot information into the bios for vfio-ccw devices.
>
> Refactor s390_get_ccw_device() to return device type. This prevents us from
> having to use messy casting logic in several places.
>
> Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
> Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> Message-Id: <1554388475-18329-2-git-send-email-jjherne@linux.ibm.com>
> [thuth: fixed "typedef struct VFIOCCWDevice" build failure with clang]
> Signed-off-by: Thomas Huth <thuth@redhat.com>
Hi; Coverity has a complaint (CID 1401098) about the use of
object_dynamic_cast() in this function. It looks like it's just
the result of code motion making it forget we'd dismissed the
warning before, but maybe we can avoid it entirely...
> @@ -335,20 +360,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
> {
> DeviceState *dev_st;
> CcwDevice *ccw_dev = NULL;
> + SCSIDevice *sd;
> + int devtype;
>
> dev_st = get_boot_device(0);
> if (dev_st) {
> - ccw_dev = s390_get_ccw_device(dev_st);
> + ccw_dev = s390_get_ccw_device(dev_st, &devtype);
> }
>
> /*
> * Currently allow IPL only from CCW devices.
> */
> if (ccw_dev) {
> - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> - TYPE_SCSI_DEVICE);
> -
> - if (sd) {
> + switch (devtype) {
> + case CCW_DEVTYPE_SCSI:
> + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> + TYPE_SCSI_DEVICE);
Coverity doesn't like the use of object_dynamic_cast() without a
check that the return value isn't NULL before we dereference
it a few lines further down.
I think that if we know this cast must always succeed, we
could instead just write
SCSIDevice *sd = SCSI_DEVICE(dev_st);
On the other hand if the cast might not succeed because dev_st
isn't necessarily of the right type, then we should check it
for NULL and handle that appropriately.
thanks
-- PMM
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-30 16:54 ` Peter Maydell
2019-04-30 16:54 ` Peter Maydell
@ 2019-04-30 20:30 ` Eduardo Habkost
2019-04-30 20:30 ` Eduardo Habkost
2019-05-02 15:48 ` Cornelia Huck
1 sibling, 2 replies; 48+ messages in thread
From: Eduardo Habkost @ 2019-04-30 20:30 UTC (permalink / raw)
To: Peter Maydell
Cc: Cornelia Huck, Jason J. Herne, qemu-s390x, QEMU Developers,
Thomas Huth
On Tue, Apr 30, 2019 at 05:54:49PM +0100, Peter Maydell wrote:
> On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
[...]
> > - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > - TYPE_SCSI_DEVICE);
> > -
> > - if (sd) {
> > + switch (devtype) {
> > + case CCW_DEVTYPE_SCSI:
> > + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > + TYPE_SCSI_DEVICE);
>
> Coverity doesn't like the use of object_dynamic_cast() without a
> check that the return value isn't NULL before we dereference
> it a few lines further down.
>
> I think that if we know this cast must always succeed, we
> could instead just write
> SCSIDevice *sd = SCSI_DEVICE(dev_st);
>
> On the other hand if the cast might not succeed because dev_st
> isn't necessarily of the right type, then we should check it
> for NULL and handle that appropriately.
s390_get_ccw_device() will set devtype=CCW_DEVTYPE_SCSI only if
dev_st is TYPE_SCSI_DEVICE, so the cast must always succeed and
we should use SCSI_DEVICE(dev_st) here.
--
Eduardo
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-30 20:30 ` Eduardo Habkost
@ 2019-04-30 20:30 ` Eduardo Habkost
2019-05-02 15:48 ` Cornelia Huck
1 sibling, 0 replies; 48+ messages in thread
From: Eduardo Habkost @ 2019-04-30 20:30 UTC (permalink / raw)
To: Peter Maydell
Cc: Jason J. Herne, qemu-s390x, Cornelia Huck, QEMU Developers,
Thomas Huth
On Tue, Apr 30, 2019 at 05:54:49PM +0100, Peter Maydell wrote:
> On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
[...]
> > - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > - TYPE_SCSI_DEVICE);
> > -
> > - if (sd) {
> > + switch (devtype) {
> > + case CCW_DEVTYPE_SCSI:
> > + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > + TYPE_SCSI_DEVICE);
>
> Coverity doesn't like the use of object_dynamic_cast() without a
> check that the return value isn't NULL before we dereference
> it a few lines further down.
>
> I think that if we know this cast must always succeed, we
> could instead just write
> SCSIDevice *sd = SCSI_DEVICE(dev_st);
>
> On the other hand if the cast might not succeed because dev_st
> isn't necessarily of the right type, then we should check it
> for NULL and handle that appropriately.
s390_get_ccw_device() will set devtype=CCW_DEVTYPE_SCSI only if
dev_st is TYPE_SCSI_DEVICE, so the cast must always succeed and
we should use SCSI_DEVICE(dev_st) here.
--
Eduardo
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-04-30 20:30 ` Eduardo Habkost
2019-04-30 20:30 ` Eduardo Habkost
@ 2019-05-02 15:48 ` Cornelia Huck
2019-05-02 15:48 ` Cornelia Huck
1 sibling, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-05-02 15:48 UTC (permalink / raw)
To: Eduardo Habkost
Cc: Peter Maydell, Jason J. Herne, qemu-s390x, QEMU Developers,
Thomas Huth
On Tue, 30 Apr 2019 17:30:09 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
> On Tue, Apr 30, 2019 at 05:54:49PM +0100, Peter Maydell wrote:
> > On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
> [...]
> > > - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > > - TYPE_SCSI_DEVICE);
> > > -
> > > - if (sd) {
> > > + switch (devtype) {
> > > + case CCW_DEVTYPE_SCSI:
> > > + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > > + TYPE_SCSI_DEVICE);
> >
> > Coverity doesn't like the use of object_dynamic_cast() without a
> > check that the return value isn't NULL before we dereference
> > it a few lines further down.
> >
> > I think that if we know this cast must always succeed, we
> > could instead just write
> > SCSIDevice *sd = SCSI_DEVICE(dev_st);
> >
> > On the other hand if the cast might not succeed because dev_st
> > isn't necessarily of the right type, then we should check it
> > for NULL and handle that appropriately.
>
> s390_get_ccw_device() will set devtype=CCW_DEVTYPE_SCSI only if
> dev_st is TYPE_SCSI_DEVICE, so the cast must always succeed and
> we should use SCSI_DEVICE(dev_st) here.
>
Yes; sending a patch.
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data
2019-05-02 15:48 ` Cornelia Huck
@ 2019-05-02 15:48 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-05-02 15:48 UTC (permalink / raw)
To: Eduardo Habkost
Cc: Jason J. Herne, Peter Maydell, qemu-s390x, QEMU Developers,
Thomas Huth
On Tue, 30 Apr 2019 17:30:09 -0300
Eduardo Habkost <ehabkost@redhat.com> wrote:
> On Tue, Apr 30, 2019 at 05:54:49PM +0100, Peter Maydell wrote:
> > On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
> [...]
> > > - SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > > - TYPE_SCSI_DEVICE);
> > > -
> > > - if (sd) {
> > > + switch (devtype) {
> > > + case CCW_DEVTYPE_SCSI:
> > > + sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
> > > + TYPE_SCSI_DEVICE);
> >
> > Coverity doesn't like the use of object_dynamic_cast() without a
> > check that the return value isn't NULL before we dereference
> > it a few lines further down.
> >
> > I think that if we know this cast must always succeed, we
> > could instead just write
> > SCSIDevice *sd = SCSI_DEVICE(dev_st);
> >
> > On the other hand if the cast might not succeed because dev_st
> > isn't necessarily of the right type, then we should check it
> > for NULL and handle that appropriately.
>
> s390_get_ccw_device() will set devtype=CCW_DEVTYPE_SCSI only if
> dev_st is TYPE_SCSI_DEVICE, so the cast must always succeed and
> we should use SCSI_DEVICE(dev_st) here.
>
Yes; sending a patch.
^ permalink raw reply [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 02/19] s390-bios: decouple cio setup from virtio
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 01/19] s390 vfio-ccw: Add bootindex property and IPLB data Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 03/19] s390-bios: decouple common boot logic " Cornelia Huck
` (17 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Move channel i/o setup code out to a separate function. This decouples cio
setup from the virtio code path and allows us to make use of it for booting
dasd devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-3-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 544851d672d8..e82fe2ce2315 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -99,6 +99,18 @@ static void menu_setup(void)
}
}
+/*
+ * Initialize the channel I/O subsystem so we can talk to our ipl/boot device.
+ */
+static void css_setup(void)
+{
+ /*
+ * Unconditionally enable mss support. In every sane configuration this
+ * will succeed; and even if it doesn't, stsch_err() can handle it.
+ */
+ enable_mss_facility();
+}
+
static void virtio_setup(void)
{
Schib schib;
@@ -109,13 +121,6 @@ static void virtio_setup(void)
VDev *vdev = virtio_get_device();
QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
- /*
- * We unconditionally enable mss support. In every sane configuration,
- * this will succeed; and even if it doesn't, stsch_err() can deal
- * with the consequences.
- */
- enable_mss_facility();
-
sclp_get_loadparm_ascii(loadparm_str);
memcpy(ldp + 10, loadparm_str, LOADPARM_LEN);
sclp_print(ldp);
@@ -168,6 +173,7 @@ static void virtio_setup(void)
int main(void)
{
sclp_setup();
+ css_setup();
virtio_setup();
zipl_load(); /* no return */
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 02/19] s390-bios: decouple cio setup from virtio
2019-04-25 13:21 ` [Qemu-devel] [PULL 02/19] s390-bios: decouple cio setup from virtio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Move channel i/o setup code out to a separate function. This decouples cio
setup from the virtio code path and allows us to make use of it for booting
dasd devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-3-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 544851d672d8..e82fe2ce2315 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -99,6 +99,18 @@ static void menu_setup(void)
}
}
+/*
+ * Initialize the channel I/O subsystem so we can talk to our ipl/boot device.
+ */
+static void css_setup(void)
+{
+ /*
+ * Unconditionally enable mss support. In every sane configuration this
+ * will succeed; and even if it doesn't, stsch_err() can handle it.
+ */
+ enable_mss_facility();
+}
+
static void virtio_setup(void)
{
Schib schib;
@@ -109,13 +121,6 @@ static void virtio_setup(void)
VDev *vdev = virtio_get_device();
QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
- /*
- * We unconditionally enable mss support. In every sane configuration,
- * this will succeed; and even if it doesn't, stsch_err() can deal
- * with the consequences.
- */
- enable_mss_facility();
-
sclp_get_loadparm_ascii(loadparm_str);
memcpy(ldp + 10, loadparm_str, LOADPARM_LEN);
sclp_print(ldp);
@@ -168,6 +173,7 @@ static void virtio_setup(void)
int main(void)
{
sclp_setup();
+ css_setup();
virtio_setup();
zipl_load(); /* no return */
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 03/19] s390-bios: decouple common boot logic from virtio
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (2 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 02/19] s390-bios: decouple cio setup from virtio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 04/19] s390-bios: Clean up cio.h Cornelia Huck
` (16 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a boot_setup function to handle getting boot information from
the machine/hypervisor. This decouples common boot logic from the
virtio code path and allows us to make use of it for the real dasd boot
scenario.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-4-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e82fe2ce2315..67df42191b94 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -14,16 +14,17 @@
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
-IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
+IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
+static bool have_iplb;
#define LOADPARM_PROMPT "PROMPT "
#define LOADPARM_EMPTY " "
#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
/*
- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
+ * Principles of Operations (SA22-7832-09) chapter 17 requires that
* a subsystem-identification is at 184-187 and bytes 188-191 are zero
* after list-directed-IPL and ccw-IPL.
*/
@@ -111,23 +112,33 @@ static void css_setup(void)
enable_mss_facility();
}
+/*
+ * Collect various pieces of information from the hypervisor/hardware that
+ * we'll use to determine exactly how we'll boot.
+ */
+static void boot_setup(void)
+{
+ char lpmsg[] = "LOADPARM=[________]\n";
+
+ sclp_get_loadparm_ascii(loadparm_str);
+ memcpy(lpmsg + 10, loadparm_str, 8);
+ sclp_print(lpmsg);
+
+ have_iplb = store_iplb(&iplb);
+}
+
static void virtio_setup(void)
{
Schib schib;
int ssid;
bool found = false;
uint16_t dev_no;
- char ldp[] = "LOADPARM=[________]\n";
VDev *vdev = virtio_get_device();
QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
- sclp_get_loadparm_ascii(loadparm_str);
- memcpy(ldp + 10, loadparm_str, LOADPARM_LEN);
- sclp_print(ldp);
-
memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
- if (store_iplb(&iplb)) {
+ if (have_iplb) {
switch (iplb.pbt) {
case S390_IPL_TYPE_CCW:
dev_no = iplb.ccw.devno;
@@ -174,6 +185,7 @@ int main(void)
{
sclp_setup();
css_setup();
+ boot_setup();
virtio_setup();
zipl_load(); /* no return */
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 03/19] s390-bios: decouple common boot logic from virtio
2019-04-25 13:21 ` [Qemu-devel] [PULL 03/19] s390-bios: decouple common boot logic " Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a boot_setup function to handle getting boot information from
the machine/hypervisor. This decouples common boot logic from the
virtio code path and allows us to make use of it for the real dasd boot
scenario.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-4-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e82fe2ce2315..67df42191b94 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -14,16 +14,17 @@
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
-IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
+IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
+static bool have_iplb;
#define LOADPARM_PROMPT "PROMPT "
#define LOADPARM_EMPTY " "
#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
/*
- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
+ * Principles of Operations (SA22-7832-09) chapter 17 requires that
* a subsystem-identification is at 184-187 and bytes 188-191 are zero
* after list-directed-IPL and ccw-IPL.
*/
@@ -111,23 +112,33 @@ static void css_setup(void)
enable_mss_facility();
}
+/*
+ * Collect various pieces of information from the hypervisor/hardware that
+ * we'll use to determine exactly how we'll boot.
+ */
+static void boot_setup(void)
+{
+ char lpmsg[] = "LOADPARM=[________]\n";
+
+ sclp_get_loadparm_ascii(loadparm_str);
+ memcpy(lpmsg + 10, loadparm_str, 8);
+ sclp_print(lpmsg);
+
+ have_iplb = store_iplb(&iplb);
+}
+
static void virtio_setup(void)
{
Schib schib;
int ssid;
bool found = false;
uint16_t dev_no;
- char ldp[] = "LOADPARM=[________]\n";
VDev *vdev = virtio_get_device();
QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
- sclp_get_loadparm_ascii(loadparm_str);
- memcpy(ldp + 10, loadparm_str, LOADPARM_LEN);
- sclp_print(ldp);
-
memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
- if (store_iplb(&iplb)) {
+ if (have_iplb) {
switch (iplb.pbt) {
case S390_IPL_TYPE_CCW:
dev_no = iplb.ccw.devno;
@@ -174,6 +185,7 @@ int main(void)
{
sclp_setup();
css_setup();
+ boot_setup();
virtio_setup();
zipl_load(); /* no return */
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 04/19] s390-bios: Clean up cio.h
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (3 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 03/19] s390-bios: decouple common boot logic " Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 05/19] s390-bios: Decouple channel i/o logic from virtio Cornelia Huck
` (15 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add proper typedefs to all structs and modify all bit fields to use consistent
formatting.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-5-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.h | 114 ++++++++++++++++++------------------
pc-bios/s390-ccw/s390-ccw.h | 8 ---
2 files changed, 57 insertions(+), 65 deletions(-)
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 1a0795f6455f..ed5b2cbf72db 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -17,35 +17,35 @@
* path management control word
*/
struct pmcw {
- __u32 intparm; /* interruption parameter */
- __u32 qf : 1; /* qdio facility */
- __u32 w : 1;
- __u32 isc : 3; /* interruption sublass */
- __u32 res5 : 3; /* reserved zeros */
- __u32 ena : 1; /* enabled */
- __u32 lm : 2; /* limit mode */
- __u32 mme : 2; /* measurement-mode enable */
- __u32 mp : 1; /* multipath mode */
- __u32 tf : 1; /* timing facility */
- __u32 dnv : 1; /* device number valid */
- __u32 dev : 16; /* device number */
- __u8 lpm; /* logical path mask */
- __u8 pnom; /* path not operational mask */
- __u8 lpum; /* last path used mask */
- __u8 pim; /* path installed mask */
- __u16 mbi; /* measurement-block index */
- __u8 pom; /* path operational mask */
- __u8 pam; /* path available mask */
- __u8 chpid[8]; /* CHPID 0-7 (if available) */
- __u32 unused1 : 8; /* reserved zeros */
- __u32 st : 3; /* subchannel type */
- __u32 unused2 : 18; /* reserved zeros */
- __u32 mbfc : 1; /* measurement block format control */
- __u32 xmwme : 1; /* extended measurement word mode enable */
- __u32 csense : 1; /* concurrent sense; can be enabled ...*/
- /* ... per MSCH, however, if facility */
- /* ... is not installed, this results */
- /* ... in an operand exception. */
+ __u32 intparm; /* interruption parameter */
+ __u32 qf:1; /* qdio facility */
+ __u32 w:1;
+ __u32 isc:3; /* interruption sublass */
+ __u32 res5:3; /* reserved zeros */
+ __u32 ena:1; /* enabled */
+ __u32 lm:2; /* limit mode */
+ __u32 mme:2; /* measurement-mode enable */
+ __u32 mp:1; /* multipath mode */
+ __u32 tf:1; /* timing facility */
+ __u32 dnv:1; /* device number valid */
+ __u32 dev:16; /* device number */
+ __u8 lpm; /* logical path mask */
+ __u8 pnom; /* path not operational mask */
+ __u8 lpum; /* last path used mask */
+ __u8 pim; /* path installed mask */
+ __u16 mbi; /* measurement-block index */
+ __u8 pom; /* path operational mask */
+ __u8 pam; /* path available mask */
+ __u8 chpid[8]; /* CHPID 0-7 (if available) */
+ __u32 unused1:8; /* reserved zeros */
+ __u32 st:3; /* subchannel type */
+ __u32 unused2:18; /* reserved zeros */
+ __u32 mbfc:1; /* measurement block format control */
+ __u32 xmwme:1; /* extended measurement word mode enable */
+ __u32 csense:1; /* concurrent sense; can be enabled ...*/
+ /* ... per MSCH, however, if facility */
+ /* ... is not installed, this results */
+ /* ... in an operand exception. */
} __attribute__ ((packed));
/* Target SCHIB configuration. */
@@ -77,28 +77,28 @@ struct scsw {
/*
* subchannel information block
*/
-struct schib {
+typedef struct schib {
struct pmcw pmcw; /* path management control word */
struct scsw scsw; /* subchannel status word */
__u64 mba; /* measurement block address */
__u8 mda[4]; /* model dependent area */
-} __attribute__ ((packed,aligned(4)));
-
-struct subchannel_id {
- __u32 cssid : 8;
- __u32 : 4;
- __u32 m : 1;
- __u32 ssid : 2;
- __u32 one : 1;
- __u32 sch_no : 16;
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Schib;
+
+typedef struct subchannel_id {
+ __u32 cssid:8;
+ __u32:4;
+ __u32 m:1;
+ __u32 ssid:2;
+ __u32 one:1;
+ __u32 sch_no:16;
+} __attribute__ ((packed, aligned(4))) SubChannelId;
struct chsc_header {
__u16 length;
__u16 code;
} __attribute__((packed));
-struct chsc_area_sda {
+typedef struct chsc_area_sda {
struct chsc_header request;
__u8 reserved1:4;
__u8 format:4;
@@ -111,29 +111,29 @@ struct chsc_area_sda {
__u32 reserved5:4;
__u32 format2:4;
__u32 reserved6:24;
-} __attribute__((packed));
+} __attribute__((packed)) ChscAreaSda;
/*
* TPI info structure
*/
struct tpi_info {
struct subchannel_id schid;
- __u32 intparm; /* interruption parameter */
- __u32 adapter_IO : 1;
- __u32 reserved2 : 1;
- __u32 isc : 3;
- __u32 reserved3 : 12;
- __u32 int_type : 3;
- __u32 reserved4 : 12;
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO:1;
+ __u32 reserved2:1;
+ __u32 isc:3;
+ __u32 reserved3:12;
+ __u32 int_type:3;
+ __u32 reserved4:12;
} __attribute__ ((packed, aligned(4)));
/* channel command word (type 1) */
-struct ccw1 {
+typedef struct ccw1 {
__u8 cmd_code;
__u8 flags;
__u16 count;
__u32 cda;
-} __attribute__ ((packed, aligned(8)));
+} __attribute__ ((packed, aligned(8))) Ccw1;
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
@@ -162,7 +162,7 @@ struct ccw1 {
/*
* Command-mode operation request block
*/
-struct cmd_orb {
+typedef struct cmd_orb {
__u32 intparm; /* interruption parameter */
__u32 key:4; /* flags, like key, suspend control, etc. */
__u32 spnd:1; /* suspend control */
@@ -182,7 +182,7 @@ struct cmd_orb {
__u32 zero:6; /* reserved zeros */
__u32 orbx:1; /* ORB extension control */
__u32 cpa; /* channel program address */
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) CmdOrb;
struct ciw {
__u8 type;
@@ -193,7 +193,7 @@ struct ciw {
/*
* sense-id response buffer layout
*/
-struct senseid {
+typedef struct senseid {
/* common part */
__u8 reserved; /* always 0x'FF' */
__u16 cu_type; /* control unit type */
@@ -203,15 +203,15 @@ struct senseid {
__u8 unused; /* padding byte */
/* extended part */
struct ciw ciw[62];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) SenseId;
/* interruption response block */
-struct irb {
+typedef struct irb {
struct scsw scsw;
__u32 esw[5];
__u32 ecw[8];
__u32 emw[8];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Irb;
/*
* Some S390 specific IO instructions as inline
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 9828aa233d2e..241c6d0b69be 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -49,14 +49,6 @@ typedef unsigned long long __u64;
#include "cio.h"
#include "iplb.h"
-typedef struct irb Irb;
-typedef struct ccw1 Ccw1;
-typedef struct cmd_orb CmdOrb;
-typedef struct schib Schib;
-typedef struct chsc_area_sda ChscAreaSda;
-typedef struct senseid SenseId;
-typedef struct subchannel_id SubChannelId;
-
/* start.s */
void disabled_wait(void);
void consume_sclp_int(void);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 04/19] s390-bios: Clean up cio.h
2019-04-25 13:21 ` [Qemu-devel] [PULL 04/19] s390-bios: Clean up cio.h Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add proper typedefs to all structs and modify all bit fields to use consistent
formatting.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Collin Walling <walling@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-5-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.h | 114 ++++++++++++++++++------------------
pc-bios/s390-ccw/s390-ccw.h | 8 ---
2 files changed, 57 insertions(+), 65 deletions(-)
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 1a0795f6455f..ed5b2cbf72db 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -17,35 +17,35 @@
* path management control word
*/
struct pmcw {
- __u32 intparm; /* interruption parameter */
- __u32 qf : 1; /* qdio facility */
- __u32 w : 1;
- __u32 isc : 3; /* interruption sublass */
- __u32 res5 : 3; /* reserved zeros */
- __u32 ena : 1; /* enabled */
- __u32 lm : 2; /* limit mode */
- __u32 mme : 2; /* measurement-mode enable */
- __u32 mp : 1; /* multipath mode */
- __u32 tf : 1; /* timing facility */
- __u32 dnv : 1; /* device number valid */
- __u32 dev : 16; /* device number */
- __u8 lpm; /* logical path mask */
- __u8 pnom; /* path not operational mask */
- __u8 lpum; /* last path used mask */
- __u8 pim; /* path installed mask */
- __u16 mbi; /* measurement-block index */
- __u8 pom; /* path operational mask */
- __u8 pam; /* path available mask */
- __u8 chpid[8]; /* CHPID 0-7 (if available) */
- __u32 unused1 : 8; /* reserved zeros */
- __u32 st : 3; /* subchannel type */
- __u32 unused2 : 18; /* reserved zeros */
- __u32 mbfc : 1; /* measurement block format control */
- __u32 xmwme : 1; /* extended measurement word mode enable */
- __u32 csense : 1; /* concurrent sense; can be enabled ...*/
- /* ... per MSCH, however, if facility */
- /* ... is not installed, this results */
- /* ... in an operand exception. */
+ __u32 intparm; /* interruption parameter */
+ __u32 qf:1; /* qdio facility */
+ __u32 w:1;
+ __u32 isc:3; /* interruption sublass */
+ __u32 res5:3; /* reserved zeros */
+ __u32 ena:1; /* enabled */
+ __u32 lm:2; /* limit mode */
+ __u32 mme:2; /* measurement-mode enable */
+ __u32 mp:1; /* multipath mode */
+ __u32 tf:1; /* timing facility */
+ __u32 dnv:1; /* device number valid */
+ __u32 dev:16; /* device number */
+ __u8 lpm; /* logical path mask */
+ __u8 pnom; /* path not operational mask */
+ __u8 lpum; /* last path used mask */
+ __u8 pim; /* path installed mask */
+ __u16 mbi; /* measurement-block index */
+ __u8 pom; /* path operational mask */
+ __u8 pam; /* path available mask */
+ __u8 chpid[8]; /* CHPID 0-7 (if available) */
+ __u32 unused1:8; /* reserved zeros */
+ __u32 st:3; /* subchannel type */
+ __u32 unused2:18; /* reserved zeros */
+ __u32 mbfc:1; /* measurement block format control */
+ __u32 xmwme:1; /* extended measurement word mode enable */
+ __u32 csense:1; /* concurrent sense; can be enabled ...*/
+ /* ... per MSCH, however, if facility */
+ /* ... is not installed, this results */
+ /* ... in an operand exception. */
} __attribute__ ((packed));
/* Target SCHIB configuration. */
@@ -77,28 +77,28 @@ struct scsw {
/*
* subchannel information block
*/
-struct schib {
+typedef struct schib {
struct pmcw pmcw; /* path management control word */
struct scsw scsw; /* subchannel status word */
__u64 mba; /* measurement block address */
__u8 mda[4]; /* model dependent area */
-} __attribute__ ((packed,aligned(4)));
-
-struct subchannel_id {
- __u32 cssid : 8;
- __u32 : 4;
- __u32 m : 1;
- __u32 ssid : 2;
- __u32 one : 1;
- __u32 sch_no : 16;
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Schib;
+
+typedef struct subchannel_id {
+ __u32 cssid:8;
+ __u32:4;
+ __u32 m:1;
+ __u32 ssid:2;
+ __u32 one:1;
+ __u32 sch_no:16;
+} __attribute__ ((packed, aligned(4))) SubChannelId;
struct chsc_header {
__u16 length;
__u16 code;
} __attribute__((packed));
-struct chsc_area_sda {
+typedef struct chsc_area_sda {
struct chsc_header request;
__u8 reserved1:4;
__u8 format:4;
@@ -111,29 +111,29 @@ struct chsc_area_sda {
__u32 reserved5:4;
__u32 format2:4;
__u32 reserved6:24;
-} __attribute__((packed));
+} __attribute__((packed)) ChscAreaSda;
/*
* TPI info structure
*/
struct tpi_info {
struct subchannel_id schid;
- __u32 intparm; /* interruption parameter */
- __u32 adapter_IO : 1;
- __u32 reserved2 : 1;
- __u32 isc : 3;
- __u32 reserved3 : 12;
- __u32 int_type : 3;
- __u32 reserved4 : 12;
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO:1;
+ __u32 reserved2:1;
+ __u32 isc:3;
+ __u32 reserved3:12;
+ __u32 int_type:3;
+ __u32 reserved4:12;
} __attribute__ ((packed, aligned(4)));
/* channel command word (type 1) */
-struct ccw1 {
+typedef struct ccw1 {
__u8 cmd_code;
__u8 flags;
__u16 count;
__u32 cda;
-} __attribute__ ((packed, aligned(8)));
+} __attribute__ ((packed, aligned(8))) Ccw1;
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
@@ -162,7 +162,7 @@ struct ccw1 {
/*
* Command-mode operation request block
*/
-struct cmd_orb {
+typedef struct cmd_orb {
__u32 intparm; /* interruption parameter */
__u32 key:4; /* flags, like key, suspend control, etc. */
__u32 spnd:1; /* suspend control */
@@ -182,7 +182,7 @@ struct cmd_orb {
__u32 zero:6; /* reserved zeros */
__u32 orbx:1; /* ORB extension control */
__u32 cpa; /* channel program address */
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) CmdOrb;
struct ciw {
__u8 type;
@@ -193,7 +193,7 @@ struct ciw {
/*
* sense-id response buffer layout
*/
-struct senseid {
+typedef struct senseid {
/* common part */
__u8 reserved; /* always 0x'FF' */
__u16 cu_type; /* control unit type */
@@ -203,15 +203,15 @@ struct senseid {
__u8 unused; /* padding byte */
/* extended part */
struct ciw ciw[62];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) SenseId;
/* interruption response block */
-struct irb {
+typedef struct irb {
struct scsw scsw;
__u32 esw[5];
__u32 ecw[8];
__u32 emw[8];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Irb;
/*
* Some S390 specific IO instructions as inline
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 9828aa233d2e..241c6d0b69be 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -49,14 +49,6 @@ typedef unsigned long long __u64;
#include "cio.h"
#include "iplb.h"
-typedef struct irb Irb;
-typedef struct ccw1 Ccw1;
-typedef struct cmd_orb CmdOrb;
-typedef struct schib Schib;
-typedef struct chsc_area_sda ChscAreaSda;
-typedef struct senseid SenseId;
-typedef struct subchannel_id SubChannelId;
-
/* start.s */
void disabled_wait(void);
void consume_sclp_int(void);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 05/19] s390-bios: Decouple channel i/o logic from virtio
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (4 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 04/19] s390-bios: Clean up cio.h Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 06/19] s390-bios: Map low core memory Cornelia Huck
` (14 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a separate library for channel i/o related code. This decouples
channel i/o operations from virtio and allows us to make use of them for
the real dasd boot path.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-6-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/cio.c | 44 ++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/cio.h | 3 +++
pc-bios/s390-ccw/main.c | 1 +
pc-bios/s390-ccw/netboot.mak | 2 +-
pc-bios/s390-ccw/netmain.c | 1 +
pc-bios/s390-ccw/s390-ccw.h | 1 -
pc-bios/s390-ccw/virtio.c | 27 ++--------------------
8 files changed, 53 insertions(+), 28 deletions(-)
create mode 100644 pc-bios/s390-ccw/cio.c
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 1eb316b02f1f..12ad9c1d5813 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
- virtio.o virtio-scsi.o virtio-blkdev.o libc.o
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
new file mode 100644
index 000000000000..87c6b34e88af
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.c
@@ -0,0 +1,44 @@
+/*
+ * S390 Channel I/O
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.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 "libc.h"
+#include "s390-ccw.h"
+#include "cio.h"
+
+static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+
+int enable_mss_facility(void)
+{
+ int ret;
+ ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
+
+ memset(sda_area, 0, PAGE_SIZE);
+ sda_area->request.length = 0x0400;
+ sda_area->request.code = 0x0031;
+ sda_area->operation_code = 0x2;
+
+ ret = chsc(sda_area);
+ if ((ret == 0) && (sda_area->response.code == 0x0001)) {
+ return 0;
+ }
+ return -EIO;
+}
+
+void enable_subchannel(SubChannelId schid)
+{
+ Schib schib;
+
+ stsch_err(schid, &schib);
+ schib.pmcw.ena = 1;
+ msch(schid, &schib);
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index ed5b2cbf72db..218fd96ea3a6 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -213,6 +213,9 @@ typedef struct irb {
__u32 emw[8];
} __attribute__ ((packed, aligned(4))) Irb;
+int enable_mss_facility(void);
+void enable_subchannel(SubChannelId schid);
+
/*
* Some S390 specific IO instructions as inline
*/
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 67df42191b94..10f04c69068f 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -10,6 +10,7 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
index 14e96b2aa611..5eefb7c28939 100644
--- a/pc-bios/s390-ccw/netboot.mak
+++ b/pc-bios/s390-ccw/netboot.mak
@@ -1,7 +1,7 @@
SLOF_DIR := $(SRC_PATH)/roms/SLOF
-NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \
+NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \
libnet.a libc.a
LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 0392131c27b3..5189c0fc39e5 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -33,6 +33,7 @@
#include <pxelinux.h>
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#define DEFAULT_BOOT_RETRIES 10
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 241c6d0b69be..b39ee5d32314 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -72,7 +72,6 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
bool virtio_is_supported(SubChannelId schid);
void virtio_blk_setup_device(SubChannelId schid);
int virtio_read(ulong sector, void *load_addr);
-int enable_mss_facility(void);
u64 get_clock(void);
ulong get_second(void);
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index cdb66f459e15..aa9da7253fb2 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -10,6 +10,7 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#include "virtio-scsi.h"
#include "bswap.h"
@@ -20,8 +21,6 @@ static VRing block[VIRTIO_MAX_VQS];
static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS]
__attribute__((__aligned__(PAGE_SIZE)));
-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-
static VDev vdev = {
.nr_vqs = 1,
.vrings = block,
@@ -94,14 +93,9 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
{
Ccw1 ccw = {};
CmdOrb orb = {};
- Schib schib;
int r;
- /* start command processing */
- stsch_err(vdev->schid, &schib);
- /* enable the subchannel for IPL device */
- schib.pmcw.ena = 1;
- msch(vdev->schid, &schib);
+ enable_subchannel(vdev->schid);
/* start subchannel command */
orb.fmt = 1;
@@ -343,20 +337,3 @@ bool virtio_is_supported(SubChannelId schid)
}
return false;
}
-
-int enable_mss_facility(void)
-{
- int ret;
- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
-
- memset(sda_area, 0, PAGE_SIZE);
- sda_area->request.length = 0x0400;
- sda_area->request.code = 0x0031;
- sda_area->operation_code = 0x2;
-
- ret = chsc(sda_area);
- if ((ret == 0) && (sda_area->response.code == 0x0001)) {
- return 0;
- }
- return -EIO;
-}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 05/19] s390-bios: Decouple channel i/o logic from virtio
2019-04-25 13:21 ` [Qemu-devel] [PULL 05/19] s390-bios: Decouple channel i/o logic from virtio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a separate library for channel i/o related code. This decouples
channel i/o operations from virtio and allows us to make use of them for
the real dasd boot path.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-6-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/cio.c | 44 ++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/cio.h | 3 +++
pc-bios/s390-ccw/main.c | 1 +
pc-bios/s390-ccw/netboot.mak | 2 +-
pc-bios/s390-ccw/netmain.c | 1 +
pc-bios/s390-ccw/s390-ccw.h | 1 -
pc-bios/s390-ccw/virtio.c | 27 ++--------------------
8 files changed, 53 insertions(+), 28 deletions(-)
create mode 100644 pc-bios/s390-ccw/cio.c
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 1eb316b02f1f..12ad9c1d5813 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
- virtio.o virtio-scsi.o virtio-blkdev.o libc.o
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
new file mode 100644
index 000000000000..87c6b34e88af
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.c
@@ -0,0 +1,44 @@
+/*
+ * S390 Channel I/O
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.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 "libc.h"
+#include "s390-ccw.h"
+#include "cio.h"
+
+static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+
+int enable_mss_facility(void)
+{
+ int ret;
+ ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
+
+ memset(sda_area, 0, PAGE_SIZE);
+ sda_area->request.length = 0x0400;
+ sda_area->request.code = 0x0031;
+ sda_area->operation_code = 0x2;
+
+ ret = chsc(sda_area);
+ if ((ret == 0) && (sda_area->response.code == 0x0001)) {
+ return 0;
+ }
+ return -EIO;
+}
+
+void enable_subchannel(SubChannelId schid)
+{
+ Schib schib;
+
+ stsch_err(schid, &schib);
+ schib.pmcw.ena = 1;
+ msch(schid, &schib);
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index ed5b2cbf72db..218fd96ea3a6 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -213,6 +213,9 @@ typedef struct irb {
__u32 emw[8];
} __attribute__ ((packed, aligned(4))) Irb;
+int enable_mss_facility(void);
+void enable_subchannel(SubChannelId schid);
+
/*
* Some S390 specific IO instructions as inline
*/
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 67df42191b94..10f04c69068f 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -10,6 +10,7 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
index 14e96b2aa611..5eefb7c28939 100644
--- a/pc-bios/s390-ccw/netboot.mak
+++ b/pc-bios/s390-ccw/netboot.mak
@@ -1,7 +1,7 @@
SLOF_DIR := $(SRC_PATH)/roms/SLOF
-NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \
+NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \
libnet.a libc.a
LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 0392131c27b3..5189c0fc39e5 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -33,6 +33,7 @@
#include <pxelinux.h>
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#define DEFAULT_BOOT_RETRIES 10
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 241c6d0b69be..b39ee5d32314 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -72,7 +72,6 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
bool virtio_is_supported(SubChannelId schid);
void virtio_blk_setup_device(SubChannelId schid);
int virtio_read(ulong sector, void *load_addr);
-int enable_mss_facility(void);
u64 get_clock(void);
ulong get_second(void);
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index cdb66f459e15..aa9da7253fb2 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -10,6 +10,7 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#include "virtio-scsi.h"
#include "bswap.h"
@@ -20,8 +21,6 @@ static VRing block[VIRTIO_MAX_VQS];
static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS]
__attribute__((__aligned__(PAGE_SIZE)));
-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-
static VDev vdev = {
.nr_vqs = 1,
.vrings = block,
@@ -94,14 +93,9 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
{
Ccw1 ccw = {};
CmdOrb orb = {};
- Schib schib;
int r;
- /* start command processing */
- stsch_err(vdev->schid, &schib);
- /* enable the subchannel for IPL device */
- schib.pmcw.ena = 1;
- msch(vdev->schid, &schib);
+ enable_subchannel(vdev->schid);
/* start subchannel command */
orb.fmt = 1;
@@ -343,20 +337,3 @@ bool virtio_is_supported(SubChannelId schid)
}
return false;
}
-
-int enable_mss_facility(void)
-{
- int ret;
- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
-
- memset(sda_area, 0, PAGE_SIZE);
- sda_area->request.length = 0x0400;
- sda_area->request.code = 0x0031;
- sda_area->operation_code = 0x2;
-
- ret = chsc(sda_area);
- if ((ret == 0) && (sda_area->response.code == 0x0001)) {
- return 0;
- }
- return -EIO;
-}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 06/19] s390-bios: Map low core memory
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (5 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 05/19] s390-bios: Decouple channel i/o logic from virtio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 07/19] s390-bios: ptr2u32 and u32toptr Cornelia Huck
` (13 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a new header for basic architecture specific definitions and add a
mapping of low core memory. This mapping will be used by the real dasd boot
process.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-7-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 2 +
pc-bios/s390-ccw/s390-arch.h | 90 ++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+)
create mode 100644 pc-bios/s390-ccw/s390-arch.h
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 10f04c69068f..e403b5f733e4 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -9,6 +9,7 @@
*/
#include "libc.h"
+#include "s390-arch.h"
#include "s390-ccw.h"
#include "cio.h"
#include "virtio.h"
@@ -19,6 +20,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static bool have_iplb;
+LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */
#define LOADPARM_PROMPT "PROMPT "
#define LOADPARM_EMPTY " "
diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h
new file mode 100644
index 000000000000..5e92c7a27d53
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-arch.h
@@ -0,0 +1,90 @@
+/*
+ * S390 Basic Architecture
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 S390_ARCH_H
+#define S390_ARCH_H
+
+typedef struct PSW {
+ uint64_t mask;
+ uint64_t addr;
+} __attribute__ ((aligned(8))) PSW;
+_Static_assert(sizeof(struct PSW) == 16, "PSW size incorrect");
+
+/* Older PSW format used by LPSW instruction */
+typedef struct PSWLegacy {
+ uint32_t mask;
+ uint32_t addr;
+} __attribute__ ((aligned(8))) PSWLegacy;
+_Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect");
+
+/* s390 psw bit masks */
+#define PSW_MASK_IOINT 0x0200000000000000ULL
+#define PSW_MASK_WAIT 0x0002000000000000ULL
+#define PSW_MASK_EAMODE 0x0000000100000000ULL
+#define PSW_MASK_BAMODE 0x0000000080000000ULL
+#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE)
+
+/* Low core mapping */
+typedef struct LowCore {
+ /* prefix area: defined by architecture */
+ PSWLegacy ipl_psw; /* 0x000 */
+ uint32_t ccw1[2]; /* 0x008 */
+ uint32_t ccw2[2]; /* 0x010 */
+ uint8_t pad1[0x80 - 0x18]; /* 0x018 */
+ uint32_t ext_params; /* 0x080 */
+ uint16_t cpu_addr; /* 0x084 */
+ uint16_t ext_int_code; /* 0x086 */
+ uint16_t svc_ilen; /* 0x088 */
+ uint16_t svc_code; /* 0x08a */
+ uint16_t pgm_ilen; /* 0x08c */
+ uint16_t pgm_code; /* 0x08e */
+ uint32_t data_exc_code; /* 0x090 */
+ uint16_t mon_class_num; /* 0x094 */
+ uint16_t per_perc_atmid; /* 0x096 */
+ uint64_t per_address; /* 0x098 */
+ uint8_t exc_access_id; /* 0x0a0 */
+ uint8_t per_access_id; /* 0x0a1 */
+ uint8_t op_access_id; /* 0x0a2 */
+ uint8_t ar_access_id; /* 0x0a3 */
+ uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
+ uint64_t trans_exc_code; /* 0x0a8 */
+ uint64_t monitor_code; /* 0x0b0 */
+ uint16_t subchannel_id; /* 0x0b8 */
+ uint16_t subchannel_nr; /* 0x0ba */
+ uint32_t io_int_parm; /* 0x0bc */
+ uint32_t io_int_word; /* 0x0c0 */
+ uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
+ uint32_t stfl_fac_list; /* 0x0c8 */
+ uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
+ uint64_t mcic; /* 0x0e8 */
+ uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
+ uint32_t external_damage_code; /* 0x0f4 */
+ uint64_t failing_storage_address; /* 0x0f8 */
+ uint8_t pad6[0x110 - 0x100]; /* 0x100 */
+ uint64_t per_breaking_event_addr; /* 0x110 */
+ uint8_t pad7[0x120 - 0x118]; /* 0x118 */
+ PSW restart_old_psw; /* 0x120 */
+ PSW external_old_psw; /* 0x130 */
+ PSW svc_old_psw; /* 0x140 */
+ PSW program_old_psw; /* 0x150 */
+ PSW mcck_old_psw; /* 0x160 */
+ PSW io_old_psw; /* 0x170 */
+ uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
+ PSW restart_new_psw; /* 0x1a0 */
+ PSW external_new_psw; /* 0x1b0 */
+ PSW svc_new_psw; /* 0x1c0 */
+ PSW program_new_psw; /* 0x1d0 */
+ PSW mcck_new_psw; /* 0x1e0 */
+ PSW io_new_psw; /* 0x1f0 */
+} __attribute__((packed, aligned(8192))) LowCore;
+
+extern LowCore const *lowcore;
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 06/19] s390-bios: Map low core memory
2019-04-25 13:21 ` [Qemu-devel] [PULL 06/19] s390-bios: Map low core memory Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Create a new header for basic architecture specific definitions and add a
mapping of low core memory. This mapping will be used by the real dasd boot
process.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-7-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 2 +
pc-bios/s390-ccw/s390-arch.h | 90 ++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+)
create mode 100644 pc-bios/s390-ccw/s390-arch.h
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 10f04c69068f..e403b5f733e4 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -9,6 +9,7 @@
*/
#include "libc.h"
+#include "s390-arch.h"
#include "s390-ccw.h"
#include "cio.h"
#include "virtio.h"
@@ -19,6 +20,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static bool have_iplb;
+LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */
#define LOADPARM_PROMPT "PROMPT "
#define LOADPARM_EMPTY " "
diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h
new file mode 100644
index 000000000000..5e92c7a27d53
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-arch.h
@@ -0,0 +1,90 @@
+/*
+ * S390 Basic Architecture
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 S390_ARCH_H
+#define S390_ARCH_H
+
+typedef struct PSW {
+ uint64_t mask;
+ uint64_t addr;
+} __attribute__ ((aligned(8))) PSW;
+_Static_assert(sizeof(struct PSW) == 16, "PSW size incorrect");
+
+/* Older PSW format used by LPSW instruction */
+typedef struct PSWLegacy {
+ uint32_t mask;
+ uint32_t addr;
+} __attribute__ ((aligned(8))) PSWLegacy;
+_Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect");
+
+/* s390 psw bit masks */
+#define PSW_MASK_IOINT 0x0200000000000000ULL
+#define PSW_MASK_WAIT 0x0002000000000000ULL
+#define PSW_MASK_EAMODE 0x0000000100000000ULL
+#define PSW_MASK_BAMODE 0x0000000080000000ULL
+#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE)
+
+/* Low core mapping */
+typedef struct LowCore {
+ /* prefix area: defined by architecture */
+ PSWLegacy ipl_psw; /* 0x000 */
+ uint32_t ccw1[2]; /* 0x008 */
+ uint32_t ccw2[2]; /* 0x010 */
+ uint8_t pad1[0x80 - 0x18]; /* 0x018 */
+ uint32_t ext_params; /* 0x080 */
+ uint16_t cpu_addr; /* 0x084 */
+ uint16_t ext_int_code; /* 0x086 */
+ uint16_t svc_ilen; /* 0x088 */
+ uint16_t svc_code; /* 0x08a */
+ uint16_t pgm_ilen; /* 0x08c */
+ uint16_t pgm_code; /* 0x08e */
+ uint32_t data_exc_code; /* 0x090 */
+ uint16_t mon_class_num; /* 0x094 */
+ uint16_t per_perc_atmid; /* 0x096 */
+ uint64_t per_address; /* 0x098 */
+ uint8_t exc_access_id; /* 0x0a0 */
+ uint8_t per_access_id; /* 0x0a1 */
+ uint8_t op_access_id; /* 0x0a2 */
+ uint8_t ar_access_id; /* 0x0a3 */
+ uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
+ uint64_t trans_exc_code; /* 0x0a8 */
+ uint64_t monitor_code; /* 0x0b0 */
+ uint16_t subchannel_id; /* 0x0b8 */
+ uint16_t subchannel_nr; /* 0x0ba */
+ uint32_t io_int_parm; /* 0x0bc */
+ uint32_t io_int_word; /* 0x0c0 */
+ uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
+ uint32_t stfl_fac_list; /* 0x0c8 */
+ uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
+ uint64_t mcic; /* 0x0e8 */
+ uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
+ uint32_t external_damage_code; /* 0x0f4 */
+ uint64_t failing_storage_address; /* 0x0f8 */
+ uint8_t pad6[0x110 - 0x100]; /* 0x100 */
+ uint64_t per_breaking_event_addr; /* 0x110 */
+ uint8_t pad7[0x120 - 0x118]; /* 0x118 */
+ PSW restart_old_psw; /* 0x120 */
+ PSW external_old_psw; /* 0x130 */
+ PSW svc_old_psw; /* 0x140 */
+ PSW program_old_psw; /* 0x150 */
+ PSW mcck_old_psw; /* 0x160 */
+ PSW io_old_psw; /* 0x170 */
+ uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
+ PSW restart_new_psw; /* 0x1a0 */
+ PSW external_new_psw; /* 0x1b0 */
+ PSW svc_new_psw; /* 0x1c0 */
+ PSW program_new_psw; /* 0x1d0 */
+ PSW mcck_new_psw; /* 0x1e0 */
+ PSW io_new_psw; /* 0x1f0 */
+} __attribute__((packed, aligned(8192))) LowCore;
+
+extern LowCore const *lowcore;
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 07/19] s390-bios: ptr2u32 and u32toptr
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (6 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 06/19] s390-bios: Map low core memory Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 08/19] s390-bios: Support for running format-0/1 channel programs Cornelia Huck
` (12 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Introduce inline functions to convert between pointers and unsigned 32-bit
ints. These are used to hide the ugliness required to avoid compiler
warnings.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-8-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/helper.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 pc-bios/s390-ccw/helper.h
diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h
new file mode 100644
index 000000000000..78d5bc74421b
--- /dev/null
+++ b/pc-bios/s390-ccw/helper.h
@@ -0,0 +1,31 @@
+/*
+ * Helper Functions
+ *
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.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 S390_CCW_HELPER_H
+#define S390_CCW_HELPER_H
+
+#include "s390-ccw.h"
+
+/* Avoids compiler warnings when casting a pointer to a u32 */
+static inline uint32_t ptr2u32(void *ptr)
+{
+ IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large");
+ return (uint32_t)(uint64_t)ptr;
+}
+
+/* Avoids compiler warnings when casting a u32 to a pointer */
+static inline void *u32toptr(uint32_t n)
+{
+ return (void *)(uint64_t)n;
+}
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 07/19] s390-bios: ptr2u32 and u32toptr
2019-04-25 13:21 ` [Qemu-devel] [PULL 07/19] s390-bios: ptr2u32 and u32toptr Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Introduce inline functions to convert between pointers and unsigned 32-bit
ints. These are used to hide the ugliness required to avoid compiler
warnings.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-8-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/helper.h | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 pc-bios/s390-ccw/helper.h
diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h
new file mode 100644
index 000000000000..78d5bc74421b
--- /dev/null
+++ b/pc-bios/s390-ccw/helper.h
@@ -0,0 +1,31 @@
+/*
+ * Helper Functions
+ *
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.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 S390_CCW_HELPER_H
+#define S390_CCW_HELPER_H
+
+#include "s390-ccw.h"
+
+/* Avoids compiler warnings when casting a pointer to a u32 */
+static inline uint32_t ptr2u32(void *ptr)
+{
+ IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large");
+ return (uint32_t)(uint64_t)ptr;
+}
+
+/* Avoids compiler warnings when casting a u32 to a pointer */
+static inline void *u32toptr(uint32_t n)
+{
+ return (void *)(uint64_t)n;
+}
+
+#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 08/19] s390-bios: Support for running format-0/1 channel programs
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (7 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 07/19] s390-bios: ptr2u32 and u32toptr Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 09/19] s390-bios: cio error handling Cornelia Huck
` (11 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Introduce a library function for executing format-0 and format-1
channel programs and waiting for their completion before continuing
execution.
Add cu_type() to channel io library. This will be used to query control
unit type which is used to determine if we are booting a virtio device or a
real dasd device.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Message-Id: <1554388475-18329-9-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/cio.h | 130 +++++++++++++++++++++++++++++++-
pc-bios/s390-ccw/s390-ccw.h | 1 +
pc-bios/s390-ccw/start.S | 29 ++++++++
4 files changed, 301 insertions(+), 3 deletions(-)
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
index 87c6b34e88af..c43e50b00b8e 100644
--- a/pc-bios/s390-ccw/cio.c
+++ b/pc-bios/s390-ccw/cio.c
@@ -13,10 +13,14 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "helper.h"
#include "cio.h"
static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
+
int enable_mss_facility(void)
{
int ret;
@@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid)
schib.pmcw.ena = 1;
msch(schid, &schib);
}
+
+uint16_t cu_type(SubChannelId schid)
+{
+ Ccw1 sense_id_ccw;
+ SenseId sense_data;
+
+ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID;
+ sense_id_ccw.cda = ptr2u32(&sense_data);
+ sense_id_ccw.count = sizeof(sense_data);
+ sense_id_ccw.flags |= CCW_FLAG_SLI;
+
+ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
+ panic("Failed to run SenseID CCw\n");
+ }
+
+ return sense_data.cu_type;
+}
+
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size)
+{
+ Ccw1 senseCcw;
+ Irb irb;
+
+ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE;
+ senseCcw.cda = ptr2u32(sense_data);
+ senseCcw.count = data_size;
+
+ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
+}
+
+static bool irb_error(Irb *irb)
+{
+ if (irb->scsw.cstat) {
+ return true;
+ }
+ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
+}
+
+/*
+ * Handles executing ssch, tsch and returns the irb obtained from tsch.
+ * Returns 0 on success, -1 if unexpected status pending and we need to retry,
+ * otherwise returns condition code from ssch/tsch for error cases.
+ */
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
+{
+ CmdOrb orb = {};
+ int rc;
+
+ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
+
+ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
+ if (fmt == 0) {
+ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
+ }
+
+ orb.fmt = fmt;
+ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */
+ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */
+ orb.lpm = 0xFF; /* All paths allowed */
+ orb.cpa = ccw_addr;
+
+ rc = ssch(schid, &orb);
+ if (rc == 1 || rc == 2) {
+ /* Subchannel status pending or busy. Eat status and ask for retry. */
+ tsch(schid, irb);
+ return -1;
+ }
+ if (rc) {
+ print_int("ssch failed with cc=", rc);
+ return rc;
+ }
+
+ consume_io_int();
+
+ /* collect status */
+ rc = tsch(schid, irb);
+ if (rc) {
+ print_int("tsch failed with cc=", rc);
+ }
+
+ return rc;
+}
+
+/*
+ * Executes a channel program at a given subchannel. The request to run the
+ * channel program is sent to the subchannel, we then wait for the interrupt
+ * signaling completion of the I/O operation(s) performed by the channel
+ * program. Lastly we verify that the i/o operation completed without error and
+ * that the interrupt we received was for the subchannel used to run the
+ * channel program.
+ *
+ * Note: This function assumes it is running in an environment where no other
+ * cpus are generating or receiving I/O interrupts. So either run it in a
+ * single-cpu environment or make sure all other cpus are not doing I/O and
+ * have I/O interrupts masked off. We also assume that only one device is
+ * active (generating i/o interrupts).
+ *
+ * Returns non-zero on error.
+ */
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
+{
+ Irb irb = {};
+ SenseDataEckdDasd sd;
+ int rc, retries = 0;
+
+ while (true) {
+ rc = __do_cio(schid, ccw_addr, fmt, &irb);
+
+ if (rc == -1) {
+ retries++;
+ continue;
+ }
+ if (rc) {
+ /* ssch/tsch error. Message already reported by __do_cio */
+ break;
+ }
+
+ if (!irb_error(&irb)) {
+ break;
+ }
+
+ /*
+ * Unexpected unit check, or interface-control-check. Use sense to
+ * clear (unit check only) then retry.
+ */
+ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
+ if (unit_check(&irb)) {
+ basic_sense(schid, cutype, &sd, sizeof(sd));
+ }
+ retries++;
+ continue;
+ }
+
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 218fd96ea3a6..1637e32070f3 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -70,9 +70,46 @@ struct scsw {
__u16 count;
} __attribute__ ((packed));
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
-#define SCSW_FCTL_HALT_FUNC 0x2000
+/* Function Control */
#define SCSW_FCTL_START_FUNC 0x4000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+
+/* Activity Control */
+#define SCSW_ACTL_RESUME_PEND 0x0800
+#define SCSW_ACTL_START_PEND 0x0400
+#define SCSW_ACTL_HALT_PEND 0x0200
+#define SCSW_ACTL_CLEAR_PEND 0x0100
+#define SCSW_ACTL_CH_ACTIVE 0x0080
+#define SCSW_ACTL_DEV_ACTIVE 0x0040
+#define SCSW_ACTL_SUSPENDED 0x0020
+
+/* Status Control */
+#define SCSW_SCTL_ALERT 0x0010
+#define SCSW_SCTL_INTERMED 0x0008
+#define SCSW_SCTL_PRIMARY 0x0004
+#define SCSW_SCTL_SECONDARY 0x0002
+#define SCSW_SCTL_STATUS_PEND 0x0001
+
+/* SCSW Device Status Flags */
+#define SCSW_DSTAT_ATTN 0x80
+#define SCSW_DSTAT_STATMOD 0x40
+#define SCSW_DSTAT_CUEND 0x20
+#define SCSW_DSTAT_BUSY 0x10
+#define SCSW_DSTAT_CHEND 0x08
+#define SCSW_DSTAT_DEVEND 0x04
+#define SCSW_DSTAT_UCHK 0x02
+#define SCSW_DSTAT_UEXCP 0x01
+
+/* SCSW Subchannel Status Flags */
+#define SCSW_CSTAT_PCINT 0x80
+#define SCSW_CSTAT_BADLEN 0x40
+#define SCSW_CSTAT_PROGCHK 0x20
+#define SCSW_CSTAT_PROTCHK 0x10
+#define SCSW_CSTAT_CHDCHK 0x08
+#define SCSW_CSTAT_CHCCHK 0x04
+#define SCSW_CSTAT_ICCHK 0x02
+#define SCSW_CSTAT_CHAINCHK 0x01
/*
* subchannel information block
@@ -127,7 +164,23 @@ struct tpi_info {
__u32 reserved4:12;
} __attribute__ ((packed, aligned(4)));
-/* channel command word (type 1) */
+/* channel command word (format 0) */
+typedef struct ccw0 {
+ __u8 cmd_code;
+ __u32 cda:24;
+ __u32 chainData:1;
+ __u32 chain:1;
+ __u32 sli:1;
+ __u32 skip:1;
+ __u32 pci:1;
+ __u32 ida:1;
+ __u32 suspend:1;
+ __u32 mida:1;
+ __u8 reserved;
+ __u16 count;
+} __attribute__ ((packed, aligned(8))) Ccw0;
+
+/* channel command word (format 1) */
typedef struct ccw1 {
__u8 cmd_code;
__u8 flags;
@@ -135,6 +188,10 @@ typedef struct ccw1 {
__u32 cda;
} __attribute__ ((packed, aligned(8))) Ccw1;
+/* do_cio() CCW formats */
+#define CCW_FMT0 0x00
+#define CCW_FMT1 0x01
+
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
#define CCW_FLAG_SLI 0x20
@@ -190,6 +247,11 @@ struct ciw {
__u16 count;
};
+#define CU_TYPE_UNKNOWN 0x0000
+#define CU_TYPE_DASD_2107 0x2107
+#define CU_TYPE_VIRTIO 0x3832
+#define CU_TYPE_DASD_3990 0x3990
+
/*
* sense-id response buffer layout
*/
@@ -205,6 +267,64 @@ typedef struct senseid {
struct ciw ciw[62];
} __attribute__ ((packed, aligned(4))) SenseId;
+/*
+ * architected values for first sense byte - common_status. Bits 0-5 of this
+ * field are common to all device types.
+ */
+#define SNS_STAT0_CMD_REJECT 0x80
+#define SNS_STAT0_INTERVENTION_REQ 0x40
+#define SNS_STAT0_BUS_OUT_CHECK 0x20
+#define SNS_STAT0_EQUIPMENT_CHECK 0x10
+#define SNS_STAT0_DATA_CHECK 0x08
+#define SNS_STAT0_OVERRUN 0x04
+#define SNS_STAT0_INCOMPL_DOMAIN 0x01
+
+/* ECKD DASD status[0] byte */
+#define SNS_STAT1_PERM_ERR 0x80
+#define SNS_STAT1_INV_TRACK_FORMAT 0x40
+#define SNS_STAT1_EOC 0x20
+#define SNS_STAT1_MESSAGE_TO_OPER 0x10
+#define SNS_STAT1_NO_REC_FOUND 0x08
+#define SNS_STAT1_FILE_PROTECTED 0x04
+#define SNS_STAT1_WRITE_INHIBITED 0x02
+#define SNS_STAT1_IMPRECISE_END 0x01
+
+/* ECKD DASD status[1] byte */
+#define SNS_STAT2_REQ_INH_WRITE 0x80
+#define SNS_STAT2_CORRECTABLE 0x40
+#define SNS_STAT2_FIRST_LOG_ERR 0x20
+#define SNS_STAT2_ENV_DATA_PRESENT 0x10
+#define SNS_STAT2_IMPRECISE_END 0x04
+
+/* ECKD DASD 24-byte Sense fmt_msg codes */
+#define SENSE24_FMT_PROG_SYS 0x0
+#define SENSE24_FMT_EQUIPMENT 0x2
+#define SENSE24_FMT_CONTROLLER 0x3
+#define SENSE24_FMT_MISC 0xF
+
+/* basic sense response buffer layout */
+typedef struct SenseDataEckdDasd {
+ uint8_t common_status;
+ uint8_t status[2];
+ uint8_t res_count;
+ uint8_t phys_drive_id;
+ uint8_t low_cyl_addr;
+ uint8_t head_high_cyl_addr;
+ uint8_t fmt_msg;
+ uint64_t fmt_dependent_info[2];
+ uint8_t reserved;
+ uint8_t program_action_code;
+ uint16_t config_info;
+ uint8_t mcode_hicyl;
+ uint8_t cyl_head_addr[3];
+} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
+
+#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
+#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
+
+#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
+#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
+
/* interruption response block */
typedef struct irb {
struct scsw scsw;
@@ -215,6 +335,10 @@ typedef struct irb {
int enable_mss_facility(void);
void enable_subchannel(SubChannelId schid);
+uint16_t cu_type(SubChannelId schid);
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size);
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
/*
* Some S390 specific IO instructions as inline
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index b39ee5d32314..11bce7d73c85 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -52,6 +52,7 @@ typedef unsigned long long __u64;
/* start.s */
void disabled_wait(void);
void consume_sclp_int(void);
+void consume_io_int(void);
/* main.c */
void panic(const char *string);
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
index 5c22cb0849d3..aa8fceb19da2 100644
--- a/pc-bios/s390-ccw/start.S
+++ b/pc-bios/s390-ccw/start.S
@@ -71,6 +71,26 @@ consume_sclp_int:
larl %r1, enabled_wait_psw
lpswe 0(%r1)
+/*
+ * void consume_io_int(void)
+ *
+ * eats one I/O interrupt
+ */
+ .globl consume_io_int
+consume_io_int:
+ /* enable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ oi 4(%r15), 0xff
+ lctlg %c6,%c6,0(%r15)
+ /* prepare i/o call handler */
+ larl %r1, io_new_code
+ stg %r1, 0x1f8
+ larl %r1, io_new_mask
+ mvc 0x1f0(8),0(%r1)
+ /* load enabled wait PSW */
+ larl %r1, enabled_wait_psw
+ lpswe 0(%r1)
+
external_new_code:
/* disable service interrupts in cr0 */
stctg %c0,%c0,0(%r15)
@@ -78,6 +98,13 @@ external_new_code:
lctlg %c0,%c0,0(%r15)
br %r14
+io_new_code:
+ /* disable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ ni 4(%r15), 0x00
+ lctlg %c6,%c6,0(%r15)
+ br %r14
+
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000
@@ -85,3 +112,5 @@ enabled_wait_psw:
.quad 0x0302000180000000,0x0000000000000000
external_new_mask:
.quad 0x0000000180000000
+io_new_mask:
+ .quad 0x0000000180000000
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 08/19] s390-bios: Support for running format-0/1 channel programs
2019-04-25 13:21 ` [Qemu-devel] [PULL 08/19] s390-bios: Support for running format-0/1 channel programs Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Introduce a library function for executing format-0 and format-1
channel programs and waiting for their completion before continuing
execution.
Add cu_type() to channel io library. This will be used to query control
unit type which is used to determine if we are booting a virtio device or a
real dasd device.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Message-Id: <1554388475-18329-9-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/cio.h | 130 +++++++++++++++++++++++++++++++-
pc-bios/s390-ccw/s390-ccw.h | 1 +
pc-bios/s390-ccw/start.S | 29 ++++++++
4 files changed, 301 insertions(+), 3 deletions(-)
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
index 87c6b34e88af..c43e50b00b8e 100644
--- a/pc-bios/s390-ccw/cio.c
+++ b/pc-bios/s390-ccw/cio.c
@@ -13,10 +13,14 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "helper.h"
#include "cio.h"
static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
+
int enable_mss_facility(void)
{
int ret;
@@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid)
schib.pmcw.ena = 1;
msch(schid, &schib);
}
+
+uint16_t cu_type(SubChannelId schid)
+{
+ Ccw1 sense_id_ccw;
+ SenseId sense_data;
+
+ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID;
+ sense_id_ccw.cda = ptr2u32(&sense_data);
+ sense_id_ccw.count = sizeof(sense_data);
+ sense_id_ccw.flags |= CCW_FLAG_SLI;
+
+ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
+ panic("Failed to run SenseID CCw\n");
+ }
+
+ return sense_data.cu_type;
+}
+
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size)
+{
+ Ccw1 senseCcw;
+ Irb irb;
+
+ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE;
+ senseCcw.cda = ptr2u32(sense_data);
+ senseCcw.count = data_size;
+
+ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
+}
+
+static bool irb_error(Irb *irb)
+{
+ if (irb->scsw.cstat) {
+ return true;
+ }
+ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
+}
+
+/*
+ * Handles executing ssch, tsch and returns the irb obtained from tsch.
+ * Returns 0 on success, -1 if unexpected status pending and we need to retry,
+ * otherwise returns condition code from ssch/tsch for error cases.
+ */
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
+{
+ CmdOrb orb = {};
+ int rc;
+
+ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
+
+ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
+ if (fmt == 0) {
+ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
+ }
+
+ orb.fmt = fmt;
+ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */
+ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */
+ orb.lpm = 0xFF; /* All paths allowed */
+ orb.cpa = ccw_addr;
+
+ rc = ssch(schid, &orb);
+ if (rc == 1 || rc == 2) {
+ /* Subchannel status pending or busy. Eat status and ask for retry. */
+ tsch(schid, irb);
+ return -1;
+ }
+ if (rc) {
+ print_int("ssch failed with cc=", rc);
+ return rc;
+ }
+
+ consume_io_int();
+
+ /* collect status */
+ rc = tsch(schid, irb);
+ if (rc) {
+ print_int("tsch failed with cc=", rc);
+ }
+
+ return rc;
+}
+
+/*
+ * Executes a channel program at a given subchannel. The request to run the
+ * channel program is sent to the subchannel, we then wait for the interrupt
+ * signaling completion of the I/O operation(s) performed by the channel
+ * program. Lastly we verify that the i/o operation completed without error and
+ * that the interrupt we received was for the subchannel used to run the
+ * channel program.
+ *
+ * Note: This function assumes it is running in an environment where no other
+ * cpus are generating or receiving I/O interrupts. So either run it in a
+ * single-cpu environment or make sure all other cpus are not doing I/O and
+ * have I/O interrupts masked off. We also assume that only one device is
+ * active (generating i/o interrupts).
+ *
+ * Returns non-zero on error.
+ */
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
+{
+ Irb irb = {};
+ SenseDataEckdDasd sd;
+ int rc, retries = 0;
+
+ while (true) {
+ rc = __do_cio(schid, ccw_addr, fmt, &irb);
+
+ if (rc == -1) {
+ retries++;
+ continue;
+ }
+ if (rc) {
+ /* ssch/tsch error. Message already reported by __do_cio */
+ break;
+ }
+
+ if (!irb_error(&irb)) {
+ break;
+ }
+
+ /*
+ * Unexpected unit check, or interface-control-check. Use sense to
+ * clear (unit check only) then retry.
+ */
+ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
+ if (unit_check(&irb)) {
+ basic_sense(schid, cutype, &sd, sizeof(sd));
+ }
+ retries++;
+ continue;
+ }
+
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 218fd96ea3a6..1637e32070f3 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -70,9 +70,46 @@ struct scsw {
__u16 count;
} __attribute__ ((packed));
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
-#define SCSW_FCTL_HALT_FUNC 0x2000
+/* Function Control */
#define SCSW_FCTL_START_FUNC 0x4000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+
+/* Activity Control */
+#define SCSW_ACTL_RESUME_PEND 0x0800
+#define SCSW_ACTL_START_PEND 0x0400
+#define SCSW_ACTL_HALT_PEND 0x0200
+#define SCSW_ACTL_CLEAR_PEND 0x0100
+#define SCSW_ACTL_CH_ACTIVE 0x0080
+#define SCSW_ACTL_DEV_ACTIVE 0x0040
+#define SCSW_ACTL_SUSPENDED 0x0020
+
+/* Status Control */
+#define SCSW_SCTL_ALERT 0x0010
+#define SCSW_SCTL_INTERMED 0x0008
+#define SCSW_SCTL_PRIMARY 0x0004
+#define SCSW_SCTL_SECONDARY 0x0002
+#define SCSW_SCTL_STATUS_PEND 0x0001
+
+/* SCSW Device Status Flags */
+#define SCSW_DSTAT_ATTN 0x80
+#define SCSW_DSTAT_STATMOD 0x40
+#define SCSW_DSTAT_CUEND 0x20
+#define SCSW_DSTAT_BUSY 0x10
+#define SCSW_DSTAT_CHEND 0x08
+#define SCSW_DSTAT_DEVEND 0x04
+#define SCSW_DSTAT_UCHK 0x02
+#define SCSW_DSTAT_UEXCP 0x01
+
+/* SCSW Subchannel Status Flags */
+#define SCSW_CSTAT_PCINT 0x80
+#define SCSW_CSTAT_BADLEN 0x40
+#define SCSW_CSTAT_PROGCHK 0x20
+#define SCSW_CSTAT_PROTCHK 0x10
+#define SCSW_CSTAT_CHDCHK 0x08
+#define SCSW_CSTAT_CHCCHK 0x04
+#define SCSW_CSTAT_ICCHK 0x02
+#define SCSW_CSTAT_CHAINCHK 0x01
/*
* subchannel information block
@@ -127,7 +164,23 @@ struct tpi_info {
__u32 reserved4:12;
} __attribute__ ((packed, aligned(4)));
-/* channel command word (type 1) */
+/* channel command word (format 0) */
+typedef struct ccw0 {
+ __u8 cmd_code;
+ __u32 cda:24;
+ __u32 chainData:1;
+ __u32 chain:1;
+ __u32 sli:1;
+ __u32 skip:1;
+ __u32 pci:1;
+ __u32 ida:1;
+ __u32 suspend:1;
+ __u32 mida:1;
+ __u8 reserved;
+ __u16 count;
+} __attribute__ ((packed, aligned(8))) Ccw0;
+
+/* channel command word (format 1) */
typedef struct ccw1 {
__u8 cmd_code;
__u8 flags;
@@ -135,6 +188,10 @@ typedef struct ccw1 {
__u32 cda;
} __attribute__ ((packed, aligned(8))) Ccw1;
+/* do_cio() CCW formats */
+#define CCW_FMT0 0x00
+#define CCW_FMT1 0x01
+
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
#define CCW_FLAG_SLI 0x20
@@ -190,6 +247,11 @@ struct ciw {
__u16 count;
};
+#define CU_TYPE_UNKNOWN 0x0000
+#define CU_TYPE_DASD_2107 0x2107
+#define CU_TYPE_VIRTIO 0x3832
+#define CU_TYPE_DASD_3990 0x3990
+
/*
* sense-id response buffer layout
*/
@@ -205,6 +267,64 @@ typedef struct senseid {
struct ciw ciw[62];
} __attribute__ ((packed, aligned(4))) SenseId;
+/*
+ * architected values for first sense byte - common_status. Bits 0-5 of this
+ * field are common to all device types.
+ */
+#define SNS_STAT0_CMD_REJECT 0x80
+#define SNS_STAT0_INTERVENTION_REQ 0x40
+#define SNS_STAT0_BUS_OUT_CHECK 0x20
+#define SNS_STAT0_EQUIPMENT_CHECK 0x10
+#define SNS_STAT0_DATA_CHECK 0x08
+#define SNS_STAT0_OVERRUN 0x04
+#define SNS_STAT0_INCOMPL_DOMAIN 0x01
+
+/* ECKD DASD status[0] byte */
+#define SNS_STAT1_PERM_ERR 0x80
+#define SNS_STAT1_INV_TRACK_FORMAT 0x40
+#define SNS_STAT1_EOC 0x20
+#define SNS_STAT1_MESSAGE_TO_OPER 0x10
+#define SNS_STAT1_NO_REC_FOUND 0x08
+#define SNS_STAT1_FILE_PROTECTED 0x04
+#define SNS_STAT1_WRITE_INHIBITED 0x02
+#define SNS_STAT1_IMPRECISE_END 0x01
+
+/* ECKD DASD status[1] byte */
+#define SNS_STAT2_REQ_INH_WRITE 0x80
+#define SNS_STAT2_CORRECTABLE 0x40
+#define SNS_STAT2_FIRST_LOG_ERR 0x20
+#define SNS_STAT2_ENV_DATA_PRESENT 0x10
+#define SNS_STAT2_IMPRECISE_END 0x04
+
+/* ECKD DASD 24-byte Sense fmt_msg codes */
+#define SENSE24_FMT_PROG_SYS 0x0
+#define SENSE24_FMT_EQUIPMENT 0x2
+#define SENSE24_FMT_CONTROLLER 0x3
+#define SENSE24_FMT_MISC 0xF
+
+/* basic sense response buffer layout */
+typedef struct SenseDataEckdDasd {
+ uint8_t common_status;
+ uint8_t status[2];
+ uint8_t res_count;
+ uint8_t phys_drive_id;
+ uint8_t low_cyl_addr;
+ uint8_t head_high_cyl_addr;
+ uint8_t fmt_msg;
+ uint64_t fmt_dependent_info[2];
+ uint8_t reserved;
+ uint8_t program_action_code;
+ uint16_t config_info;
+ uint8_t mcode_hicyl;
+ uint8_t cyl_head_addr[3];
+} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
+
+#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
+#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
+
+#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
+#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
+
/* interruption response block */
typedef struct irb {
struct scsw scsw;
@@ -215,6 +335,10 @@ typedef struct irb {
int enable_mss_facility(void);
void enable_subchannel(SubChannelId schid);
+uint16_t cu_type(SubChannelId schid);
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size);
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
/*
* Some S390 specific IO instructions as inline
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index b39ee5d32314..11bce7d73c85 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -52,6 +52,7 @@ typedef unsigned long long __u64;
/* start.s */
void disabled_wait(void);
void consume_sclp_int(void);
+void consume_io_int(void);
/* main.c */
void panic(const char *string);
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
index 5c22cb0849d3..aa8fceb19da2 100644
--- a/pc-bios/s390-ccw/start.S
+++ b/pc-bios/s390-ccw/start.S
@@ -71,6 +71,26 @@ consume_sclp_int:
larl %r1, enabled_wait_psw
lpswe 0(%r1)
+/*
+ * void consume_io_int(void)
+ *
+ * eats one I/O interrupt
+ */
+ .globl consume_io_int
+consume_io_int:
+ /* enable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ oi 4(%r15), 0xff
+ lctlg %c6,%c6,0(%r15)
+ /* prepare i/o call handler */
+ larl %r1, io_new_code
+ stg %r1, 0x1f8
+ larl %r1, io_new_mask
+ mvc 0x1f0(8),0(%r1)
+ /* load enabled wait PSW */
+ larl %r1, enabled_wait_psw
+ lpswe 0(%r1)
+
external_new_code:
/* disable service interrupts in cr0 */
stctg %c0,%c0,0(%r15)
@@ -78,6 +98,13 @@ external_new_code:
lctlg %c0,%c0,0(%r15)
br %r14
+io_new_code:
+ /* disable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ ni 4(%r15), 0x00
+ lctlg %c6,%c6,0(%r15)
+ br %r14
+
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000
@@ -85,3 +112,5 @@ enabled_wait_psw:
.quad 0x0302000180000000,0x0000000000000000
external_new_mask:
.quad 0x0000000180000000
+io_new_mask:
+ .quad 0x0000000180000000
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 09/19] s390-bios: cio error handling
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (8 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 08/19] s390-bios: Support for running format-0/1 channel programs Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 10/19] s390-bios: Extend find_dev() for non-virtio devices Cornelia Huck
` (10 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add verbose error output for when unexpected i/o errors happen. This eases the
burden of debugging and reporting i/o errors. No error information is printed
in the success case, here is an example of what is output on error:
cio device error
ssid : 0x0000000000000000
cssid : 0x0000000000000000
sch_no: 0x0000000000000000
Interrupt Response Block Data:
Function Ctrl : [Start]
Activity Ctrl : [Start-Pending]
Status Ctrl : [Alert] [Primary] [Secondary] [Status-Pending]
Device Status : [Unit-Check]
Channel Status :
cpa=: 0x000000007f8d6038
prev_ccw=: 0x0000000000000000
this_ccw=: 0x0000000000000000
Eckd Dasd Sense Data (fmt 32-bytes):
Sense Condition Flags :
Residual Count =: 0x0000000000000000
Phys Drive ID =: 0x000000000000009e
low cyl address =: 0x0000000000000000
head addr & hi cyl =: 0x0000000000000000
format/message =: 0x0000000000000008
fmt-dependent[0-7] =: 0x0000000000000004
fmt-dependent[8-15]=: 0xe561282305082fff
prog action code =: 0x0000000000000016
Configuration info =: 0x00000000000040e0
mcode / hi-cyl =: 0x0000000000000000
cyl & head addr [0]=: 0x0000000000000000
cyl & head addr [1]=: 0x0000000000000000
cyl & head addr [2]=: 0x0000000000000000
The Sense Data section is currently only printed for ECKD DASD.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-10-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.c | 235 ++++++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/libc.h | 11 ++
2 files changed, 246 insertions(+)
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
index c43e50b00b8e..339ec5fbe7a4 100644
--- a/pc-bios/s390-ccw/cio.c
+++ b/pc-bios/s390-ccw/cio.c
@@ -85,6 +85,228 @@ static bool irb_error(Irb *irb)
return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
}
+static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd)
+{
+ char msgline[512];
+
+ if (sd->config_info & 0x8000) {
+ sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n");
+ } else {
+ sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n");
+ }
+
+ strcat(msgline, " Sense Condition Flags :");
+ if (sd->common_status & SNS_STAT0_CMD_REJECT) {
+ strcat(msgline, " [Cmd-Reject]");
+ }
+ if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) {
+ strcat(msgline, " [Intervention-Required]");
+ }
+ if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) {
+ strcat(msgline, " [Bus-Out-Parity-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) {
+ strcat(msgline, " [Equipment-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_DATA_CHECK) {
+ strcat(msgline, " [Data-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_OVERRUN) {
+ strcat(msgline, " [Overrun]");
+ }
+ if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) {
+ strcat(msgline, " [Incomplete-Domain]");
+ }
+
+ if (sd->status[0] & SNS_STAT1_PERM_ERR) {
+ strcat(msgline, " [Permanent-Error]");
+ }
+ if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) {
+ strcat(msgline, " [Invalid-Track-Fmt]");
+ }
+ if (sd->status[0] & SNS_STAT1_EOC) {
+ strcat(msgline, " [End-of-Cyl]");
+ }
+ if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) {
+ strcat(msgline, " [Operator-Msg]");
+ }
+ if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) {
+ strcat(msgline, " [No-Record-Found]");
+ }
+ if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) {
+ strcat(msgline, " [File-Protected]");
+ }
+ if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) {
+ strcat(msgline, " [Write-Inhibited]");
+ }
+ if (sd->status[0] & SNS_STAT1_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-Ending]");
+ }
+
+ if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) {
+ strcat(msgline, " [Req-Inhibit-Write]");
+ }
+ if (sd->status[1] & SNS_STAT2_CORRECTABLE) {
+ strcat(msgline, " [Correctable-Data-Check]");
+ }
+ if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) {
+ strcat(msgline, " [First-Error-Log]");
+ }
+ if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) {
+ strcat(msgline, " [Env-Data-Present]");
+ }
+ if (sd->status[1] & SNS_STAT2_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-End]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" Residual Count =", sd->res_count);
+ print_int(" Phys Drive ID =", sd->phys_drive_id);
+ print_int(" low cyl address =", sd->low_cyl_addr);
+ print_int(" head addr & hi cyl =", sd->head_high_cyl_addr);
+ print_int(" format/message =", sd->fmt_msg);
+ print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]);
+ print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]);
+ print_int(" prog action code =", sd->program_action_code);
+ print_int(" Configuration info =", sd->config_info);
+ print_int(" mcode / hi-cyl =", sd->mcode_hicyl);
+ print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]);
+ print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]);
+ print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]);
+}
+
+static void print_irb_err(Irb *irb)
+{
+ uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa);
+ uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8);
+ char msgline[256];
+
+ sclp_print("Interrupt Response Block Data:\n");
+
+ strcat(msgline, " Function Ctrl :");
+ if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) {
+ strcat(msgline, " [Start]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
+ strcat(msgline, " [Halt]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
+ strcat(msgline, " [Clear]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Activity Ctrl :");
+ if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) {
+ strcat(msgline, " [Resume-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) {
+ strcat(msgline, " [Start-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) {
+ strcat(msgline, " [Halt-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) {
+ strcat(msgline, " [Clear-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) {
+ strcat(msgline, " [Channel-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) {
+ strcat(msgline, " [Device-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) {
+ strcat(msgline, " [Suspended]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Status Ctrl :");
+ if (irb->scsw.ctrl & SCSW_SCTL_ALERT) {
+ strcat(msgline, " [Alert]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) {
+ strcat(msgline, " [Intermediate]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) {
+ strcat(msgline, " [Primary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) {
+ strcat(msgline, " [Secondary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) {
+ strcat(msgline, " [Status-Pending]");
+ }
+
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Device Status :");
+ if (irb->scsw.dstat & SCSW_DSTAT_ATTN) {
+ strcat(msgline, " [Attention]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) {
+ strcat(msgline, " [Status-Modifier]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CUEND) {
+ strcat(msgline, " [Ctrl-Unit-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_BUSY) {
+ strcat(msgline, " [Busy]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CHEND) {
+ strcat(msgline, " [Channel-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) {
+ strcat(msgline, " [Device-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UCHK) {
+ strcat(msgline, " [Unit-Check]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) {
+ strcat(msgline, " [Unit-Exception]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Channel Status :");
+ if (irb->scsw.cstat & SCSW_CSTAT_PCINT) {
+ strcat(msgline, " [Program-Ctrl-Interruption]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) {
+ strcat(msgline, " [Incorrect-Length]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) {
+ strcat(msgline, " [Program-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) {
+ strcat(msgline, " [Protection-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) {
+ strcat(msgline, " [Channel-Data-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) {
+ strcat(msgline, " [Channel-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) {
+ strcat(msgline, " [Interface-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) {
+ strcat(msgline, " [Chaining-Check]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" cpa=", irb->scsw.cpa);
+ print_int(" prev_ccw=", prev_ccw);
+ print_int(" this_ccw=", this_ccw);
+}
+
/*
* Handles executing ssch, tsch and returns the irb obtained from tsch.
* Returns 0 on success, -1 if unexpected status pending and we need to retry,
@@ -180,6 +402,19 @@ int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
continue;
}
+ sclp_print("cio device error\n");
+ print_int(" ssid ", schid.ssid);
+ print_int(" cssid ", schid.cssid);
+ print_int(" sch_no", schid.sch_no);
+ print_int(" ctrl-unit type", cutype);
+ sclp_print("\n");
+ print_irb_err(&irb);
+ if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 ||
+ cutype == CU_TYPE_UNKNOWN) {
+ if (!basic_sense(schid, cutype, &sd, sizeof(sd))) {
+ print_eckd_dasd_sense_data(&sd);
+ }
+ }
rc = -1;
break;
}
diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h
index 818517ff5d44..bcdc45732dd8 100644
--- a/pc-bios/s390-ccw/libc.h
+++ b/pc-bios/s390-ccw/libc.h
@@ -67,6 +67,17 @@ static inline size_t strlen(const char *str)
return i;
}
+static inline char *strcat(char *dest, const char *src)
+{
+ int i;
+ char *dest_end = dest + strlen(dest);
+
+ for (i = 0; i <= strlen(src); i++) {
+ dest_end[i] = src[i];
+ }
+ return dest;
+}
+
static inline int isdigit(int c)
{
return (c >= '0') && (c <= '9');
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 09/19] s390-bios: cio error handling
2019-04-25 13:21 ` [Qemu-devel] [PULL 09/19] s390-bios: cio error handling Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Add verbose error output for when unexpected i/o errors happen. This eases the
burden of debugging and reporting i/o errors. No error information is printed
in the success case, here is an example of what is output on error:
cio device error
ssid : 0x0000000000000000
cssid : 0x0000000000000000
sch_no: 0x0000000000000000
Interrupt Response Block Data:
Function Ctrl : [Start]
Activity Ctrl : [Start-Pending]
Status Ctrl : [Alert] [Primary] [Secondary] [Status-Pending]
Device Status : [Unit-Check]
Channel Status :
cpa=: 0x000000007f8d6038
prev_ccw=: 0x0000000000000000
this_ccw=: 0x0000000000000000
Eckd Dasd Sense Data (fmt 32-bytes):
Sense Condition Flags :
Residual Count =: 0x0000000000000000
Phys Drive ID =: 0x000000000000009e
low cyl address =: 0x0000000000000000
head addr & hi cyl =: 0x0000000000000000
format/message =: 0x0000000000000008
fmt-dependent[0-7] =: 0x0000000000000004
fmt-dependent[8-15]=: 0xe561282305082fff
prog action code =: 0x0000000000000016
Configuration info =: 0x00000000000040e0
mcode / hi-cyl =: 0x0000000000000000
cyl & head addr [0]=: 0x0000000000000000
cyl & head addr [1]=: 0x0000000000000000
cyl & head addr [2]=: 0x0000000000000000
The Sense Data section is currently only printed for ECKD DASD.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-10-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.c | 235 ++++++++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/libc.h | 11 ++
2 files changed, 246 insertions(+)
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
index c43e50b00b8e..339ec5fbe7a4 100644
--- a/pc-bios/s390-ccw/cio.c
+++ b/pc-bios/s390-ccw/cio.c
@@ -85,6 +85,228 @@ static bool irb_error(Irb *irb)
return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
}
+static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd)
+{
+ char msgline[512];
+
+ if (sd->config_info & 0x8000) {
+ sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n");
+ } else {
+ sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n");
+ }
+
+ strcat(msgline, " Sense Condition Flags :");
+ if (sd->common_status & SNS_STAT0_CMD_REJECT) {
+ strcat(msgline, " [Cmd-Reject]");
+ }
+ if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) {
+ strcat(msgline, " [Intervention-Required]");
+ }
+ if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) {
+ strcat(msgline, " [Bus-Out-Parity-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) {
+ strcat(msgline, " [Equipment-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_DATA_CHECK) {
+ strcat(msgline, " [Data-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_OVERRUN) {
+ strcat(msgline, " [Overrun]");
+ }
+ if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) {
+ strcat(msgline, " [Incomplete-Domain]");
+ }
+
+ if (sd->status[0] & SNS_STAT1_PERM_ERR) {
+ strcat(msgline, " [Permanent-Error]");
+ }
+ if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) {
+ strcat(msgline, " [Invalid-Track-Fmt]");
+ }
+ if (sd->status[0] & SNS_STAT1_EOC) {
+ strcat(msgline, " [End-of-Cyl]");
+ }
+ if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) {
+ strcat(msgline, " [Operator-Msg]");
+ }
+ if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) {
+ strcat(msgline, " [No-Record-Found]");
+ }
+ if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) {
+ strcat(msgline, " [File-Protected]");
+ }
+ if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) {
+ strcat(msgline, " [Write-Inhibited]");
+ }
+ if (sd->status[0] & SNS_STAT1_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-Ending]");
+ }
+
+ if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) {
+ strcat(msgline, " [Req-Inhibit-Write]");
+ }
+ if (sd->status[1] & SNS_STAT2_CORRECTABLE) {
+ strcat(msgline, " [Correctable-Data-Check]");
+ }
+ if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) {
+ strcat(msgline, " [First-Error-Log]");
+ }
+ if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) {
+ strcat(msgline, " [Env-Data-Present]");
+ }
+ if (sd->status[1] & SNS_STAT2_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-End]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" Residual Count =", sd->res_count);
+ print_int(" Phys Drive ID =", sd->phys_drive_id);
+ print_int(" low cyl address =", sd->low_cyl_addr);
+ print_int(" head addr & hi cyl =", sd->head_high_cyl_addr);
+ print_int(" format/message =", sd->fmt_msg);
+ print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]);
+ print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]);
+ print_int(" prog action code =", sd->program_action_code);
+ print_int(" Configuration info =", sd->config_info);
+ print_int(" mcode / hi-cyl =", sd->mcode_hicyl);
+ print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]);
+ print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]);
+ print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]);
+}
+
+static void print_irb_err(Irb *irb)
+{
+ uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa);
+ uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8);
+ char msgline[256];
+
+ sclp_print("Interrupt Response Block Data:\n");
+
+ strcat(msgline, " Function Ctrl :");
+ if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) {
+ strcat(msgline, " [Start]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
+ strcat(msgline, " [Halt]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
+ strcat(msgline, " [Clear]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Activity Ctrl :");
+ if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) {
+ strcat(msgline, " [Resume-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) {
+ strcat(msgline, " [Start-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) {
+ strcat(msgline, " [Halt-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) {
+ strcat(msgline, " [Clear-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) {
+ strcat(msgline, " [Channel-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) {
+ strcat(msgline, " [Device-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) {
+ strcat(msgline, " [Suspended]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Status Ctrl :");
+ if (irb->scsw.ctrl & SCSW_SCTL_ALERT) {
+ strcat(msgline, " [Alert]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) {
+ strcat(msgline, " [Intermediate]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) {
+ strcat(msgline, " [Primary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) {
+ strcat(msgline, " [Secondary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) {
+ strcat(msgline, " [Status-Pending]");
+ }
+
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Device Status :");
+ if (irb->scsw.dstat & SCSW_DSTAT_ATTN) {
+ strcat(msgline, " [Attention]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) {
+ strcat(msgline, " [Status-Modifier]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CUEND) {
+ strcat(msgline, " [Ctrl-Unit-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_BUSY) {
+ strcat(msgline, " [Busy]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CHEND) {
+ strcat(msgline, " [Channel-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) {
+ strcat(msgline, " [Device-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UCHK) {
+ strcat(msgline, " [Unit-Check]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) {
+ strcat(msgline, " [Unit-Exception]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Channel Status :");
+ if (irb->scsw.cstat & SCSW_CSTAT_PCINT) {
+ strcat(msgline, " [Program-Ctrl-Interruption]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) {
+ strcat(msgline, " [Incorrect-Length]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) {
+ strcat(msgline, " [Program-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) {
+ strcat(msgline, " [Protection-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) {
+ strcat(msgline, " [Channel-Data-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) {
+ strcat(msgline, " [Channel-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) {
+ strcat(msgline, " [Interface-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) {
+ strcat(msgline, " [Chaining-Check]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" cpa=", irb->scsw.cpa);
+ print_int(" prev_ccw=", prev_ccw);
+ print_int(" this_ccw=", this_ccw);
+}
+
/*
* Handles executing ssch, tsch and returns the irb obtained from tsch.
* Returns 0 on success, -1 if unexpected status pending and we need to retry,
@@ -180,6 +402,19 @@ int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
continue;
}
+ sclp_print("cio device error\n");
+ print_int(" ssid ", schid.ssid);
+ print_int(" cssid ", schid.cssid);
+ print_int(" sch_no", schid.sch_no);
+ print_int(" ctrl-unit type", cutype);
+ sclp_print("\n");
+ print_irb_err(&irb);
+ if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 ||
+ cutype == CU_TYPE_UNKNOWN) {
+ if (!basic_sense(schid, cutype, &sd, sizeof(sd))) {
+ print_eckd_dasd_sense_data(&sd);
+ }
+ }
rc = -1;
break;
}
diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h
index 818517ff5d44..bcdc45732dd8 100644
--- a/pc-bios/s390-ccw/libc.h
+++ b/pc-bios/s390-ccw/libc.h
@@ -67,6 +67,17 @@ static inline size_t strlen(const char *str)
return i;
}
+static inline char *strcat(char *dest, const char *src)
+{
+ int i;
+ char *dest_end = dest + strlen(dest);
+
+ for (i = 0; i <= strlen(src); i++) {
+ dest_end[i] = src[i];
+ }
+ return dest;
+}
+
static inline int isdigit(int c)
{
return (c >= '0') && (c <= '9');
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 10/19] s390-bios: Extend find_dev() for non-virtio devices
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (9 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 09/19] s390-bios: cio error handling Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 11/19] s390-bios: Factor finding boot device out of virtio code path Cornelia Huck
` (9 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
We need a method for finding the subchannel of a dasd device. Let's
modify find_dev to handle this since it mostly does what we need. Up to
this point find_dev has been specific to only virtio devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-11-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e403b5f733e4..d04ea8972a0c 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -52,6 +52,12 @@ unsigned int get_loadparm_index(void)
return atoui(loadparm_str);
}
+/*
+ * Find the subchannel connected to the given device (dev_no) and fill in the
+ * subchannel information block (schib) with the connected subchannel's info.
+ * NOTE: The global variable blk_schid is updated to contain the subchannel
+ * information.
+ */
static bool find_dev(Schib *schib, int dev_no)
{
int i, r;
@@ -65,15 +71,15 @@ static bool find_dev(Schib *schib, int dev_no)
if (!schib->pmcw.dnv) {
continue;
}
- if (!virtio_is_supported(blk_schid)) {
- continue;
- }
+
/* Skip net devices since no IPLB is created and therefore no
- * no network bootloader has been loaded
+ * network bootloader has been loaded
*/
- if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
+ if (virtio_is_supported(blk_schid) &&
+ virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
continue;
}
+
if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
return true;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 10/19] s390-bios: Extend find_dev() for non-virtio devices
2019-04-25 13:21 ` [Qemu-devel] [PULL 10/19] s390-bios: Extend find_dev() for non-virtio devices Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
We need a method for finding the subchannel of a dasd device. Let's
modify find_dev to handle this since it mostly does what we need. Up to
this point find_dev has been specific to only virtio devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-11-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index e403b5f733e4..d04ea8972a0c 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -52,6 +52,12 @@ unsigned int get_loadparm_index(void)
return atoui(loadparm_str);
}
+/*
+ * Find the subchannel connected to the given device (dev_no) and fill in the
+ * subchannel information block (schib) with the connected subchannel's info.
+ * NOTE: The global variable blk_schid is updated to contain the subchannel
+ * information.
+ */
static bool find_dev(Schib *schib, int dev_no)
{
int i, r;
@@ -65,15 +71,15 @@ static bool find_dev(Schib *schib, int dev_no)
if (!schib->pmcw.dnv) {
continue;
}
- if (!virtio_is_supported(blk_schid)) {
- continue;
- }
+
/* Skip net devices since no IPLB is created and therefore no
- * no network bootloader has been loaded
+ * network bootloader has been loaded
*/
- if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
+ if (virtio_is_supported(blk_schid) &&
+ virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
continue;
}
+
if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
return true;
}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 11/19] s390-bios: Factor finding boot device out of virtio code path
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (10 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 10/19] s390-bios: Extend find_dev() for non-virtio devices Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 12/19] s390-bios: Refactor virtio to run channel programs via cio Cornelia Huck
` (8 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Make a new routine find_boot_device to locate the boot device for all
cases, not just virtio.
The error message for the case where no boot device has been specified
and a suitable boot device cannot be auto detected was specific to
virtio devices. We update this message to remove virtio specific wording.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-12-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 85 ++++++++++++++++++++++------------------
tests/boot-serial-test.c | 2 +-
2 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index d04ea8972a0c..d3a161c68546 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -58,17 +58,18 @@ unsigned int get_loadparm_index(void)
* NOTE: The global variable blk_schid is updated to contain the subchannel
* information.
*/
-static bool find_dev(Schib *schib, int dev_no)
+static bool find_subch(int dev_no)
{
+ Schib schib;
int i, r;
for (i = 0; i < 0x10000; i++) {
blk_schid.sch_no = i;
- r = stsch_err(blk_schid, schib);
+ r = stsch_err(blk_schid, &schib);
if ((r == 3) || (r == -EIO)) {
break;
}
- if (!schib->pmcw.dnv) {
+ if (!schib.pmcw.dnv) {
continue;
}
@@ -80,7 +81,7 @@ static bool find_dev(Schib *schib, int dev_no)
continue;
}
- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
+ if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) {
return true;
}
}
@@ -136,56 +137,61 @@ static void boot_setup(void)
have_iplb = store_iplb(&iplb);
}
-static void virtio_setup(void)
+static void find_boot_device(void)
{
- Schib schib;
- int ssid;
- bool found = false;
- uint16_t dev_no;
VDev *vdev = virtio_get_device();
- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
-
- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+ int ssid;
+ bool found;
- if (have_iplb) {
- switch (iplb.pbt) {
- case S390_IPL_TYPE_CCW:
- dev_no = iplb.ccw.devno;
- debug_print_int("device no. ", dev_no);
- blk_schid.ssid = iplb.ccw.ssid & 0x3;
- debug_print_int("ssid ", blk_schid.ssid);
- found = find_dev(&schib, dev_no);
- break;
- case S390_IPL_TYPE_QEMU_SCSI:
- vdev->scsi_device_selected = true;
- vdev->selected_scsi_device.channel = iplb.scsi.channel;
- vdev->selected_scsi_device.target = iplb.scsi.target;
- vdev->selected_scsi_device.lun = iplb.scsi.lun;
- blk_schid.ssid = iplb.scsi.ssid & 0x3;
- found = find_dev(&schib, iplb.scsi.devno);
- break;
- default:
- panic("List-directed IPL not supported yet!\n");
- }
- menu_setup();
- } else {
+ if (!have_iplb) {
for (ssid = 0; ssid < 0x3; ssid++) {
blk_schid.ssid = ssid;
- found = find_dev(&schib, -1);
+ found = find_subch(-1);
if (found) {
- break;
+ return;
}
}
+ panic("Could not find a suitable boot device (none specified)\n");
+ }
+
+ switch (iplb.pbt) {
+ case S390_IPL_TYPE_CCW:
+ debug_print_int("device no. ", iplb.ccw.devno);
+ blk_schid.ssid = iplb.ccw.ssid & 0x3;
+ debug_print_int("ssid ", blk_schid.ssid);
+ found = find_subch(iplb.ccw.devno);
+ break;
+ case S390_IPL_TYPE_QEMU_SCSI:
+ vdev->scsi_device_selected = true;
+ vdev->selected_scsi_device.channel = iplb.scsi.channel;
+ vdev->selected_scsi_device.target = iplb.scsi.target;
+ vdev->selected_scsi_device.lun = iplb.scsi.lun;
+ blk_schid.ssid = iplb.scsi.ssid & 0x3;
+ found = find_subch(iplb.scsi.devno);
+ break;
+ default:
+ panic("List-directed IPL not supported yet!\n");
}
- IPL_assert(found, "No virtio device found");
+ IPL_assert(found, "Boot device not found\n");
+}
+
+static void virtio_setup(void)
+{
+ VDev *vdev = virtio_get_device();
+ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
+
+ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+
+ if (have_iplb) {
+ menu_setup();
+ }
if (virtio_get_device_type() == VIRTIO_ID_NET) {
sclp_print("Network boot device detected\n");
vdev->netboot_start_addr = qipl.netboot_start_addr;
} else {
virtio_blk_setup_device(blk_schid);
-
IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
}
}
@@ -195,8 +201,9 @@ int main(void)
sclp_setup();
css_setup();
boot_setup();
- virtio_setup();
+ find_boot_device();
+ virtio_setup();
zipl_load(); /* no return */
panic("Failed to load OS from hard disk\n");
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index c591748aaf00..24852d4c7d0b 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -114,7 +114,7 @@ static testdef_t tests[] = {
{ "sparc", "SS-4", "", "MB86904" },
{ "sparc", "SS-600MP", "", "TMS390Z55" },
{ "sparc64", "sun4u", "", "UltraSPARC" },
- { "s390x", "s390-ccw-virtio", "", "virtio device" },
+ { "s390x", "s390-ccw-virtio", "", "device" },
{ "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 },
{ "microblaze", "petalogix-s3adsp1800", "", "TT",
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 11/19] s390-bios: Factor finding boot device out of virtio code path
2019-04-25 13:21 ` [Qemu-devel] [PULL 11/19] s390-bios: Factor finding boot device out of virtio code path Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Make a new routine find_boot_device to locate the boot device for all
cases, not just virtio.
The error message for the case where no boot device has been specified
and a suitable boot device cannot be auto detected was specific to
virtio devices. We update this message to remove virtio specific wording.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-12-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 85 ++++++++++++++++++++++------------------
tests/boot-serial-test.c | 2 +-
2 files changed, 47 insertions(+), 40 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index d04ea8972a0c..d3a161c68546 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -58,17 +58,18 @@ unsigned int get_loadparm_index(void)
* NOTE: The global variable blk_schid is updated to contain the subchannel
* information.
*/
-static bool find_dev(Schib *schib, int dev_no)
+static bool find_subch(int dev_no)
{
+ Schib schib;
int i, r;
for (i = 0; i < 0x10000; i++) {
blk_schid.sch_no = i;
- r = stsch_err(blk_schid, schib);
+ r = stsch_err(blk_schid, &schib);
if ((r == 3) || (r == -EIO)) {
break;
}
- if (!schib->pmcw.dnv) {
+ if (!schib.pmcw.dnv) {
continue;
}
@@ -80,7 +81,7 @@ static bool find_dev(Schib *schib, int dev_no)
continue;
}
- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
+ if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) {
return true;
}
}
@@ -136,56 +137,61 @@ static void boot_setup(void)
have_iplb = store_iplb(&iplb);
}
-static void virtio_setup(void)
+static void find_boot_device(void)
{
- Schib schib;
- int ssid;
- bool found = false;
- uint16_t dev_no;
VDev *vdev = virtio_get_device();
- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
-
- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+ int ssid;
+ bool found;
- if (have_iplb) {
- switch (iplb.pbt) {
- case S390_IPL_TYPE_CCW:
- dev_no = iplb.ccw.devno;
- debug_print_int("device no. ", dev_no);
- blk_schid.ssid = iplb.ccw.ssid & 0x3;
- debug_print_int("ssid ", blk_schid.ssid);
- found = find_dev(&schib, dev_no);
- break;
- case S390_IPL_TYPE_QEMU_SCSI:
- vdev->scsi_device_selected = true;
- vdev->selected_scsi_device.channel = iplb.scsi.channel;
- vdev->selected_scsi_device.target = iplb.scsi.target;
- vdev->selected_scsi_device.lun = iplb.scsi.lun;
- blk_schid.ssid = iplb.scsi.ssid & 0x3;
- found = find_dev(&schib, iplb.scsi.devno);
- break;
- default:
- panic("List-directed IPL not supported yet!\n");
- }
- menu_setup();
- } else {
+ if (!have_iplb) {
for (ssid = 0; ssid < 0x3; ssid++) {
blk_schid.ssid = ssid;
- found = find_dev(&schib, -1);
+ found = find_subch(-1);
if (found) {
- break;
+ return;
}
}
+ panic("Could not find a suitable boot device (none specified)\n");
+ }
+
+ switch (iplb.pbt) {
+ case S390_IPL_TYPE_CCW:
+ debug_print_int("device no. ", iplb.ccw.devno);
+ blk_schid.ssid = iplb.ccw.ssid & 0x3;
+ debug_print_int("ssid ", blk_schid.ssid);
+ found = find_subch(iplb.ccw.devno);
+ break;
+ case S390_IPL_TYPE_QEMU_SCSI:
+ vdev->scsi_device_selected = true;
+ vdev->selected_scsi_device.channel = iplb.scsi.channel;
+ vdev->selected_scsi_device.target = iplb.scsi.target;
+ vdev->selected_scsi_device.lun = iplb.scsi.lun;
+ blk_schid.ssid = iplb.scsi.ssid & 0x3;
+ found = find_subch(iplb.scsi.devno);
+ break;
+ default:
+ panic("List-directed IPL not supported yet!\n");
}
- IPL_assert(found, "No virtio device found");
+ IPL_assert(found, "Boot device not found\n");
+}
+
+static void virtio_setup(void)
+{
+ VDev *vdev = virtio_get_device();
+ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
+
+ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+
+ if (have_iplb) {
+ menu_setup();
+ }
if (virtio_get_device_type() == VIRTIO_ID_NET) {
sclp_print("Network boot device detected\n");
vdev->netboot_start_addr = qipl.netboot_start_addr;
} else {
virtio_blk_setup_device(blk_schid);
-
IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
}
}
@@ -195,8 +201,9 @@ int main(void)
sclp_setup();
css_setup();
boot_setup();
- virtio_setup();
+ find_boot_device();
+ virtio_setup();
zipl_load(); /* no return */
panic("Failed to load OS from hard disk\n");
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index c591748aaf00..24852d4c7d0b 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -114,7 +114,7 @@ static testdef_t tests[] = {
{ "sparc", "SS-4", "", "MB86904" },
{ "sparc", "SS-600MP", "", "TMS390Z55" },
{ "sparc64", "sun4u", "", "UltraSPARC" },
- { "s390x", "s390-ccw-virtio", "", "virtio device" },
+ { "s390x", "s390-ccw-virtio", "", "device" },
{ "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 },
{ "microblaze", "petalogix-s3adsp1800", "", "TT",
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 12/19] s390-bios: Refactor virtio to run channel programs via cio
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (11 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 11/19] s390-bios: Factor finding boot device out of virtio code path Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 13/19] s390-bios: Use control unit type to determine boot method Cornelia Huck
` (7 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Now that we have a Channel I/O library let's modify virtio boot code to
make use of it for running channel programs.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-13-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/virtio.c | 57 +++++++++++++++++++--------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index aa9da7253fb2..35278eaee13d 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -14,6 +14,7 @@
#include "virtio.h"
#include "virtio-scsi.h"
#include "bswap.h"
+#include "helper.h"
#define VRING_WAIT_REPLY_TIMEOUT 30
@@ -89,33 +90,20 @@ int drain_irqs(SubChannelId schid)
}
}
-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
+static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli)
{
Ccw1 ccw = {};
- CmdOrb orb = {};
- int r;
-
- enable_subchannel(vdev->schid);
-
- /* start subchannel command */
- orb.fmt = 1;
- orb.cpa = (u32)(long)&ccw;
- orb.lpm = 0x80;
ccw.cmd_code = cmd;
ccw.cda = (long)ptr;
ccw.count = len;
- r = ssch(vdev->schid, &orb);
- /*
- * XXX Wait until device is done processing the CCW. For now we can
- * assume that a simple tsch will have finished the CCW processing,
- * but the architecture allows for asynchronous operation
- */
- if (!r) {
- r = drain_irqs(vdev->schid);
+ if (sli) {
+ ccw.flags |= CCW_FLAG_SLI;
}
- return r;
+
+ enable_subchannel(vdev->schid);
+ return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1);
}
static void vring_init(VRing *vr, VqInfo *info)
@@ -257,7 +245,7 @@ void virtio_setup_ccw(VDev *vdev)
vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */
vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0);
+ run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false);
switch (vdev->senseid.cu_model) {
case VIRTIO_ID_NET:
@@ -278,18 +266,19 @@ void virtio_setup_ccw(VDev *vdev)
default:
panic("Unsupported virtio device\n");
}
- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0,
- "Could not get block device configuration");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0,
+ "Could not get block device configuration");
/* Feature negotiation */
for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) {
feats.features = 0;
feats.index = i;
- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not get features bits");
vdev->guest_features[i] &= bswap32(feats.features);
feats.features = bswap32(vdev->guest_features[i]);
- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not set features bits");
}
@@ -306,16 +295,17 @@ void virtio_setup_ccw(VDev *vdev)
};
IPL_assert(
- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0,
+ run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0,
"Could not get block device VQ configuration");
info.num = config.num;
vring_init(&vdev->vrings[i], &info);
vdev->vrings[i].schid = vdev->schid;
- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0,
- "Cannot set VQ info");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0,
+ "Cannot set VQ info");
}
IPL_assert(
- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0,
+ run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0,
"Could not write status to host");
}
@@ -323,8 +313,15 @@ bool virtio_is_supported(SubChannelId schid)
{
vdev.schid = schid;
memset(&vdev.senseid, 0, sizeof(vdev.senseid));
- /* run sense id command */
- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) {
+
+ /*
+ * Run sense id command.
+ * The size of the senseid data differs between devices (notably,
+ * between virtio devices and dasds), so specify the largest possible
+ * size and suppress the incorrect length indication for smaller sizes.
+ */
+ if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid),
+ true)) {
return false;
}
if (vdev.senseid.cu_type == 0x3832) {
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 12/19] s390-bios: Refactor virtio to run channel programs via cio
2019-04-25 13:21 ` [Qemu-devel] [PULL 12/19] s390-bios: Refactor virtio to run channel programs via cio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Now that we have a Channel I/O library let's modify virtio boot code to
make use of it for running channel programs.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-13-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/virtio.c | 57 +++++++++++++++++++--------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index aa9da7253fb2..35278eaee13d 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -14,6 +14,7 @@
#include "virtio.h"
#include "virtio-scsi.h"
#include "bswap.h"
+#include "helper.h"
#define VRING_WAIT_REPLY_TIMEOUT 30
@@ -89,33 +90,20 @@ int drain_irqs(SubChannelId schid)
}
}
-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
+static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli)
{
Ccw1 ccw = {};
- CmdOrb orb = {};
- int r;
-
- enable_subchannel(vdev->schid);
-
- /* start subchannel command */
- orb.fmt = 1;
- orb.cpa = (u32)(long)&ccw;
- orb.lpm = 0x80;
ccw.cmd_code = cmd;
ccw.cda = (long)ptr;
ccw.count = len;
- r = ssch(vdev->schid, &orb);
- /*
- * XXX Wait until device is done processing the CCW. For now we can
- * assume that a simple tsch will have finished the CCW processing,
- * but the architecture allows for asynchronous operation
- */
- if (!r) {
- r = drain_irqs(vdev->schid);
+ if (sli) {
+ ccw.flags |= CCW_FLAG_SLI;
}
- return r;
+
+ enable_subchannel(vdev->schid);
+ return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1);
}
static void vring_init(VRing *vr, VqInfo *info)
@@ -257,7 +245,7 @@ void virtio_setup_ccw(VDev *vdev)
vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */
vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0);
+ run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false);
switch (vdev->senseid.cu_model) {
case VIRTIO_ID_NET:
@@ -278,18 +266,19 @@ void virtio_setup_ccw(VDev *vdev)
default:
panic("Unsupported virtio device\n");
}
- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0,
- "Could not get block device configuration");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0,
+ "Could not get block device configuration");
/* Feature negotiation */
for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) {
feats.features = 0;
feats.index = i;
- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not get features bits");
vdev->guest_features[i] &= bswap32(feats.features);
feats.features = bswap32(vdev->guest_features[i]);
- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not set features bits");
}
@@ -306,16 +295,17 @@ void virtio_setup_ccw(VDev *vdev)
};
IPL_assert(
- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0,
+ run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0,
"Could not get block device VQ configuration");
info.num = config.num;
vring_init(&vdev->vrings[i], &info);
vdev->vrings[i].schid = vdev->schid;
- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0,
- "Cannot set VQ info");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0,
+ "Cannot set VQ info");
}
IPL_assert(
- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0,
+ run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0,
"Could not write status to host");
}
@@ -323,8 +313,15 @@ bool virtio_is_supported(SubChannelId schid)
{
vdev.schid = schid;
memset(&vdev.senseid, 0, sizeof(vdev.senseid));
- /* run sense id command */
- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) {
+
+ /*
+ * Run sense id command.
+ * The size of the senseid data differs between devices (notably,
+ * between virtio devices and dasds), so specify the largest possible
+ * size and suppress the incorrect length indication for smaller sizes.
+ */
+ if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid),
+ true)) {
return false;
}
if (vdev.senseid.cu_type == 0x3832) {
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 13/19] s390-bios: Use control unit type to determine boot method
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (12 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 12/19] s390-bios: Refactor virtio to run channel programs via cio Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 14/19] s390-bios: Add channel command codes/structs needed for dasd-ipl Cornelia Huck
` (6 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
The boot method is different depending on which device type we are
booting from. Let's examine the control unit type to determine if we're
a virtio device. We'll eventually add a case to check for a real dasd device
here as well.
Since we have to call enable_subchannel() in main now, might as well
remove that call from virtio.c : run_ccw(). This requires adding some
additional enable_subchannel calls to not break calls to
virtio_is_supported().
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-14-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 16 ++++++++++++++--
pc-bios/s390-ccw/netmain.c | 1 +
pc-bios/s390-ccw/virtio.c | 1 -
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index d3a161c68546..57a10138c65d 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -76,6 +76,7 @@ static bool find_subch(int dev_no)
/* Skip net devices since no IPLB is created and therefore no
* network bootloader has been loaded
*/
+ enable_subchannel(blk_schid);
if (virtio_is_supported(blk_schid) &&
virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
continue;
@@ -198,13 +199,24 @@ static void virtio_setup(void)
int main(void)
{
+ uint16_t cutype;
+
sclp_setup();
css_setup();
boot_setup();
find_boot_device();
+ enable_subchannel(blk_schid);
- virtio_setup();
- zipl_load(); /* no return */
+ cutype = cu_type(blk_schid);
+ switch (cutype) {
+ case CU_TYPE_VIRTIO:
+ virtio_setup();
+ zipl_load(); /* no return */
+ break;
+ default:
+ print_int("Attempting to boot from unexpected device type", cutype);
+ panic("");
+ }
panic("Failed to load OS from hard disk\n");
return 0; /* make compiler happy */
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 5189c0fc39e5..f3542cb2cf11 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -476,6 +476,7 @@ static bool find_net_dev(Schib *schib, int dev_no)
if (!schib->pmcw.dnv) {
continue;
}
+ enable_subchannel(net_schid);
if (!virtio_is_supported(net_schid)) {
continue;
}
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 35278eaee13d..fb40ca982853 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -102,7 +102,6 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli)
ccw.flags |= CCW_FLAG_SLI;
}
- enable_subchannel(vdev->schid);
return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1);
}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 13/19] s390-bios: Use control unit type to determine boot method
2019-04-25 13:21 ` [Qemu-devel] [PULL 13/19] s390-bios: Use control unit type to determine boot method Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
The boot method is different depending on which device type we are
booting from. Let's examine the control unit type to determine if we're
a virtio device. We'll eventually add a case to check for a real dasd device
here as well.
Since we have to call enable_subchannel() in main now, might as well
remove that call from virtio.c : run_ccw(). This requires adding some
additional enable_subchannel calls to not break calls to
virtio_is_supported().
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-14-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 16 ++++++++++++++--
pc-bios/s390-ccw/netmain.c | 1 +
pc-bios/s390-ccw/virtio.c | 1 -
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index d3a161c68546..57a10138c65d 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -76,6 +76,7 @@ static bool find_subch(int dev_no)
/* Skip net devices since no IPLB is created and therefore no
* network bootloader has been loaded
*/
+ enable_subchannel(blk_schid);
if (virtio_is_supported(blk_schid) &&
virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
continue;
@@ -198,13 +199,24 @@ static void virtio_setup(void)
int main(void)
{
+ uint16_t cutype;
+
sclp_setup();
css_setup();
boot_setup();
find_boot_device();
+ enable_subchannel(blk_schid);
- virtio_setup();
- zipl_load(); /* no return */
+ cutype = cu_type(blk_schid);
+ switch (cutype) {
+ case CU_TYPE_VIRTIO:
+ virtio_setup();
+ zipl_load(); /* no return */
+ break;
+ default:
+ print_int("Attempting to boot from unexpected device type", cutype);
+ panic("");
+ }
panic("Failed to load OS from hard disk\n");
return 0; /* make compiler happy */
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 5189c0fc39e5..f3542cb2cf11 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -476,6 +476,7 @@ static bool find_net_dev(Schib *schib, int dev_no)
if (!schib->pmcw.dnv) {
continue;
}
+ enable_subchannel(net_schid);
if (!virtio_is_supported(net_schid)) {
continue;
}
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 35278eaee13d..fb40ca982853 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -102,7 +102,6 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli)
ccw.flags |= CCW_FLAG_SLI;
}
- enable_subchannel(vdev->schid);
return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1);
}
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 14/19] s390-bios: Add channel command codes/structs needed for dasd-ipl
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (13 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 13/19] s390-bios: Use control unit type to determine boot method Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 15/19] s390-bios: Support booting from real dasd device Cornelia Huck
` (5 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
The dasd IPL procedure needs to execute a few previously unused
channel commands. Let's define them and their associated data
structures.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-15-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 1637e32070f3..aaa432deddb9 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -200,11 +200,14 @@ typedef struct ccw1 {
#define CCW_FLAG_IDA 0x04
#define CCW_FLAG_SUSPEND 0x02
+/* Common CCW commands */
+#define CCW_CMD_READ_IPL 0x02
#define CCW_CMD_NOOP 0x03
#define CCW_CMD_BASIC_SENSE 0x04
#define CCW_CMD_TIC 0x08
#define CCW_CMD_SENSE_ID 0xe4
+/* Virtio CCW commands */
#define CCW_CMD_SET_VQ 0x13
#define CCW_CMD_VDEV_RESET 0x33
#define CCW_CMD_READ_FEAT 0x12
@@ -216,6 +219,12 @@ typedef struct ccw1 {
#define CCW_CMD_SET_CONF_IND 0x53
#define CCW_CMD_READ_VQ_CONF 0x32
+/* DASD CCW commands */
+#define CCW_CMD_DASD_READ 0x06
+#define CCW_CMD_DASD_SEEK 0x07
+#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31
+#define CCW_CMD_DASD_READ_MT 0x86
+
/*
* Command-mode operation request block
*/
@@ -333,6 +342,20 @@ typedef struct irb {
__u32 emw[8];
} __attribute__ ((packed, aligned(4))) Irb;
+/* Used for SEEK ccw commands */
+typedef struct CcwSeekData {
+ uint16_t reserved;
+ uint16_t cyl;
+ uint16_t head;
+} __attribute__((packed)) CcwSeekData;
+
+/* Used for SEARCH ID ccw commands */
+typedef struct CcwSearchIdData {
+ uint16_t cyl;
+ uint16_t head;
+ uint8_t record;
+} __attribute__((packed)) CcwSearchIdData;
+
int enable_mss_facility(void);
void enable_subchannel(SubChannelId schid);
uint16_t cu_type(SubChannelId schid);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 14/19] s390-bios: Add channel command codes/structs needed for dasd-ipl
2019-04-25 13:21 ` [Qemu-devel] [PULL 14/19] s390-bios: Add channel command codes/structs needed for dasd-ipl Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
The dasd IPL procedure needs to execute a few previously unused
channel commands. Let's define them and their associated data
structures.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <1554388475-18329-15-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/cio.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 1637e32070f3..aaa432deddb9 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -200,11 +200,14 @@ typedef struct ccw1 {
#define CCW_FLAG_IDA 0x04
#define CCW_FLAG_SUSPEND 0x02
+/* Common CCW commands */
+#define CCW_CMD_READ_IPL 0x02
#define CCW_CMD_NOOP 0x03
#define CCW_CMD_BASIC_SENSE 0x04
#define CCW_CMD_TIC 0x08
#define CCW_CMD_SENSE_ID 0xe4
+/* Virtio CCW commands */
#define CCW_CMD_SET_VQ 0x13
#define CCW_CMD_VDEV_RESET 0x33
#define CCW_CMD_READ_FEAT 0x12
@@ -216,6 +219,12 @@ typedef struct ccw1 {
#define CCW_CMD_SET_CONF_IND 0x53
#define CCW_CMD_READ_VQ_CONF 0x32
+/* DASD CCW commands */
+#define CCW_CMD_DASD_READ 0x06
+#define CCW_CMD_DASD_SEEK 0x07
+#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31
+#define CCW_CMD_DASD_READ_MT 0x86
+
/*
* Command-mode operation request block
*/
@@ -333,6 +342,20 @@ typedef struct irb {
__u32 emw[8];
} __attribute__ ((packed, aligned(4))) Irb;
+/* Used for SEEK ccw commands */
+typedef struct CcwSeekData {
+ uint16_t reserved;
+ uint16_t cyl;
+ uint16_t head;
+} __attribute__((packed)) CcwSeekData;
+
+/* Used for SEARCH ID ccw commands */
+typedef struct CcwSearchIdData {
+ uint16_t cyl;
+ uint16_t head;
+ uint8_t record;
+} __attribute__((packed)) CcwSearchIdData;
+
int enable_mss_facility(void);
void enable_subchannel(SubChannelId schid);
uint16_t cu_type(SubChannelId schid);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 15/19] s390-bios: Support booting from real dasd device
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (14 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 14/19] s390-bios: Add channel command codes/structs needed for dasd-ipl Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 16/19] s390-bios: Use control unit type to find bootable devices Cornelia Huck
` (4 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Allows guest to boot from a vfio configured real dasd device.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-16-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 1 +
docs/devel/s390-dasd-ipl.txt | 133 ++++++++++++++++++++
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/dasd-ipl.c | 235 +++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/dasd-ipl.h | 16 +++
pc-bios/s390-ccw/main.c | 5 +
pc-bios/s390-ccw/s390-arch.h | 13 ++
7 files changed, 404 insertions(+), 1 deletion(-)
create mode 100644 docs/devel/s390-dasd-ipl.txt
create mode 100644 pc-bios/s390-ccw/dasd-ipl.c
create mode 100644 pc-bios/s390-ccw/dasd-ipl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index f7976aa43d0a..be53b7d3b703 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1181,6 +1181,7 @@ S: Supported
F: hw/s390x/ipl.*
F: pc-bios/s390-ccw/
F: pc-bios/s390-ccw.img
+F: docs/devel/s390-dasd-ipl.txt
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/docs/devel/s390-dasd-ipl.txt b/docs/devel/s390-dasd-ipl.txt
new file mode 100644
index 000000000000..9107e048e4e6
--- /dev/null
+++ b/docs/devel/s390-dasd-ipl.txt
@@ -0,0 +1,133 @@
+*****************************
+***** s390 hardware IPL *****
+*****************************
+
+The s390 hardware IPL process consists of the following steps.
+
+1. A READ IPL ccw is constructed in memory location 0x0.
+ This ccw, by definition, reads the IPL1 record which is located on the disk
+ at cylinder 0 track 0 record 1. Note that the chain flag is on in this ccw
+ so when it is complete another ccw will be fetched and executed from memory
+ location 0x08.
+
+2. Execute the Read IPL ccw at 0x00, thereby reading IPL1 data into 0x00.
+ IPL1 data is 24 bytes in length and consists of the following pieces of
+ information: [psw][read ccw][tic ccw]. When the machine executes the Read
+ IPL ccw it read the 24-bytes of IPL1 to be read into memory starting at
+ location 0x0. Then the ccw program at 0x08 which consists of a read
+ ccw and a tic ccw is automatically executed because of the chain flag from
+ the original READ IPL ccw. The read ccw will read the IPL2 data into memory
+ and the TIC (Transfer In Channel) will transfer control to the channel
+ program contained in the IPL2 data. The TIC channel command is the
+ equivalent of a branch/jump/goto instruction for channel programs.
+ NOTE: The ccws in IPL1 are defined by the architecture to be format 0.
+
+3. Execute IPL2.
+ The TIC ccw instruction at the end of the IPL1 channel program will begin
+ the execution of the IPL2 channel program. IPL2 is stage-2 of the boot
+ process and will contain a larger channel program than IPL1. The point of
+ IPL2 is to find and load either the operating system or a small program that
+ loads the operating system from disk. At the end of this step all or some of
+ the real operating system is loaded into memory and we are ready to hand
+ control over to the guest operating system. At this point the guest
+ operating system is entirely responsible for loading any more data it might
+ need to function. NOTE: The IPL2 channel program might read data into memory
+ location 0 thereby overwriting the IPL1 psw and channel program. This is ok
+ as long as the data placed in location 0 contains a psw whose instruction
+ address points to the guest operating system code to execute at the end of
+ the IPL/boot process.
+ NOTE: The ccws in IPL2 are defined by the architecture to be format 0.
+
+4. Start executing the guest operating system.
+ The psw that was loaded into memory location 0 as part of the ipl process
+ should contain the needed flags for the operating system we have loaded. The
+ psw's instruction address will point to the location in memory where we want
+ to start executing the operating system. This psw is loaded (via LPSW
+ instruction) causing control to be passed to the operating system code.
+
+In a non-virtualized environment this process, handled entirely by the hardware,
+is kicked off by the user initiating a "Load" procedure from the hardware
+management console. This "Load" procedure crafts a special "Read IPL" ccw in
+memory location 0x0 that reads IPL1. It then executes this ccw thereby kicking
+off the reading of IPL1 data. Since the channel program from IPL1 will be
+written immediately after the special "Read IPL" ccw, the IPL1 channel program
+will be executed immediately (the special read ccw has the chaining bit turned
+on). The TIC at the end of the IPL1 channel program will cause the IPL2 channel
+program to be executed automatically. After this sequence completes the "Load"
+procedure then loads the psw from 0x0.
+
+**********************************************************
+***** How this all pertains to QEMU (and the kernel) *****
+**********************************************************
+
+In theory we should merely have to do the following to IPL/boot a guest
+operating system from a DASD device:
+
+1. Place a "Read IPL" ccw into memory location 0x0 with chaining bit on.
+2. Execute channel program at 0x0.
+3. LPSW 0x0.
+
+However, our emulation of the machine's channel program logic within the kernel
+is missing one key feature that is required for this process to work:
+non-prefetch of ccw data.
+
+When we start a channel program we pass the channel subsystem parameters via an
+ORB (Operation Request Block). One of those parameters is a prefetch bit. If the
+bit is on then the vfio-ccw kernel driver is allowed to read the entire channel
+program from guest memory before it starts executing it. This means that any
+channel commands that read additional channel commands will not work as expected
+because the newly read commands will only exist in guest memory and NOT within
+the kernel's channel subsystem memory. The kernel vfio-ccw driver currently
+requires this bit to be on for all channel programs. This is a problem because
+the IPL process consists of transferring control from the "Read IPL" ccw
+immediately to the IPL1 channel program that was read by "Read IPL".
+
+Not being able to turn off prefetch will also prevent the TIC at the end of the
+IPL1 channel program from transferring control to the IPL2 channel program.
+
+Lastly, in some cases (the zipl bootloader for example) the IPL2 program also
+transfers control to another channel program segment immediately after reading
+it from the disk. So we need to be able to handle this case.
+
+**************************
+***** What QEMU does *****
+**************************
+
+Since we are forced to live with prefetch we cannot use the very simple IPL
+procedure we defined in the preceding section. So we compensate by doing the
+following.
+
+1. Place "Read IPL" ccw into memory location 0x0, but turn off chaining bit.
+2. Execute "Read IPL" at 0x0.
+
+ So now IPL1's psw is at 0x0 and IPL1's channel program is at 0x08.
+
+4. Write a custom channel program that will seek to the IPL2 record and then
+ execute the READ and TIC ccws from IPL1. Normally the seek is not required
+ because after reading the IPL1 record the disk is automatically positioned
+ to read the very next record which will be IPL2. But since we are not reading
+ both IPL1 and IPL2 as part of the same channel program we must manually set
+ the position.
+
+5. Grab the target address of the TIC instruction from the IPL1 channel program.
+ This address is where the IPL2 channel program starts.
+
+ Now IPL2 is loaded into memory somewhere, and we know the address.
+
+6. Execute the IPL2 channel program at the address obtained in step #5.
+
+ Because this channel program can be dynamic, we must use a special algorithm
+ that detects a READ immediately followed by a TIC and breaks the ccw chain
+ by turning off the chain bit in the READ ccw. When control is returned from
+ the kernel/hardware to the QEMU bios code we immediately issue another start
+ subchannel to execute the remaining TIC instruction. This causes the entire
+ channel program (starting from the TIC) and all needed data to be refetched
+ thereby stepping around the limitation that would otherwise prevent this
+ channel program from executing properly.
+
+ Now the operating system code is loaded somewhere in guest memory and the psw
+ in memory location 0x0 will point to entry code for the guest operating
+ system.
+
+7. LPSW 0x0.
+ LPSW transfers control to the guest operating system and we're done.
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 12ad9c1d5813..a048b6b077a9 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
- virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c
new file mode 100644
index 000000000000..0fc879bb8e8f
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.c
@@ -0,0 +1,235 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 "libc.h"
+#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "dasd-ipl.h"
+#include "helper.h"
+
+static char prefix_page[PAGE_SIZE * 2]
+ __attribute__((__aligned__(PAGE_SIZE * 2)));
+
+static void enable_prefixing(void)
+{
+ memcpy(&prefix_page, lowcore, 4096);
+ set_prefix(ptr2u32(&prefix_page));
+}
+
+static void disable_prefixing(void)
+{
+ set_prefix(0);
+ /* Copy io interrupt info back to low core */
+ memcpy((void *)&lowcore->subchannel_id, prefix_page + 0xB8, 12);
+}
+
+static bool is_read_tic_ccw_chain(Ccw0 *ccw)
+{
+ Ccw0 *next_ccw = ccw + 1;
+
+ return ((ccw->cmd_code == CCW_CMD_DASD_READ ||
+ ccw->cmd_code == CCW_CMD_DASD_READ_MT) &&
+ ccw->chain && next_ccw->cmd_code == CCW_CMD_TIC);
+}
+
+static bool dynamic_cp_fixup(uint32_t ccw_addr, uint32_t *next_cpa)
+{
+ Ccw0 *cur_ccw = (Ccw0 *)(uint64_t)ccw_addr;
+ Ccw0 *tic_ccw;
+
+ while (true) {
+ /* Skip over inline TIC (it might not have the chain bit on) */
+ if (cur_ccw->cmd_code == CCW_CMD_TIC &&
+ cur_ccw->cda == ptr2u32(cur_ccw) - 8) {
+ cur_ccw += 1;
+ continue;
+ }
+
+ if (!cur_ccw->chain) {
+ break;
+ }
+ if (is_read_tic_ccw_chain(cur_ccw)) {
+ /*
+ * Breaking a chain of CCWs may alter the semantics or even the
+ * validity of a channel program. The heuristic implemented below
+ * seems to work well in practice for the channel programs
+ * generated by zipl.
+ */
+ tic_ccw = cur_ccw + 1;
+ *next_cpa = tic_ccw->cda;
+ cur_ccw->chain = 0;
+ return true;
+ }
+ cur_ccw += 1;
+ }
+ return false;
+}
+
+static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype,
+ uint32_t cpa)
+{
+ bool has_next;
+ uint32_t next_cpa = 0;
+ int rc;
+
+ do {
+ has_next = dynamic_cp_fixup(cpa, &next_cpa);
+
+ print_int("executing ccw chain at ", cpa);
+ enable_prefixing();
+ rc = do_cio(schid, cutype, cpa, CCW_FMT0);
+ disable_prefixing();
+
+ if (rc) {
+ break;
+ }
+ cpa = next_cpa;
+ } while (has_next);
+
+ return rc;
+}
+
+static void make_readipl(void)
+{
+ Ccw0 *ccwIplRead = (Ccw0 *)0x00;
+
+ /* Create Read IPL ccw at address 0 */
+ ccwIplRead->cmd_code = CCW_CMD_READ_IPL;
+ ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */
+ ccwIplRead->chain = 0; /* Chain flag */
+ ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */
+}
+
+static void run_readipl(SubChannelId schid, uint16_t cutype)
+{
+ if (do_cio(schid, cutype, 0x00, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run Read IPL channel program\n");
+ }
+}
+
+/*
+ * The architecture states that IPL1 data should consist of a psw followed by
+ * format-0 READ and TIC CCWs. Let's sanity check.
+ */
+static void check_ipl1(void)
+{
+ Ccw0 *ccwread = (Ccw0 *)0x08;
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ if (ccwread->cmd_code != CCW_CMD_DASD_READ ||
+ ccwtic->cmd_code != CCW_CMD_TIC) {
+ panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static void check_ipl2(uint32_t ipl2_addr)
+{
+ Ccw0 *ccw = u32toptr(ipl2_addr);
+
+ if (ipl2_addr == 0x00) {
+ panic("IPL2 address invalid. Is this disk really bootable?\n");
+ }
+ if (ccw->cmd_code == 0x00) {
+ panic("IPL2 ccw data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static uint32_t read_ipl2_addr(void)
+{
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ return ccwtic->cda;
+}
+
+static void ipl1_fixup(void)
+{
+ Ccw0 *ccwSeek = (Ccw0 *) 0x08;
+ Ccw0 *ccwSearchID = (Ccw0 *) 0x10;
+ Ccw0 *ccwSearchTic = (Ccw0 *) 0x18;
+ Ccw0 *ccwRead = (Ccw0 *) 0x20;
+ CcwSeekData *seekData = (CcwSeekData *) 0x30;
+ CcwSearchIdData *searchData = (CcwSearchIdData *) 0x38;
+
+ /* move IPL1 CCWs to make room for CCWs needed to locate record 2 */
+ memcpy(ccwRead, (void *)0x08, 16);
+
+ /* Disable chaining so we don't TIC to IPL2 channel program */
+ ccwRead->chain = 0x00;
+
+ ccwSeek->cmd_code = CCW_CMD_DASD_SEEK;
+ ccwSeek->cda = ptr2u32(seekData);
+ ccwSeek->chain = 1;
+ ccwSeek->count = sizeof(*seekData);
+ seekData->reserved = 0x00;
+ seekData->cyl = 0x00;
+ seekData->head = 0x00;
+
+ ccwSearchID->cmd_code = CCW_CMD_DASD_SEARCH_ID_EQ;
+ ccwSearchID->cda = ptr2u32(searchData);
+ ccwSearchID->chain = 1;
+ ccwSearchID->count = sizeof(*searchData);
+ searchData->cyl = 0;
+ searchData->head = 0;
+ searchData->record = 2;
+
+ /* Go back to Search CCW if correct record not yet found */
+ ccwSearchTic->cmd_code = CCW_CMD_TIC;
+ ccwSearchTic->cda = ptr2u32(ccwSearchID);
+}
+
+static void run_ipl1(SubChannelId schid, uint16_t cutype)
+ {
+ uint32_t startAddr = 0x08;
+
+ if (do_cio(schid, cutype, startAddr, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run IPL1 channel program\n");
+ }
+}
+
+static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr)
+{
+ if (run_dynamic_ccw_program(schid, cutype, addr)) {
+ panic("dasd-ipl: Failed to run IPL2 channel program\n");
+ }
+}
+
+/*
+ * Limitations in vfio-ccw support complicate the IPL process. Details can
+ * be found in docs/devel/s390-dasd-ipl.txt
+ */
+void dasd_ipl(SubChannelId schid, uint16_t cutype)
+{
+ PSWLegacy *pswl = (PSWLegacy *) 0x00;
+ uint32_t ipl2_addr;
+
+ /* Construct Read IPL CCW and run it to read IPL1 from boot disk */
+ make_readipl();
+ run_readipl(schid, cutype);
+ ipl2_addr = read_ipl2_addr();
+ check_ipl1();
+
+ /*
+ * Fixup IPL1 channel program to account for vfio-ccw limitations, then run
+ * it to read IPL2 channel program from boot disk.
+ */
+ ipl1_fixup();
+ run_ipl1(schid, cutype);
+ check_ipl2(ipl2_addr);
+
+ /*
+ * Run IPL2 channel program to read operating system code from boot disk
+ */
+ run_ipl2(schid, cutype, ipl2_addr);
+
+ /* Transfer control to the guest operating system */
+ pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */
+ pswl->addr |= PSW_MASK_BAMODE; /* ... */
+ jump_to_low_kernel();
+}
diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h
new file mode 100644
index 000000000000..c3948289062c
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.h
@@ -0,0 +1,16 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 DASD_IPL_H
+#define DASD_IPL_H
+
+void dasd_ipl(SubChannelId schid, uint16_t cutype);
+
+#endif /* DASD_IPL_H */
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 57a10138c65d..3c449ad49688 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -13,6 +13,7 @@
#include "s390-ccw.h"
#include "cio.h"
#include "virtio.h"
+#include "dasd-ipl.h"
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
@@ -209,6 +210,10 @@ int main(void)
cutype = cu_type(blk_schid);
switch (cutype) {
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ dasd_ipl(blk_schid, cutype); /* no return */
+ break;
case CU_TYPE_VIRTIO:
virtio_setup();
zipl_load(); /* no return */
diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h
index 5e92c7a27d53..504fc7c2f098 100644
--- a/pc-bios/s390-ccw/s390-arch.h
+++ b/pc-bios/s390-ccw/s390-arch.h
@@ -87,4 +87,17 @@ typedef struct LowCore {
extern LowCore const *lowcore;
+static inline void set_prefix(uint32_t address)
+{
+ asm volatile("spx %0" : : "m" (address) : "memory");
+}
+
+static inline uint32_t store_prefix(void)
+{
+ uint32_t address;
+
+ asm volatile("stpx %0" : "=m" (address));
+ return address;
+}
+
#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 15/19] s390-bios: Support booting from real dasd device
2019-04-25 13:21 ` [Qemu-devel] [PULL 15/19] s390-bios: Support booting from real dasd device Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
Allows guest to boot from a vfio configured real dasd device.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <1554388475-18329-16-git-send-email-jjherne@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 1 +
docs/devel/s390-dasd-ipl.txt | 133 ++++++++++++++++++++
pc-bios/s390-ccw/Makefile | 2 +-
pc-bios/s390-ccw/dasd-ipl.c | 235 +++++++++++++++++++++++++++++++++++
pc-bios/s390-ccw/dasd-ipl.h | 16 +++
pc-bios/s390-ccw/main.c | 5 +
pc-bios/s390-ccw/s390-arch.h | 13 ++
7 files changed, 404 insertions(+), 1 deletion(-)
create mode 100644 docs/devel/s390-dasd-ipl.txt
create mode 100644 pc-bios/s390-ccw/dasd-ipl.c
create mode 100644 pc-bios/s390-ccw/dasd-ipl.h
diff --git a/MAINTAINERS b/MAINTAINERS
index f7976aa43d0a..be53b7d3b703 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1181,6 +1181,7 @@ S: Supported
F: hw/s390x/ipl.*
F: pc-bios/s390-ccw/
F: pc-bios/s390-ccw.img
+F: docs/devel/s390-dasd-ipl.txt
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/docs/devel/s390-dasd-ipl.txt b/docs/devel/s390-dasd-ipl.txt
new file mode 100644
index 000000000000..9107e048e4e6
--- /dev/null
+++ b/docs/devel/s390-dasd-ipl.txt
@@ -0,0 +1,133 @@
+*****************************
+***** s390 hardware IPL *****
+*****************************
+
+The s390 hardware IPL process consists of the following steps.
+
+1. A READ IPL ccw is constructed in memory location 0x0.
+ This ccw, by definition, reads the IPL1 record which is located on the disk
+ at cylinder 0 track 0 record 1. Note that the chain flag is on in this ccw
+ so when it is complete another ccw will be fetched and executed from memory
+ location 0x08.
+
+2. Execute the Read IPL ccw at 0x00, thereby reading IPL1 data into 0x00.
+ IPL1 data is 24 bytes in length and consists of the following pieces of
+ information: [psw][read ccw][tic ccw]. When the machine executes the Read
+ IPL ccw it read the 24-bytes of IPL1 to be read into memory starting at
+ location 0x0. Then the ccw program at 0x08 which consists of a read
+ ccw and a tic ccw is automatically executed because of the chain flag from
+ the original READ IPL ccw. The read ccw will read the IPL2 data into memory
+ and the TIC (Transfer In Channel) will transfer control to the channel
+ program contained in the IPL2 data. The TIC channel command is the
+ equivalent of a branch/jump/goto instruction for channel programs.
+ NOTE: The ccws in IPL1 are defined by the architecture to be format 0.
+
+3. Execute IPL2.
+ The TIC ccw instruction at the end of the IPL1 channel program will begin
+ the execution of the IPL2 channel program. IPL2 is stage-2 of the boot
+ process and will contain a larger channel program than IPL1. The point of
+ IPL2 is to find and load either the operating system or a small program that
+ loads the operating system from disk. At the end of this step all or some of
+ the real operating system is loaded into memory and we are ready to hand
+ control over to the guest operating system. At this point the guest
+ operating system is entirely responsible for loading any more data it might
+ need to function. NOTE: The IPL2 channel program might read data into memory
+ location 0 thereby overwriting the IPL1 psw and channel program. This is ok
+ as long as the data placed in location 0 contains a psw whose instruction
+ address points to the guest operating system code to execute at the end of
+ the IPL/boot process.
+ NOTE: The ccws in IPL2 are defined by the architecture to be format 0.
+
+4. Start executing the guest operating system.
+ The psw that was loaded into memory location 0 as part of the ipl process
+ should contain the needed flags for the operating system we have loaded. The
+ psw's instruction address will point to the location in memory where we want
+ to start executing the operating system. This psw is loaded (via LPSW
+ instruction) causing control to be passed to the operating system code.
+
+In a non-virtualized environment this process, handled entirely by the hardware,
+is kicked off by the user initiating a "Load" procedure from the hardware
+management console. This "Load" procedure crafts a special "Read IPL" ccw in
+memory location 0x0 that reads IPL1. It then executes this ccw thereby kicking
+off the reading of IPL1 data. Since the channel program from IPL1 will be
+written immediately after the special "Read IPL" ccw, the IPL1 channel program
+will be executed immediately (the special read ccw has the chaining bit turned
+on). The TIC at the end of the IPL1 channel program will cause the IPL2 channel
+program to be executed automatically. After this sequence completes the "Load"
+procedure then loads the psw from 0x0.
+
+**********************************************************
+***** How this all pertains to QEMU (and the kernel) *****
+**********************************************************
+
+In theory we should merely have to do the following to IPL/boot a guest
+operating system from a DASD device:
+
+1. Place a "Read IPL" ccw into memory location 0x0 with chaining bit on.
+2. Execute channel program at 0x0.
+3. LPSW 0x0.
+
+However, our emulation of the machine's channel program logic within the kernel
+is missing one key feature that is required for this process to work:
+non-prefetch of ccw data.
+
+When we start a channel program we pass the channel subsystem parameters via an
+ORB (Operation Request Block). One of those parameters is a prefetch bit. If the
+bit is on then the vfio-ccw kernel driver is allowed to read the entire channel
+program from guest memory before it starts executing it. This means that any
+channel commands that read additional channel commands will not work as expected
+because the newly read commands will only exist in guest memory and NOT within
+the kernel's channel subsystem memory. The kernel vfio-ccw driver currently
+requires this bit to be on for all channel programs. This is a problem because
+the IPL process consists of transferring control from the "Read IPL" ccw
+immediately to the IPL1 channel program that was read by "Read IPL".
+
+Not being able to turn off prefetch will also prevent the TIC at the end of the
+IPL1 channel program from transferring control to the IPL2 channel program.
+
+Lastly, in some cases (the zipl bootloader for example) the IPL2 program also
+transfers control to another channel program segment immediately after reading
+it from the disk. So we need to be able to handle this case.
+
+**************************
+***** What QEMU does *****
+**************************
+
+Since we are forced to live with prefetch we cannot use the very simple IPL
+procedure we defined in the preceding section. So we compensate by doing the
+following.
+
+1. Place "Read IPL" ccw into memory location 0x0, but turn off chaining bit.
+2. Execute "Read IPL" at 0x0.
+
+ So now IPL1's psw is at 0x0 and IPL1's channel program is at 0x08.
+
+4. Write a custom channel program that will seek to the IPL2 record and then
+ execute the READ and TIC ccws from IPL1. Normally the seek is not required
+ because after reading the IPL1 record the disk is automatically positioned
+ to read the very next record which will be IPL2. But since we are not reading
+ both IPL1 and IPL2 as part of the same channel program we must manually set
+ the position.
+
+5. Grab the target address of the TIC instruction from the IPL1 channel program.
+ This address is where the IPL2 channel program starts.
+
+ Now IPL2 is loaded into memory somewhere, and we know the address.
+
+6. Execute the IPL2 channel program at the address obtained in step #5.
+
+ Because this channel program can be dynamic, we must use a special algorithm
+ that detects a READ immediately followed by a TIC and breaks the ccw chain
+ by turning off the chain bit in the READ ccw. When control is returned from
+ the kernel/hardware to the QEMU bios code we immediately issue another start
+ subchannel to execute the remaining TIC instruction. This causes the entire
+ channel program (starting from the TIC) and all needed data to be refetched
+ thereby stepping around the limitation that would otherwise prevent this
+ channel program from executing properly.
+
+ Now the operating system code is loaded somewhere in guest memory and the psw
+ in memory location 0x0 will point to entry code for the guest operating
+ system.
+
+7. LPSW 0x0.
+ LPSW transfers control to the guest operating system and we're done.
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 12ad9c1d5813..a048b6b077a9 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
- virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c
new file mode 100644
index 000000000000..0fc879bb8e8f
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.c
@@ -0,0 +1,235 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 "libc.h"
+#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "dasd-ipl.h"
+#include "helper.h"
+
+static char prefix_page[PAGE_SIZE * 2]
+ __attribute__((__aligned__(PAGE_SIZE * 2)));
+
+static void enable_prefixing(void)
+{
+ memcpy(&prefix_page, lowcore, 4096);
+ set_prefix(ptr2u32(&prefix_page));
+}
+
+static void disable_prefixing(void)
+{
+ set_prefix(0);
+ /* Copy io interrupt info back to low core */
+ memcpy((void *)&lowcore->subchannel_id, prefix_page + 0xB8, 12);
+}
+
+static bool is_read_tic_ccw_chain(Ccw0 *ccw)
+{
+ Ccw0 *next_ccw = ccw + 1;
+
+ return ((ccw->cmd_code == CCW_CMD_DASD_READ ||
+ ccw->cmd_code == CCW_CMD_DASD_READ_MT) &&
+ ccw->chain && next_ccw->cmd_code == CCW_CMD_TIC);
+}
+
+static bool dynamic_cp_fixup(uint32_t ccw_addr, uint32_t *next_cpa)
+{
+ Ccw0 *cur_ccw = (Ccw0 *)(uint64_t)ccw_addr;
+ Ccw0 *tic_ccw;
+
+ while (true) {
+ /* Skip over inline TIC (it might not have the chain bit on) */
+ if (cur_ccw->cmd_code == CCW_CMD_TIC &&
+ cur_ccw->cda == ptr2u32(cur_ccw) - 8) {
+ cur_ccw += 1;
+ continue;
+ }
+
+ if (!cur_ccw->chain) {
+ break;
+ }
+ if (is_read_tic_ccw_chain(cur_ccw)) {
+ /*
+ * Breaking a chain of CCWs may alter the semantics or even the
+ * validity of a channel program. The heuristic implemented below
+ * seems to work well in practice for the channel programs
+ * generated by zipl.
+ */
+ tic_ccw = cur_ccw + 1;
+ *next_cpa = tic_ccw->cda;
+ cur_ccw->chain = 0;
+ return true;
+ }
+ cur_ccw += 1;
+ }
+ return false;
+}
+
+static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype,
+ uint32_t cpa)
+{
+ bool has_next;
+ uint32_t next_cpa = 0;
+ int rc;
+
+ do {
+ has_next = dynamic_cp_fixup(cpa, &next_cpa);
+
+ print_int("executing ccw chain at ", cpa);
+ enable_prefixing();
+ rc = do_cio(schid, cutype, cpa, CCW_FMT0);
+ disable_prefixing();
+
+ if (rc) {
+ break;
+ }
+ cpa = next_cpa;
+ } while (has_next);
+
+ return rc;
+}
+
+static void make_readipl(void)
+{
+ Ccw0 *ccwIplRead = (Ccw0 *)0x00;
+
+ /* Create Read IPL ccw at address 0 */
+ ccwIplRead->cmd_code = CCW_CMD_READ_IPL;
+ ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */
+ ccwIplRead->chain = 0; /* Chain flag */
+ ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */
+}
+
+static void run_readipl(SubChannelId schid, uint16_t cutype)
+{
+ if (do_cio(schid, cutype, 0x00, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run Read IPL channel program\n");
+ }
+}
+
+/*
+ * The architecture states that IPL1 data should consist of a psw followed by
+ * format-0 READ and TIC CCWs. Let's sanity check.
+ */
+static void check_ipl1(void)
+{
+ Ccw0 *ccwread = (Ccw0 *)0x08;
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ if (ccwread->cmd_code != CCW_CMD_DASD_READ ||
+ ccwtic->cmd_code != CCW_CMD_TIC) {
+ panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static void check_ipl2(uint32_t ipl2_addr)
+{
+ Ccw0 *ccw = u32toptr(ipl2_addr);
+
+ if (ipl2_addr == 0x00) {
+ panic("IPL2 address invalid. Is this disk really bootable?\n");
+ }
+ if (ccw->cmd_code == 0x00) {
+ panic("IPL2 ccw data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static uint32_t read_ipl2_addr(void)
+{
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ return ccwtic->cda;
+}
+
+static void ipl1_fixup(void)
+{
+ Ccw0 *ccwSeek = (Ccw0 *) 0x08;
+ Ccw0 *ccwSearchID = (Ccw0 *) 0x10;
+ Ccw0 *ccwSearchTic = (Ccw0 *) 0x18;
+ Ccw0 *ccwRead = (Ccw0 *) 0x20;
+ CcwSeekData *seekData = (CcwSeekData *) 0x30;
+ CcwSearchIdData *searchData = (CcwSearchIdData *) 0x38;
+
+ /* move IPL1 CCWs to make room for CCWs needed to locate record 2 */
+ memcpy(ccwRead, (void *)0x08, 16);
+
+ /* Disable chaining so we don't TIC to IPL2 channel program */
+ ccwRead->chain = 0x00;
+
+ ccwSeek->cmd_code = CCW_CMD_DASD_SEEK;
+ ccwSeek->cda = ptr2u32(seekData);
+ ccwSeek->chain = 1;
+ ccwSeek->count = sizeof(*seekData);
+ seekData->reserved = 0x00;
+ seekData->cyl = 0x00;
+ seekData->head = 0x00;
+
+ ccwSearchID->cmd_code = CCW_CMD_DASD_SEARCH_ID_EQ;
+ ccwSearchID->cda = ptr2u32(searchData);
+ ccwSearchID->chain = 1;
+ ccwSearchID->count = sizeof(*searchData);
+ searchData->cyl = 0;
+ searchData->head = 0;
+ searchData->record = 2;
+
+ /* Go back to Search CCW if correct record not yet found */
+ ccwSearchTic->cmd_code = CCW_CMD_TIC;
+ ccwSearchTic->cda = ptr2u32(ccwSearchID);
+}
+
+static void run_ipl1(SubChannelId schid, uint16_t cutype)
+ {
+ uint32_t startAddr = 0x08;
+
+ if (do_cio(schid, cutype, startAddr, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run IPL1 channel program\n");
+ }
+}
+
+static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr)
+{
+ if (run_dynamic_ccw_program(schid, cutype, addr)) {
+ panic("dasd-ipl: Failed to run IPL2 channel program\n");
+ }
+}
+
+/*
+ * Limitations in vfio-ccw support complicate the IPL process. Details can
+ * be found in docs/devel/s390-dasd-ipl.txt
+ */
+void dasd_ipl(SubChannelId schid, uint16_t cutype)
+{
+ PSWLegacy *pswl = (PSWLegacy *) 0x00;
+ uint32_t ipl2_addr;
+
+ /* Construct Read IPL CCW and run it to read IPL1 from boot disk */
+ make_readipl();
+ run_readipl(schid, cutype);
+ ipl2_addr = read_ipl2_addr();
+ check_ipl1();
+
+ /*
+ * Fixup IPL1 channel program to account for vfio-ccw limitations, then run
+ * it to read IPL2 channel program from boot disk.
+ */
+ ipl1_fixup();
+ run_ipl1(schid, cutype);
+ check_ipl2(ipl2_addr);
+
+ /*
+ * Run IPL2 channel program to read operating system code from boot disk
+ */
+ run_ipl2(schid, cutype, ipl2_addr);
+
+ /* Transfer control to the guest operating system */
+ pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */
+ pswl->addr |= PSW_MASK_BAMODE; /* ... */
+ jump_to_low_kernel();
+}
diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h
new file mode 100644
index 000000000000..c3948289062c
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.h
@@ -0,0 +1,16 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.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 DASD_IPL_H
+#define DASD_IPL_H
+
+void dasd_ipl(SubChannelId schid, uint16_t cutype);
+
+#endif /* DASD_IPL_H */
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 57a10138c65d..3c449ad49688 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -13,6 +13,7 @@
#include "s390-ccw.h"
#include "cio.h"
#include "virtio.h"
+#include "dasd-ipl.h"
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
@@ -209,6 +210,10 @@ int main(void)
cutype = cu_type(blk_schid);
switch (cutype) {
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ dasd_ipl(blk_schid, cutype); /* no return */
+ break;
case CU_TYPE_VIRTIO:
virtio_setup();
zipl_load(); /* no return */
diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h
index 5e92c7a27d53..504fc7c2f098 100644
--- a/pc-bios/s390-ccw/s390-arch.h
+++ b/pc-bios/s390-ccw/s390-arch.h
@@ -87,4 +87,17 @@ typedef struct LowCore {
extern LowCore const *lowcore;
+static inline void set_prefix(uint32_t address)
+{
+ asm volatile("spx %0" : : "m" (address) : "memory");
+}
+
+static inline uint32_t store_prefix(void)
+{
+ uint32_t address;
+
+ asm volatile("stpx %0" : "=m" (address));
+ return address;
+}
+
#endif
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 16/19] s390-bios: Use control unit type to find bootable devices
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (15 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 15/19] s390-bios: Support booting from real dasd device Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 17/19] pc-bios/s390: Update firmware images Cornelia Huck
` (3 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Jason J. Herne, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
When the user does not specify which device to boot from then we end
up guessing. Instead of simply grabbing the first available device let's
be a little bit smarter and only choose devices that might be bootable
like disk, and not console devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Message-Id: <1554388475-18329-17-git-send-email-jjherne@linux.ibm.com>
[thuth: Added fix for virtio_is_supported() not being called anymore]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 45 ++++++++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 3c449ad49688..a69c73349e8f 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -21,6 +21,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static bool have_iplb;
+static uint16_t cutype;
LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */
#define LOADPARM_PROMPT "PROMPT "
@@ -58,11 +59,15 @@ unsigned int get_loadparm_index(void)
* subchannel information block (schib) with the connected subchannel's info.
* NOTE: The global variable blk_schid is updated to contain the subchannel
* information.
+ *
+ * If the caller gives dev_no=-1 then the user did not specify a boot device.
+ * In this case we'll just use the first potentially bootable device we find.
*/
static bool find_subch(int dev_no)
{
Schib schib;
int i, r;
+ bool is_virtio;
for (i = 0; i < 0x10000; i++) {
blk_schid.sch_no = i;
@@ -74,16 +79,39 @@ static bool find_subch(int dev_no)
continue;
}
- /* Skip net devices since no IPLB is created and therefore no
- * network bootloader has been loaded
- */
enable_subchannel(blk_schid);
- if (virtio_is_supported(blk_schid) &&
- virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
- continue;
+ cutype = cu_type(blk_schid);
+
+ /*
+ * Note: we always have to run virtio_is_supported() here to make
+ * sure that the vdev.senseid data gets pre-initialized correctly
+ */
+ is_virtio = virtio_is_supported(blk_schid);
+
+ /* No specific devno given, just return 1st possibly bootable device */
+ if (dev_no < 0) {
+ switch (cutype) {
+ case CU_TYPE_VIRTIO:
+ if (is_virtio) {
+ /*
+ * Skip net devices since no IPLB is created and therefore
+ * no network bootloader has been loaded
+ */
+ if (virtio_get_device_type() != VIRTIO_ID_NET) {
+ return true;
+ }
+ }
+ continue;
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ return true;
+ default:
+ continue;
+ }
}
- if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) {
+ /* Caller asked for a specific devno */
+ if (schib.pmcw.dev == dev_no) {
return true;
}
}
@@ -200,15 +228,12 @@ static void virtio_setup(void)
int main(void)
{
- uint16_t cutype;
-
sclp_setup();
css_setup();
boot_setup();
find_boot_device();
enable_subchannel(blk_schid);
- cutype = cu_type(blk_schid);
switch (cutype) {
case CU_TYPE_DASD_3990:
case CU_TYPE_DASD_2107:
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 16/19] s390-bios: Use control unit type to find bootable devices
2019-04-25 13:21 ` [Qemu-devel] [PULL 16/19] s390-bios: Use control unit type to find bootable devices Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Jason J. Herne, qemu-s390x, qemu-devel, Thomas Huth
From: "Jason J. Herne" <jjherne@linux.ibm.com>
When the user does not specify which device to boot from then we end
up guessing. Instead of simply grabbing the first available device let's
be a little bit smarter and only choose devices that might be bootable
like disk, and not console devices.
Signed-off-by: Jason J. Herne <jjherne@linux.ibm.com>
Message-Id: <1554388475-18329-17-git-send-email-jjherne@linux.ibm.com>
[thuth: Added fix for virtio_is_supported() not being called anymore]
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw/main.c | 45 ++++++++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 3c449ad49688..a69c73349e8f 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -21,6 +21,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static bool have_iplb;
+static uint16_t cutype;
LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */
#define LOADPARM_PROMPT "PROMPT "
@@ -58,11 +59,15 @@ unsigned int get_loadparm_index(void)
* subchannel information block (schib) with the connected subchannel's info.
* NOTE: The global variable blk_schid is updated to contain the subchannel
* information.
+ *
+ * If the caller gives dev_no=-1 then the user did not specify a boot device.
+ * In this case we'll just use the first potentially bootable device we find.
*/
static bool find_subch(int dev_no)
{
Schib schib;
int i, r;
+ bool is_virtio;
for (i = 0; i < 0x10000; i++) {
blk_schid.sch_no = i;
@@ -74,16 +79,39 @@ static bool find_subch(int dev_no)
continue;
}
- /* Skip net devices since no IPLB is created and therefore no
- * network bootloader has been loaded
- */
enable_subchannel(blk_schid);
- if (virtio_is_supported(blk_schid) &&
- virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
- continue;
+ cutype = cu_type(blk_schid);
+
+ /*
+ * Note: we always have to run virtio_is_supported() here to make
+ * sure that the vdev.senseid data gets pre-initialized correctly
+ */
+ is_virtio = virtio_is_supported(blk_schid);
+
+ /* No specific devno given, just return 1st possibly bootable device */
+ if (dev_no < 0) {
+ switch (cutype) {
+ case CU_TYPE_VIRTIO:
+ if (is_virtio) {
+ /*
+ * Skip net devices since no IPLB is created and therefore
+ * no network bootloader has been loaded
+ */
+ if (virtio_get_device_type() != VIRTIO_ID_NET) {
+ return true;
+ }
+ }
+ continue;
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ return true;
+ default:
+ continue;
+ }
}
- if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) {
+ /* Caller asked for a specific devno */
+ if (schib.pmcw.dev == dev_no) {
return true;
}
}
@@ -200,15 +228,12 @@ static void virtio_setup(void)
int main(void)
{
- uint16_t cutype;
-
sclp_setup();
css_setup();
boot_setup();
find_boot_device();
enable_subchannel(blk_schid);
- cutype = cu_type(blk_schid);
switch (cutype) {
case CU_TYPE_DASD_3990:
case CU_TYPE_DASD_2107:
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 17/19] pc-bios/s390: Update firmware images
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (16 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 16/19] s390-bios: Use control unit type to find bootable devices Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 18/19] s390x/kvm: Configure page size after memory has actually been initialized Cornelia Huck
` (2 subsequent siblings)
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, Thomas Huth
From: Thomas Huth <thuth@redhat.com>
s390-ccw.img contains support for booting from vfio-ccw dasd passthrough
devices now, and s390-netboot.img is updated since there were changes
to the code that is shared between s390-ccw.img and s390-netboot.img.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw.img | Bin 34568 -> 42608 bytes
pc-bios/s390-netboot.img | Bin 54944 -> 67232 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 450a076dc0ad9f2babc7f2e3005ea05a1082a808..ba054828d35d72fd1ed5521a48f43f593a1c291f 100644
GIT binary patch
literal 42608
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
delta 16147
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
R&FRaA2C%C;_qK6~{|{5#FdqN_
diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img
index 2c6886efb8320ff711589119ffbf077e68ec8784..aa90fbccb142470924ad5f0de5a4c6337916c63a 100644
GIT binary patch
delta 23541
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�+(
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
delta 11243
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
--
2.17.2
^ permalink raw reply [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 17/19] pc-bios/s390: Update firmware images
2019-04-25 13:21 ` [Qemu-devel] [PULL 17/19] pc-bios/s390: Update firmware images Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: Thomas Huth, qemu-s390x, qemu-devel
From: Thomas Huth <thuth@redhat.com>
s390-ccw.img contains support for booting from vfio-ccw dasd passthrough
devices now, and s390-netboot.img is updated since there were changes
to the code that is shared between s390-ccw.img and s390-netboot.img.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
pc-bios/s390-ccw.img | Bin 34568 -> 42608 bytes
pc-bios/s390-netboot.img | Bin 54944 -> 67232 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 450a076dc0ad9f2babc7f2e3005ea05a1082a808..ba054828d35d72fd1ed5521a48f43f593a1c291f 100644
GIT binary patch
literal 42608
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
delta 16147
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
R&FRaA2C%C;_qK6~{|{5#FdqN_
diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img
index 2c6886efb8320ff711589119ffbf077e68ec8784..aa90fbccb142470924ad5f0de5a4c6337916c63a 100644
GIT binary patch
delta 23541
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�+(
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
delta 11243
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
--
2.17.2
^ permalink raw reply [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 18/19] s390x/kvm: Configure page size after memory has actually been initialized
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (17 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 17/19] pc-bios/s390: Update firmware images Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` [Qemu-devel] [PULL 19/19] exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize() Cornelia Huck
2019-04-26 13:29 ` [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Peter Maydell
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Right now we configure the pagesize quite early, when initializing KVM.
This is long before system memory is actually allocated via
memory_region_allocate_system_memory(), and therefore memory backends
marked as mapped.
Instead, let's configure the maximum page size after initializing
memory in s390_memory_init(). cap_hpage_1m is still properly
configured before creating any CPUs, and therefore before configuring
the CPU model and eventually enabling CMMA.
This is not a fix but rather a preparation for the future, when initial
memory might reside on memory backends (not the case for s390x right now)
We will replace qemu_getrampagesize() soon by a function that will always
return the maximum page size (not the minimum page size, which only
works by pure luck so far, as there are no memory backends).
Acked-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190417113143.5551-2-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 12 ++++++++++++
target/s390x/cpu.c | 7 +++++++
target/s390x/cpu.h | 1 +
target/s390x/kvm-stub.c | 4 ++++
target/s390x/kvm.c | 35 ++++++++++++++---------------------
target/s390x/kvm_s390x.h | 1 +
6 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d11069b860b4..3be567965736 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -15,6 +15,7 @@
#include "cpu.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
+#include "exec/ram_addr.h"
#include "hw/s390x/s390-virtio-hcall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
@@ -163,6 +164,7 @@ static void s390_memory_init(ram_addr_t mem_size)
MemoryRegion *sysmem = get_system_memory();
ram_addr_t chunk, offset = 0;
unsigned int number = 0;
+ Error *local_err = NULL;
gchar *name;
/* allocate RAM for core */
@@ -182,6 +184,15 @@ static void s390_memory_init(ram_addr_t mem_size)
}
g_free(name);
+ /*
+ * Configure the maximum page size. As no memory devices were created
+ * yet, this is the page size of initial memory only.
+ */
+ s390_set_max_pagesize(qemu_getrampagesize(), &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ exit(EXIT_FAILURE);
+ }
/* Initialize storage key device */
s390_skeys_init();
/* Initialize storage attributes device */
@@ -253,6 +264,7 @@ static void ccw_init(MachineState *machine)
DeviceState *dev;
s390_sclp_init();
+ /* init memory + setup max page size. Required for the CPU model */
s390_memory_init(machine->ram_size);
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 698dd9cb82ab..b58ef0a8ef62 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -399,6 +399,13 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+ if (kvm_enabled()) {
+ kvm_s390_set_max_pagesize(pagesize, errp);
+ }
+}
+
void s390_cmma_reset(void)
{
if (kvm_enabled()) {
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d8990c405a5d..7305cacc7b77 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -734,6 +734,7 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
/* cpu.c */
void s390_crypto_reset(void);
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void s390_cmma_reset(void);
void s390_enable_css_support(S390CPU *cpu);
int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
index bf7795e47a1c..22b4514ca68c 100644
--- a/target/s390x/kvm-stub.c
+++ b/target/s390x/kvm-stub.c
@@ -93,6 +93,10 @@ int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+}
+
void kvm_s390_crypto_reset(void)
{
}
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 2c6e35b5aafe..7df7be4a1bdc 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -283,44 +283,37 @@ void kvm_s390_crypto_reset(void)
}
}
-static int kvm_s390_configure_mempath_backing(KVMState *s)
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
{
- size_t path_psize = qemu_getrampagesize();
-
- if (path_psize == 4 * KiB) {
- return 0;
+ if (pagesize == 4 * KiB) {
+ return;
}
if (!hpage_1m_allowed()) {
- error_report("This QEMU machine does not support huge page "
- "mappings");
- return -EINVAL;
+ error_setg(errp, "This QEMU machine does not support huge page "
+ "mappings");
+ return;
}
- if (path_psize != 1 * MiB) {
- error_report("Memory backing with 2G pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (pagesize != 1 * MiB) {
+ error_setg(errp, "Memory backing with 2G pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
- if (kvm_vm_enable_cap(s, KVM_CAP_S390_HPAGE_1M, 0)) {
- error_report("Memory backing with 1M pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (kvm_vm_enable_cap(kvm_state, KVM_CAP_S390_HPAGE_1M, 0)) {
+ error_setg(errp, "Memory backing with 1M pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
cap_hpage_1m = 1;
- return 0;
}
int kvm_arch_init(MachineState *ms, KVMState *s)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
- if (kvm_s390_configure_mempath_backing(s)) {
- return -EINVAL;
- }
-
mc->default_cpu_type = S390_CPU_TYPE_NAME("host");
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
index 6e52287da3f0..caf985955ba5 100644
--- a/target/s390x/kvm_s390x.h
+++ b/target/s390x/kvm_s390x.h
@@ -36,6 +36,7 @@ int kvm_s390_cmma_active(void);
void kvm_s390_cmma_reset(void);
void kvm_s390_reset_vcpu(S390CPU *cpu);
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit);
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void kvm_s390_crypto_reset(void);
void kvm_s390_restart_interrupt(S390CPU *cpu);
void kvm_s390_stop_interrupt(S390CPU *cpu);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 18/19] s390x/kvm: Configure page size after memory has actually been initialized
2019-04-25 13:21 ` [Qemu-devel] [PULL 18/19] s390x/kvm: Configure page size after memory has actually been initialized Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, Cornelia Huck, qemu-devel, David Hildenbrand
From: David Hildenbrand <david@redhat.com>
Right now we configure the pagesize quite early, when initializing KVM.
This is long before system memory is actually allocated via
memory_region_allocate_system_memory(), and therefore memory backends
marked as mapped.
Instead, let's configure the maximum page size after initializing
memory in s390_memory_init(). cap_hpage_1m is still properly
configured before creating any CPUs, and therefore before configuring
the CPU model and eventually enabling CMMA.
This is not a fix but rather a preparation for the future, when initial
memory might reside on memory backends (not the case for s390x right now)
We will replace qemu_getrampagesize() soon by a function that will always
return the maximum page size (not the minimum page size, which only
works by pure luck so far, as there are no memory backends).
Acked-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190417113143.5551-2-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 12 ++++++++++++
target/s390x/cpu.c | 7 +++++++
target/s390x/cpu.h | 1 +
target/s390x/kvm-stub.c | 4 ++++
target/s390x/kvm.c | 35 ++++++++++++++---------------------
target/s390x/kvm_s390x.h | 1 +
6 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d11069b860b4..3be567965736 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -15,6 +15,7 @@
#include "cpu.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
+#include "exec/ram_addr.h"
#include "hw/s390x/s390-virtio-hcall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
@@ -163,6 +164,7 @@ static void s390_memory_init(ram_addr_t mem_size)
MemoryRegion *sysmem = get_system_memory();
ram_addr_t chunk, offset = 0;
unsigned int number = 0;
+ Error *local_err = NULL;
gchar *name;
/* allocate RAM for core */
@@ -182,6 +184,15 @@ static void s390_memory_init(ram_addr_t mem_size)
}
g_free(name);
+ /*
+ * Configure the maximum page size. As no memory devices were created
+ * yet, this is the page size of initial memory only.
+ */
+ s390_set_max_pagesize(qemu_getrampagesize(), &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ exit(EXIT_FAILURE);
+ }
/* Initialize storage key device */
s390_skeys_init();
/* Initialize storage attributes device */
@@ -253,6 +264,7 @@ static void ccw_init(MachineState *machine)
DeviceState *dev;
s390_sclp_init();
+ /* init memory + setup max page size. Required for the CPU model */
s390_memory_init(machine->ram_size);
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 698dd9cb82ab..b58ef0a8ef62 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -399,6 +399,13 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+ if (kvm_enabled()) {
+ kvm_s390_set_max_pagesize(pagesize, errp);
+ }
+}
+
void s390_cmma_reset(void)
{
if (kvm_enabled()) {
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d8990c405a5d..7305cacc7b77 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -734,6 +734,7 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
/* cpu.c */
void s390_crypto_reset(void);
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void s390_cmma_reset(void);
void s390_enable_css_support(S390CPU *cpu);
int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
index bf7795e47a1c..22b4514ca68c 100644
--- a/target/s390x/kvm-stub.c
+++ b/target/s390x/kvm-stub.c
@@ -93,6 +93,10 @@ int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+}
+
void kvm_s390_crypto_reset(void)
{
}
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 2c6e35b5aafe..7df7be4a1bdc 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -283,44 +283,37 @@ void kvm_s390_crypto_reset(void)
}
}
-static int kvm_s390_configure_mempath_backing(KVMState *s)
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
{
- size_t path_psize = qemu_getrampagesize();
-
- if (path_psize == 4 * KiB) {
- return 0;
+ if (pagesize == 4 * KiB) {
+ return;
}
if (!hpage_1m_allowed()) {
- error_report("This QEMU machine does not support huge page "
- "mappings");
- return -EINVAL;
+ error_setg(errp, "This QEMU machine does not support huge page "
+ "mappings");
+ return;
}
- if (path_psize != 1 * MiB) {
- error_report("Memory backing with 2G pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (pagesize != 1 * MiB) {
+ error_setg(errp, "Memory backing with 2G pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
- if (kvm_vm_enable_cap(s, KVM_CAP_S390_HPAGE_1M, 0)) {
- error_report("Memory backing with 1M pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (kvm_vm_enable_cap(kvm_state, KVM_CAP_S390_HPAGE_1M, 0)) {
+ error_setg(errp, "Memory backing with 1M pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
cap_hpage_1m = 1;
- return 0;
}
int kvm_arch_init(MachineState *ms, KVMState *s)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
- if (kvm_s390_configure_mempath_backing(s)) {
- return -EINVAL;
- }
-
mc->default_cpu_type = S390_CPU_TYPE_NAME("host");
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
index 6e52287da3f0..caf985955ba5 100644
--- a/target/s390x/kvm_s390x.h
+++ b/target/s390x/kvm_s390x.h
@@ -36,6 +36,7 @@ int kvm_s390_cmma_active(void);
void kvm_s390_cmma_reset(void);
void kvm_s390_reset_vcpu(S390CPU *cpu);
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit);
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void kvm_s390_crypto_reset(void);
void kvm_s390_restart_interrupt(S390CPU *cpu);
void kvm_s390_stop_interrupt(S390CPU *cpu);
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 19/19] exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize()
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (18 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 18/19] s390x/kvm: Configure page size after memory has actually been initialized Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
2019-04-25 13:21 ` Cornelia Huck
2019-04-26 13:29 ` [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Peter Maydell
20 siblings, 1 reply; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, qemu-devel, David Hildenbrand, Cornelia Huck
From: David Hildenbrand <david@redhat.com>
Rename qemu_getrampagesize() to qemu_minrampagesize(). While at it,
properly rename find_max_supported_pagesize() to
find_min_backend_pagesize().
s390x is actually interested into the maximum ram pagesize, so
introduce and use qemu_maxrampagesize().
Add a TODO, indicating that looking at any mapped memory backends is not
100% correct in some cases.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190417113143.5551-3-david@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
exec.c | 44 ++++++++++++++++++++++++++++++++++----
hw/ppc/spapr_caps.c | 4 ++--
hw/s390x/s390-virtio-ccw.c | 2 +-
hw/vfio/spapr.c | 2 +-
include/exec/ram_addr.h | 3 ++-
target/ppc/kvm.c | 2 +-
6 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/exec.c b/exec.c
index 2646207661d4..bb1dff423aaf 100644
--- a/exec.c
+++ b/exec.c
@@ -1688,7 +1688,7 @@ void ram_block_dump(Monitor *mon)
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
-static int find_max_supported_pagesize(Object *obj, void *opaque)
+static int find_min_backend_pagesize(Object *obj, void *opaque)
{
long *hpsize_min = opaque;
@@ -1704,7 +1704,27 @@ static int find_max_supported_pagesize(Object *obj, void *opaque)
return 0;
}
-long qemu_getrampagesize(void)
+static int find_max_backend_pagesize(Object *obj, void *opaque)
+{
+ long *hpsize_max = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ long hpsize = host_memory_backend_pagesize(backend);
+
+ if (host_memory_backend_is_mapped(backend) && (hpsize > *hpsize_max)) {
+ *hpsize_max = hpsize;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * TODO: We assume right now that all mapped host memory backends are
+ * used as RAM, however some might be used for different purposes.
+ */
+long qemu_minrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
@@ -1724,7 +1744,7 @@ long qemu_getrampagesize(void)
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
- object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
+ object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
@@ -1747,8 +1767,24 @@ long qemu_getrampagesize(void)
return hpsize;
}
+
+long qemu_maxrampagesize(void)
+{
+ long pagesize = qemu_mempath_getpagesize(mem_path);
+ Object *memdev_root = object_resolve_path("/objects", NULL);
+
+ if (memdev_root) {
+ object_child_foreach(memdev_root, find_max_backend_pagesize,
+ &pagesize);
+ }
+ return pagesize;
+}
#else
-long qemu_getrampagesize(void)
+long qemu_minrampagesize(void)
+{
+ return getpagesize();
+}
+long qemu_maxrampagesize(void)
{
return getpagesize();
}
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index edc5ed0e0c4e..9b1c10baa6c5 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -347,7 +347,7 @@ static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
warn_report("Many guests require at least 64kiB hpt-max-page-size");
}
- spapr_check_pagesize(spapr, qemu_getrampagesize(), errp);
+ spapr_check_pagesize(spapr, qemu_minrampagesize(), errp);
}
static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
@@ -609,7 +609,7 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
uint8_t mps;
if (kvmppc_hpt_needs_host_contiguous_pages()) {
- mps = ctz64(qemu_getrampagesize());
+ mps = ctz64(qemu_minrampagesize());
} else {
mps = 34; /* allow everything up to 16GiB, i.e. everything */
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 3be567965736..7e256d3d31b8 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -188,7 +188,7 @@ static void s390_memory_init(ram_addr_t mem_size)
* Configure the maximum page size. As no memory devices were created
* yet, this is the page size of initial memory only.
*/
- s390_set_max_pagesize(qemu_getrampagesize(), &local_err);
+ s390_set_max_pagesize(qemu_maxrampagesize(), &local_err);
if (local_err) {
error_report_err(local_err);
exit(EXIT_FAILURE);
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 57fe758e5441..96c0ad9d9b7e 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -148,7 +148,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, bits_total, bits_per_level, max_levels;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
- long rampagesize = qemu_getrampagesize();
+ long rampagesize = qemu_minrampagesize();
/*
* The host might not support the guest supported IOMMU page size,
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 9ecd911c3e78..139ad79390fa 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -73,7 +73,8 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
bool ramblock_is_pmem(RAMBlock *rb);
-long qemu_getrampagesize(void);
+long qemu_minrampagesize(void);
+long qemu_maxrampagesize(void);
/**
* qemu_ram_alloc_from_file,
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2427c8ee13ae..59d92c42751e 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2136,7 +2136,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
/* Find the largest hardware supported page size that's less than
* or equal to the (logical) backing page size of guest RAM */
kvm_get_smmu_info(&info, &error_fatal);
- rampagesize = qemu_getrampagesize();
+ rampagesize = qemu_minrampagesize();
best_page_shift = 0;
for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [Qemu-devel] [PULL 19/19] exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize()
2019-04-25 13:21 ` [Qemu-devel] [PULL 19/19] exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize() Cornelia Huck
@ 2019-04-25 13:21 ` Cornelia Huck
0 siblings, 0 replies; 48+ messages in thread
From: Cornelia Huck @ 2019-04-25 13:21 UTC (permalink / raw)
To: Peter Maydell; +Cc: qemu-s390x, Cornelia Huck, qemu-devel, David Hildenbrand
From: David Hildenbrand <david@redhat.com>
Rename qemu_getrampagesize() to qemu_minrampagesize(). While at it,
properly rename find_max_supported_pagesize() to
find_min_backend_pagesize().
s390x is actually interested into the maximum ram pagesize, so
introduce and use qemu_maxrampagesize().
Add a TODO, indicating that looking at any mapped memory backends is not
100% correct in some cases.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190417113143.5551-3-david@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
exec.c | 44 ++++++++++++++++++++++++++++++++++----
hw/ppc/spapr_caps.c | 4 ++--
hw/s390x/s390-virtio-ccw.c | 2 +-
hw/vfio/spapr.c | 2 +-
include/exec/ram_addr.h | 3 ++-
target/ppc/kvm.c | 2 +-
6 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/exec.c b/exec.c
index 2646207661d4..bb1dff423aaf 100644
--- a/exec.c
+++ b/exec.c
@@ -1688,7 +1688,7 @@ void ram_block_dump(Monitor *mon)
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
-static int find_max_supported_pagesize(Object *obj, void *opaque)
+static int find_min_backend_pagesize(Object *obj, void *opaque)
{
long *hpsize_min = opaque;
@@ -1704,7 +1704,27 @@ static int find_max_supported_pagesize(Object *obj, void *opaque)
return 0;
}
-long qemu_getrampagesize(void)
+static int find_max_backend_pagesize(Object *obj, void *opaque)
+{
+ long *hpsize_max = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ long hpsize = host_memory_backend_pagesize(backend);
+
+ if (host_memory_backend_is_mapped(backend) && (hpsize > *hpsize_max)) {
+ *hpsize_max = hpsize;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * TODO: We assume right now that all mapped host memory backends are
+ * used as RAM, however some might be used for different purposes.
+ */
+long qemu_minrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
@@ -1724,7 +1744,7 @@ long qemu_getrampagesize(void)
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
- object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
+ object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
@@ -1747,8 +1767,24 @@ long qemu_getrampagesize(void)
return hpsize;
}
+
+long qemu_maxrampagesize(void)
+{
+ long pagesize = qemu_mempath_getpagesize(mem_path);
+ Object *memdev_root = object_resolve_path("/objects", NULL);
+
+ if (memdev_root) {
+ object_child_foreach(memdev_root, find_max_backend_pagesize,
+ &pagesize);
+ }
+ return pagesize;
+}
#else
-long qemu_getrampagesize(void)
+long qemu_minrampagesize(void)
+{
+ return getpagesize();
+}
+long qemu_maxrampagesize(void)
{
return getpagesize();
}
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index edc5ed0e0c4e..9b1c10baa6c5 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -347,7 +347,7 @@ static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
warn_report("Many guests require at least 64kiB hpt-max-page-size");
}
- spapr_check_pagesize(spapr, qemu_getrampagesize(), errp);
+ spapr_check_pagesize(spapr, qemu_minrampagesize(), errp);
}
static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
@@ -609,7 +609,7 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
uint8_t mps;
if (kvmppc_hpt_needs_host_contiguous_pages()) {
- mps = ctz64(qemu_getrampagesize());
+ mps = ctz64(qemu_minrampagesize());
} else {
mps = 34; /* allow everything up to 16GiB, i.e. everything */
}
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 3be567965736..7e256d3d31b8 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -188,7 +188,7 @@ static void s390_memory_init(ram_addr_t mem_size)
* Configure the maximum page size. As no memory devices were created
* yet, this is the page size of initial memory only.
*/
- s390_set_max_pagesize(qemu_getrampagesize(), &local_err);
+ s390_set_max_pagesize(qemu_maxrampagesize(), &local_err);
if (local_err) {
error_report_err(local_err);
exit(EXIT_FAILURE);
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 57fe758e5441..96c0ad9d9b7e 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -148,7 +148,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, bits_total, bits_per_level, max_levels;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
- long rampagesize = qemu_getrampagesize();
+ long rampagesize = qemu_minrampagesize();
/*
* The host might not support the guest supported IOMMU page size,
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 9ecd911c3e78..139ad79390fa 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -73,7 +73,8 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
bool ramblock_is_pmem(RAMBlock *rb);
-long qemu_getrampagesize(void);
+long qemu_minrampagesize(void);
+long qemu_maxrampagesize(void);
/**
* qemu_ram_alloc_from_file,
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2427c8ee13ae..59d92c42751e 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2136,7 +2136,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
/* Find the largest hardware supported page size that's less than
* or equal to the (logical) backing page size of guest RAM */
kvm_get_smmu_info(&info, &error_fatal);
- rampagesize = qemu_getrampagesize();
+ rampagesize = qemu_minrampagesize();
best_page_shift = 0;
for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
--
2.17.2
^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1
2019-04-25 13:21 [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Cornelia Huck
` (19 preceding siblings ...)
2019-04-25 13:21 ` [Qemu-devel] [PULL 19/19] exec: Introduce qemu_maxrampagesize() and rename qemu_getrampagesize() Cornelia Huck
@ 2019-04-26 13:29 ` Peter Maydell
2019-04-26 13:29 ` Peter Maydell
20 siblings, 1 reply; 48+ messages in thread
From: Peter Maydell @ 2019-04-26 13:29 UTC (permalink / raw)
To: Cornelia Huck; +Cc: qemu-s390x, QEMU Developers
On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
>
> The following changes since commit 3284aa128153750f14a61e8a96fd085e6f2999b6:
>
> Merge remote-tracking branch 'remotes/lersek/tags/edk2-pull-2019-04-22' into staging (2019-04-24 13:19:41 +0100)
>
> are available in the Git repository at:
>
> https://github.com/cohuck/qemu tags/s390x-20190425
>
> for you to fetch changes up to 41c3d4269b1c18d12d33c5bf089dace25d08e82e:
>
> Merge tag 's390-ccw-bios-2019-04-12' into s390-next-staging (2019-04-25 14:09:20 +0200)
>
> ----------------------------------------------------------------
> - properly detect page size of initial memory
> - support for IPL (boot) from ECKD DASD passed through via vfio-ccw
>
> ----------------------------------------------------------------
>
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/4.1
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1
2019-04-26 13:29 ` [Qemu-devel] [PULL 00/19] first batch of s390x patches for 4.1 Peter Maydell
@ 2019-04-26 13:29 ` Peter Maydell
0 siblings, 0 replies; 48+ messages in thread
From: Peter Maydell @ 2019-04-26 13:29 UTC (permalink / raw)
To: Cornelia Huck; +Cc: qemu-s390x, QEMU Developers
On Thu, 25 Apr 2019 at 14:21, Cornelia Huck <cohuck@redhat.com> wrote:
>
> The following changes since commit 3284aa128153750f14a61e8a96fd085e6f2999b6:
>
> Merge remote-tracking branch 'remotes/lersek/tags/edk2-pull-2019-04-22' into staging (2019-04-24 13:19:41 +0100)
>
> are available in the Git repository at:
>
> https://github.com/cohuck/qemu tags/s390x-20190425
>
> for you to fetch changes up to 41c3d4269b1c18d12d33c5bf089dace25d08e82e:
>
> Merge tag 's390-ccw-bios-2019-04-12' into s390-next-staging (2019-04-25 14:09:20 +0200)
>
> ----------------------------------------------------------------
> - properly detect page size of initial memory
> - support for IPL (boot) from ECKD DASD passed through via vfio-ccw
>
> ----------------------------------------------------------------
>
Applied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/4.1
for any user-visible changes.
-- PMM
^ permalink raw reply [flat|nested] 48+ messages in thread