summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--accel/kvm/kvm-all.c6
-rw-r--r--block/nbd-client.c102
-rwxr-xr-xconfigure21
-rw-r--r--default-configs/s390x-softmmu.mak2
-rw-r--r--fsdev/Makefile.objs9
-rw-r--r--hw/9pfs/Makefile.objs2
-rw-r--r--hw/Makefile.objs2
-rw-r--r--hw/intc/s390_flic_kvm.c1
-rw-r--r--hw/pci/pci-stub.c14
-rw-r--r--hw/pci/pci.c2
-rw-r--r--hw/s390x/Makefile.objs3
-rw-r--r--hw/s390x/css.c16
-rw-r--r--hw/s390x/ipl.c2
-rw-r--r--hw/s390x/s390-pci-bus.c18
-rw-r--r--hw/s390x/s390-pci-bus.h12
-rw-r--r--hw/s390x/s390-pci-inst.c4
-rw-r--r--hw/s390x/s390-pci-stub.c76
-rw-r--r--hw/s390x/s390-skeys-kvm.c4
-rw-r--r--hw/s390x/s390-skeys.c4
-rw-r--r--hw/s390x/s390-stattrib-kvm.c5
-rw-r--r--hw/s390x/s390-stattrib.c6
-rw-r--r--hw/s390x/s390-virtio-ccw.c54
-rw-r--r--hw/s390x/s390-virtio.c7
-rw-r--r--hw/s390x/s390-virtio.h2
-rw-r--r--hw/s390x/sclp.c42
-rw-r--r--hw/s390x/sclpcpu.c1
-rw-r--r--hw/watchdog/wdt_diag288.c1
-rw-r--r--include/block/nbd.h4
-rw-r--r--include/hw/compat.h3
-rw-r--r--include/hw/pci/pci.h2
-rw-r--r--include/hw/s390x/css.h4
-rw-r--r--include/hw/s390x/ioinst.h12
-rw-r--r--include/hw/s390x/sclp.h17
-rw-r--r--nbd/client.c21
-rw-r--r--nbd/nbd-internal.h33
-rw-r--r--pc-bios/s390-ccw.imgbin30520 -> 26416 bytes
-rw-r--r--pc-bios/s390-ccw/cio.h2
-rw-r--r--slirp/socket.c39
-rw-r--r--target/s390x/Makefile.objs1
-rw-r--r--target/s390x/arch_dump.c2
-rw-r--r--target/s390x/cc_helper.c1
-rw-r--r--target/s390x/cpu.c89
-rw-r--r--target/s390x/cpu.h759
-rw-r--r--target/s390x/cpu_models.c11
-rw-r--r--target/s390x/diag.c8
-rw-r--r--target/s390x/excp_helper.c15
-rw-r--r--target/s390x/fpu_helper.c1
-rw-r--r--target/s390x/gdbstub.c1
-rw-r--r--target/s390x/helper.c49
-rw-r--r--target/s390x/int_helper.c1
-rw-r--r--target/s390x/internal.h391
-rw-r--r--target/s390x/interrupt.c2
-rw-r--r--target/s390x/ioinst.c17
-rw-r--r--target/s390x/kvm-stub.c111
-rw-r--r--target/s390x/kvm.c76
-rw-r--r--target/s390x/kvm_s390x.h47
-rw-r--r--target/s390x/machine.c2
-rw-r--r--target/s390x/mem_helper.c12
-rw-r--r--target/s390x/misc_helper.c18
-rw-r--r--target/s390x/mmu_helper.c2
-rw-r--r--target/s390x/translate.c1
-rw-r--r--tests/Makefile.include12
-rw-r--r--tests/boot-sector.c61
-rw-r--r--tests/pxe-test.c7
-rwxr-xr-xtests/qemu-iotests/083136
-rw-r--r--tests/qemu-iotests/083.out149
-rwxr-xr-xtests/qemu-iotests/19423
-rw-r--r--tests/qemu-iotests/194.out11
-rw-r--r--tests/qemu-iotests/common.filter4
-rwxr-xr-xtests/qemu-iotests/nbd-fault-injector.py4
-rw-r--r--tests/test-filter-mirror.c14
-rw-r--r--tests/test-filter-redirector.c32
-rw-r--r--tests/test-netfilter.c11
74 files changed, 1599 insertions, 1039 deletions
diff --git a/VERSION b/VERSION
index 46891619f3..e8bd316d0f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.9.94
+2.10.50
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index 46ce479dc3..f85553a851 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -1248,7 +1248,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
int virq;
MSIMessage msg = {0, 0};
- if (dev) {
+ if (pci_available && dev) {
msg = pci_get_msi_message(dev, vector);
}
@@ -1271,7 +1271,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
- if (kvm_msi_devid_required()) {
+ if (pci_available && kvm_msi_devid_required()) {
kroute.flags = KVM_MSI_VALID_DEVID;
kroute.u.msi.devid = pci_requester_id(dev);
}
@@ -1309,7 +1309,7 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
- if (kvm_msi_devid_required()) {
+ if (pci_available && kvm_msi_devid_required()) {
kroute.flags = KVM_MSI_VALID_DEVID;
kroute.u.msi.devid = pci_requester_id(dev);
}
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 25bcaa2346..f0dbea24d3 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -34,7 +34,7 @@
#define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs))
#define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs))
-static void nbd_recv_coroutines_enter_all(NBDClientSession *s)
+static void nbd_recv_coroutines_wake_all(NBDClientSession *s)
{
int i;
@@ -112,7 +112,7 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
}
s->quit = true;
- nbd_recv_coroutines_enter_all(s);
+ nbd_recv_coroutines_wake_all(s);
s->read_reply_co = NULL;
}
@@ -144,12 +144,12 @@ static int nbd_co_send_request(BlockDriverState *bs,
request->handle = INDEX_TO_HANDLE(s, i);
if (s->quit) {
- qemu_co_mutex_unlock(&s->send_mutex);
- return -EIO;
+ rc = -EIO;
+ goto err;
}
if (!s->ioc) {
- qemu_co_mutex_unlock(&s->send_mutex);
- return -EPIPE;
+ rc = -EPIPE;
+ goto err;
}
if (qiov) {
@@ -166,8 +166,13 @@ static int nbd_co_send_request(BlockDriverState *bs,
} else {
rc = nbd_send_request(s->ioc, request);
}
+
+err:
if (rc < 0) {
s->quit = true;
+ s->requests[i].coroutine = NULL;
+ s->in_flight--;
+ qemu_co_queue_next(&s->free_sema);
}
qemu_co_mutex_unlock(&s->send_mutex);
return rc;
@@ -201,13 +206,6 @@ static void nbd_co_receive_reply(NBDClientSession *s,
/* Tell the read handler to read another header. */
s->reply.handle = 0;
}
-}
-
-static void nbd_coroutine_end(BlockDriverState *bs,
- NBDRequest *request)
-{
- NBDClientSession *s = nbd_get_client_session(bs);
- int i = HANDLE_TO_INDEX(s, request->handle);
s->requests[i].coroutine = NULL;
@@ -222,29 +220,40 @@ static void nbd_coroutine_end(BlockDriverState *bs,
qemu_co_mutex_unlock(&s->send_mutex);
}
+static int nbd_co_request(BlockDriverState *bs,
+ NBDRequest *request,
+ QEMUIOVector *qiov)
+{
+ NBDClientSession *client = nbd_get_client_session(bs);
+ NBDReply reply;
+ int ret;
+
+ assert(!qiov || request->type == NBD_CMD_WRITE ||
+ request->type == NBD_CMD_READ);
+ ret = nbd_co_send_request(bs, request,
+ request->type == NBD_CMD_WRITE ? qiov : NULL);
+ if (ret < 0) {
+ reply.error = -ret;
+ } else {
+ nbd_co_receive_reply(client, request, &reply,
+ request->type == NBD_CMD_READ ? qiov : NULL);
+ }
+ return -reply.error;
+}
+
int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
uint64_t bytes, QEMUIOVector *qiov, int flags)
{
- NBDClientSession *client = nbd_get_client_session(bs);
NBDRequest request = {
.type = NBD_CMD_READ,
.from = offset,
.len = bytes,
};
- NBDReply reply;
- ssize_t ret;
assert(bytes <= NBD_MAX_BUFFER_SIZE);
assert(!flags);
- ret = nbd_co_send_request(bs, &request, NULL);
- if (ret < 0) {
- reply.error = -ret;
- } else {
- nbd_co_receive_reply(client, &request, &reply, qiov);
- }
- nbd_coroutine_end(bs, &request);
- return -reply.error;
+ return nbd_co_request(bs, &request, qiov);
}
int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
@@ -256,8 +265,6 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
.from = offset,
.len = bytes,
};
- NBDReply reply;
- ssize_t ret;
if (flags & BDRV_REQ_FUA) {
assert(client->info.flags & NBD_FLAG_SEND_FUA);
@@ -266,27 +273,18 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
assert(bytes <= NBD_MAX_BUFFER_SIZE);
- ret = nbd_co_send_request(bs, &request, qiov);
- if (ret < 0) {
- reply.error = -ret;
- } else {
- nbd_co_receive_reply(client, &request, &reply, NULL);
- }
- nbd_coroutine_end(bs, &request);
- return -reply.error;
+ return nbd_co_request(bs, &request, qiov);
}
int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
int bytes, BdrvRequestFlags flags)
{
- ssize_t ret;
NBDClientSession *client = nbd_get_client_session(bs);
NBDRequest request = {
.type = NBD_CMD_WRITE_ZEROES,
.from = offset,
.len = bytes,
};
- NBDReply reply;
if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
return -ENOTSUP;
@@ -300,22 +298,13 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
request.flags |= NBD_CMD_FLAG_NO_HOLE;
}
- ret = nbd_co_send_request(bs, &request, NULL);
- if (ret < 0) {
- reply.error = -ret;
- } else {
- nbd_co_receive_reply(client, &request, &reply, NULL);
- }
- nbd_coroutine_end(bs, &request);
- return -reply.error;
+ return nbd_co_request(bs, &request, NULL);
}
int nbd_client_co_flush(BlockDriverState *bs)
{
NBDClientSession *client = nbd_get_client_session(bs);
NBDRequest request = { .type = NBD_CMD_FLUSH };
- NBDReply reply;
- ssize_t ret;
if (!(client->info.flags & NBD_FLAG_SEND_FLUSH)) {
return 0;
@@ -324,14 +313,7 @@ int nbd_client_co_flush(BlockDriverState *bs)
request.from = 0;
request.len = 0;
- ret = nbd_co_send_request(bs, &request, NULL);
- if (ret < 0) {
- reply.error = -ret;
- } else {
- nbd_co_receive_reply(client, &request, &reply, NULL);
- }
- nbd_coroutine_end(bs, &request);
- return -reply.error;
+ return nbd_co_request(bs, &request, NULL);
}
int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
@@ -342,22 +324,12 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
.from = offset,
.len = bytes,
};
- NBDReply reply;
- ssize_t ret;
if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
return 0;
}
- ret = nbd_co_send_request(bs, &request, NULL);
- if (ret < 0) {
- reply.error = -ret;
- } else {
- nbd_co_receive_reply(client, &request, &reply, NULL);
- }
- nbd_coroutine_end(bs, &request);
- return -reply.error;
-
+ return nbd_co_request(bs, &request, NULL);
}
void nbd_client_detach_aio_context(BlockDriverState *bs)
diff --git a/configure b/configure
index dd73cce62f..fb7e34a901 100755
--- a/configure
+++ b/configure
@@ -240,6 +240,11 @@ supported_target() {
return 1
}
+
+ld_has() {
+ $ld --help 2>/dev/null | grep ".$1" >/dev/null 2>&1
+}
+
# default parameters
source_path=$(dirname "$0")
cpu=""
@@ -5043,7 +5048,7 @@ fi
# Use ASLR, no-SEH and DEP if available
if test "$mingw32" = "yes" ; then
for flag in --dynamicbase --no-seh --nxcompat; do
- if $ld --help 2>/dev/null | grep ".$flag" >/dev/null 2>/dev/null ; then
+ if ld_has $flag ; then
LDFLAGS="-Wl,$flag $LDFLAGS"
fi
done
@@ -6522,6 +6527,20 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
ldflags="$ldflags $textseg_ldflags"
fi
+# Newer kernels on s390 check for an S390_PGSTE program header and
+# enable the pgste page table extensions in that case. This makes
+# the vm.allocate_pgste sysctl unnecessary. We enable this program
+# header if
+# - we build on s390x
+# - we build the system emulation for s390x (qemu-system-s390x)
+# - KVM is enabled
+# - the linker supports --s390-pgste
+if test "$TARGET_ARCH" = "s390x" -a "$target_softmmu" = "yes" -a "$ARCH" = "s390x" -a "$kvm" = "yes"; then
+ if ld_has --s390-pgste ; then
+ ldflags="-Wl,--s390-pgste $ldflags"
+ fi
+fi
+
echo "LDFLAGS+=$ldflags" >> $config_target_mak
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index 51191b77df..6ab2bc65ac 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -1,5 +1,5 @@
CONFIG_PCI=y
-CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_PCI=$(CONFIG_PCI)
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
CONFIG_VIRTIO=y
CONFIG_SCLPCONSOLE=y
diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs
index 659df6e187..fb38017c0b 100644
--- a/fsdev/Makefile.objs
+++ b/fsdev/Makefile.objs
@@ -1,10 +1,7 @@
-ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
-# only pull in the actual virtio-9p device if we also enabled virtio.
-common-obj-y = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
-else
-common-obj-y = qemu-fsdev-dummy.o
-endif
+# only pull in the actual 9p backend if we also enabled virtio or xen.
+common-obj-$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN))) = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
+common-obj-$(call lnot,$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN)))) = qemu-fsdev-dummy.o
common-obj-y += qemu-fsdev-opts.o qemu-fsdev-throttle.o
# Toplevel always builds this; targets without virtio will put it in
diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs
index cab5e942ed..fd90b62900 100644
--- a/hw/9pfs/Makefile.objs
+++ b/hw/9pfs/Makefile.objs
@@ -7,4 +7,4 @@ common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o
common-obj-y += 9p-proxy.o
common-obj-$(CONFIG_XEN) += xen-9p-backend.o
-obj-y += virtio-9p-device.o
+obj-$(CONFIG_VIRTIO) += virtio-9p-device.o
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index a2c61f6b09..cf4cb2010b 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,4 +1,4 @@
-devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/
+devices-dirs-$(call land,$(CONFIG_VIRTFS),$(call lor,$(CONFIG_VIRTIO),$(CONFIG_XEN))) += 9pfs/
devices-dirs-$(CONFIG_SOFTMMU) += acpi/
devices-dirs-$(CONFIG_SOFTMMU) += adc/
devices-dirs-$(CONFIG_SOFTMMU) += audio/
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index be3fd00a57..7ead17ac3e 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -13,6 +13,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
+#include "kvm_s390x.h"
#include <sys/ioctl.h>
#include "qemu/error-report.h"
#include "qapi/error.h"
diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c
index ecad664946..d5ce00748e 100644
--- a/hw/pci/pci-stub.c
+++ b/hw/pci/pci-stub.c
@@ -27,6 +27,7 @@
#include "hw/pci/msi.h"
bool msi_nonbroken;
+bool pci_available;
PciInfoList *qmp_query_pci(Error **errp)
{
@@ -38,3 +39,16 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "PCI devices not supported\n");
}
+
+/* kvm-all wants this */
+MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
+{
+ g_assert(false);
+ return (MSIMessage){};
+}
+
+uint16_t pci_requester_id(PCIDevice *dev)
+{
+ g_assert(false);
+ return 0;
+}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 258fbe51e2..26f346db2c 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -49,6 +49,8 @@
# define PCI_DPRINTF(format, ...) do { } while (0)
#endif
+bool pci_available = true;
+
static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index b2aade2466..7ee19d3abc 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -11,7 +11,8 @@ obj-y += 3270-ccw.o
obj-y += virtio-ccw.o
obj-y += css-bridge.o
obj-y += ccw-device.o
-obj-y += s390-pci-bus.o s390-pci-inst.o
+obj-$(CONFIG_PCI) += s390-pci-bus.o s390-pci-inst.o
+obj-$(call lnot,$(CONFIG_PCI)) += s390-pci-stub.o
obj-y += s390-skeys.o
obj-y += s390-stattrib.o
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1880b1a0ff..901dc6a0f3 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1750,10 +1750,10 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid)
}
/* We don't really use a channel path, so we're done here. */
- css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT,
+ css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 1,
channel_subsys.max_cssid > 0 ? 1 : 0, chpid);
if (channel_subsys.max_cssid > 0) {
- css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8);
+ css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 1, 0, real_cssid << 8);
}
return 0;
}
@@ -2033,7 +2033,8 @@ void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
}
}
-void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
+void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,
+ int chain, uint16_t rsid)
{
CrwContainer *crw_cont;
@@ -2045,6 +2046,9 @@ void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
return;
}
crw_cont->crw.flags = (rsc << 8) | erc;
+ if (solicited) {
+ crw_cont->crw.flags |= CRW_FLAGS_MASK_S;
+ }
if (chain) {
crw_cont->crw.flags |= CRW_FLAGS_MASK_C;
}
@@ -2091,9 +2095,9 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
}
chain_crw = (channel_subsys.max_ssid > 0) ||
(channel_subsys.max_cssid > 0);
- css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid);
+ css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, chain_crw ? 1 : 0, schid);
if (chain_crw) {
- css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
+ css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0, 0,
(guest_cssid << 8) | (ssid << 4));
}
/* RW_ERC_IPI --> clear pending interrupts */
@@ -2108,7 +2112,7 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
void css_generate_css_crws(uint8_t cssid)
{
if (!channel_subsys.sei_pending) {
- css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
+ css_queue_crw(CRW_RSC_CSS, CRW_ERC_EVENT, 0, 0, cssid);
}
channel_subsys.sei_pending = true;
}
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index cc360031ef..0d06fc12b6 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -442,6 +442,8 @@ static void s390_ipl_class_init(ObjectClass *klass, void *data)
dc->reset = s390_ipl_reset;
dc->vmsd = &vmstate_ipl;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ /* Reason: Loads the ROMs and thus can only be used one time - internally */
+ dc->user_creatable = false;
}
static const TypeInfo s390_ipl_info = {
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 61cfd2138f..0a31a4ae88 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -47,7 +47,7 @@ S390pciState *s390_get_phb(void)
return phb;
}
-int chsc_sei_nt2_get_event(void *res)
+int pci_chsc_sei_nt2_get_event(void *res)
{
ChscSeiNt2Res *nt2_res = (ChscSeiNt2Res *)res;
PciCcdfAvail *accdf;
@@ -87,7 +87,7 @@ int chsc_sei_nt2_get_event(void *res)
return rc;
}
-int chsc_sei_nt2_have_event(void)
+int pci_chsc_sei_nt2_have_event(void)
{
S390pciState *s = s390_get_phb();
@@ -122,16 +122,11 @@ S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid)
void s390_pci_sclp_configure(SCCB *sccb)
{
- PciCfgSccb *psccb = (PciCfgSccb *)sccb;
+ IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid));
uint16_t rc;
- if (be16_to_cpu(sccb->h.length) < 16) {
- rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
- goto out;
- }
-
if (!pbdev) {
DPRINTF("sclp config no dev found\n");
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
@@ -155,16 +150,11 @@ out:
void s390_pci_sclp_deconfigure(SCCB *sccb)
{
- PciCfgSccb *psccb = (PciCfgSccb *)sccb;
+ IoaCfgSccb *psccb = (IoaCfgSccb *)sccb;
S390PCIBusDevice *pbdev = s390_pci_find_dev_by_fid(s390_get_phb(),
be32_to_cpu(psccb->aid));
uint16_t rc;
- if (be16_to_cpu(sccb->h.length) < 16) {
- rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
- goto out;
- }
-
if (!pbdev) {
DPRINTF("sclp deconfig no dev found\n");
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 67af2c12ff..bd636abc28 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -244,14 +244,6 @@ typedef struct ChscSeiNt2Res {
uint8_t ccdf[4016];
} QEMU_PACKED ChscSeiNt2Res;
-typedef struct PciCfgSccb {
- SCCBHeader header;
- uint8_t atype;
- uint8_t reserved1;
- uint16_t reserved2;
- uint32_t aid;
-} QEMU_PACKED PciCfgSccb;
-
typedef struct S390MsixInfo {
bool available;
uint8_t table_bar;
@@ -319,8 +311,8 @@ typedef struct S390pciState {
} S390pciState;
S390pciState *s390_get_phb(void);
-int chsc_sei_nt2_get_event(void *res);
-int chsc_sei_nt2_have_event(void);
+int pci_chsc_sei_nt2_get_event(void *res);
+int pci_chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(SCCB *sccb);
void s390_pci_sclp_deconfigure(SCCB *sccb);
void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index b7beb8c36a..eba9ffb5f2 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -440,8 +440,8 @@ static int trap_msix(S390PCIBusDevice *pbdev, uint64_t offset, uint8_t pcias)
{
if (pbdev->msix.available && pbdev->msix.table_bar == pcias &&
offset >= pbdev->msix.table_offset &&
- offset <= pbdev->msix.table_offset +
- (pbdev->msix.entries - 1) * PCI_MSIX_ENTRY_SIZE) {
+ offset < (pbdev->msix.table_offset +
+ pbdev->msix.entries * PCI_MSIX_ENTRY_SIZE)) {
return 1;
} else {
return 0;
diff --git a/hw/s390x/s390-pci-stub.c b/hw/s390x/s390-pci-stub.c
new file mode 100644
index 0000000000..7a642d376c
--- /dev/null
+++ b/hw/s390x/s390-pci-stub.c
@@ -0,0 +1,76 @@
+/* stubs for non-pci builds */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "s390-pci-inst.h"
+#include "s390-pci-bus.h"
+
+/* target/s390x/ioinst.c */
+int pci_chsc_sei_nt2_get_event(void *res)
+{
+ return 1;
+}
+
+int pci_chsc_sei_nt2_have_event(void)
+{
+ return 0;
+}
+
+/* hw/s390x/sclp.c */
+void s390_pci_sclp_configure(SCCB *sccb)
+{
+ sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
+}
+
+void s390_pci_sclp_deconfigure(SCCB *sccb)
+{
+ sccb->h.response_code = cpu_to_be16(SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED);
+}
+
+/* target/s390x/kvm.c */
+int clp_service_call(S390CPU *cpu, uint8_t r2)
+{
+ return -1;
+}
+
+int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
+{
+ return -1;
+}
+
+int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
+{
+ return -1;
+}
+
+int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
+{
+ return -1;
+}
+
+int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
+{
+ return -1;
+}
+
+int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr,
+ uint8_t ar)
+{
+ return -1;
+}
+
+int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar)
+{
+ return -1;
+}
+
+S390pciState *s390_get_phb(void)
+{
+ return NULL;
+}
+
+S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx)
+{
+ return NULL;
+}
diff --git a/hw/s390x/s390-skeys-kvm.c b/hw/s390x/s390-skeys-kvm.c
index 131da56bbe..dc54ed8b11 100644
--- a/hw/s390x/s390-skeys-kvm.c
+++ b/hw/s390x/s390-skeys-kvm.c
@@ -54,10 +54,14 @@ static int kvm_s390_skeys_set(S390SKeysState *ss, uint64_t start_gfn,
static void kvm_s390_skeys_class_init(ObjectClass *oc, void *data)
{
S390SKeysClass *skeyclass = S390_SKEYS_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
skeyclass->skeys_enabled = kvm_s390_skeys_enabled;
skeyclass->get_skeys = kvm_s390_skeys_get;
skeyclass->set_skeys = kvm_s390_skeys_set;
+
+ /* Reason: Internal device (only one skeys device for the whole memory) */
+ dc->user_creatable = false;
}
static const TypeInfo kvm_s390_skeys_info = {
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index c0de3b0c35..53ad5d38d4 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -229,10 +229,14 @@ static int qemu_s390_skeys_get(S390SKeysState *ss, uint64_t start_gfn,
static void qemu_s390_skeys_class_init(ObjectClass *oc, void *data)
{
S390SKeysClass *skeyclass = S390_SKEYS_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
skeyclass->skeys_enabled = qemu_s390_skeys_enabled;
skeyclass->get_skeys = qemu_s390_skeys_get;
skeyclass->set_skeys = qemu_s390_skeys_set;
+
+ /* Reason: Internal device (only one skeys device for the whole memory) */
+ dc->user_creatable = false;
}
static const TypeInfo qemu_s390_skeys_info = {
diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c
index ff3f89fd2d..41770a7dec 100644
--- a/hw/s390x/s390-stattrib-kvm.c
+++ b/hw/s390x/s390-stattrib-kvm.c
@@ -17,6 +17,7 @@
#include "sysemu/kvm.h"
#include "exec/ram_addr.h"
#include "cpu.h"
+#include "kvm_s390x.h"
Object *kvm_s390_stattrib_create(void)
{
@@ -163,6 +164,7 @@ static int kvm_s390_stattrib_get_active(S390StAttribState *sa)
static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
{
S390StAttribClass *sac = S390_STATTRIB_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
sac->get_stattr = kvm_s390_stattrib_get_stattr;
sac->peek_stattr = kvm_s390_stattrib_peek_stattr;
@@ -171,6 +173,9 @@ static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount;
sac->synchronize = kvm_s390_stattrib_synchronize;
sac->get_active = kvm_s390_stattrib_get_active;
+
+ /* Reason: Can only be instantiated one time (internally) */
+ dc->user_creatable = false;
}
static const TypeInfo kvm_s390_stattrib_info = {
diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index d14923f099..2902f54f11 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -11,12 +11,12 @@
#include "qemu/osdep.h"
#include "hw/boards.h"
+#include "cpu.h"
#include "qmp-commands.h"
#include "migration/qemu-file.h"
#include "migration/register.h"
#include "hw/s390x/storage-attributes.h"
#include "qemu/error-report.h"
-#include "sysemu/kvm.h"
#include "exec/ram_addr.h"
#include "qapi/error.h"
@@ -306,6 +306,7 @@ static int qemu_s390_get_active(S390StAttribState *sa)
static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data)
{
S390StAttribClass *sa_cl = S390_STATTRIB_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
sa_cl->synchronize = qemu_s390_synchronize_stub;
sa_cl->get_stattr = qemu_s390_get_stattr_stub;
@@ -314,6 +315,9 @@ static void qemu_s390_stattrib_class_init(ObjectClass *oc, void *data)
sa_cl->set_migrationmode = qemu_s390_set_migrationmode_stub;
sa_cl->get_dirtycount = qemu_s390_get_dirtycount_stub;
sa_cl->get_active = qemu_s390_get_active;
+
+ /* Reason: Can only be instantiated one time (internally) */
+ dc->user_creatable = false;
}
static const TypeInfo qemu_s390_stattrib_info = {
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 1c7af39ce6..dd504dd5ae 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -118,12 +118,11 @@ static void ccw_init(MachineState *machine)
{
int ret;
VirtualCssBus *css_bus;
- DeviceState *dev;
s390_sclp_init();
s390_memory_init(machine->ram_size);
- /* init CPUs */
+ /* init CPUs (incl. CPU model) early so s390_has_feature() works */
s390_init_cpus(machine);
s390_flic_init();
@@ -134,17 +133,18 @@ static void ccw_init(MachineState *machine)
machine->initrd_filename, "s390-ccw.img",
"s390-netboot.img", true);
- dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
- object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
- OBJECT(dev), NULL);
- qdev_init_nofail(dev);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ DeviceState *dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE);
+ object_property_add_child(qdev_get_machine(),
+ TYPE_S390_PCI_HOST_BRIDGE,
+ OBJECT(dev), NULL);
+ qdev_init_nofail(dev);
+ }
/* register hypercalls */
virtio_ccw_register_hcalls();
- if (kvm_enabled()) {
- kvm_s390_enable_css_support(s390_cpu_addr2state(0));
- }
+ s390_enable_css_support(s390_cpu_addr2state(0));
/*
* Non mcss-e enabled guests only see the devices from the default
* css, which is determined by the value of the squash_mcss property.
@@ -161,7 +161,7 @@ static void ccw_init(MachineState *machine)
s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw");
/* Register savevm handler for guest TOD clock */
- register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, kvm_state);
+ register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, NULL);
}
static void s390_cpu_plug(HotplugHandler *hotplug_dev,
@@ -276,9 +276,6 @@ static S390CcwMachineClass *get_machine_class(void)
bool ri_allowed(void)
{
- if (!kvm_enabled()) {
- return false;
- }
/* for "none" machine this results in true */
return get_machine_class()->ri_allowed;
}
@@ -291,18 +288,8 @@ bool cpu_model_allowed(void)
bool gs_allowed(void)
{
- if (kvm_enabled()) {
- MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
- if (object_class_dynamic_cast(OBJECT_CLASS(mc),
- TYPE_S390_CCW_MACHINE)) {
- S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
-
- return s390mc->gs_allowed;
- }
- /* Make sure the "none" machine can have gs */
- return true;
- }
- return false;
+ /* for "none" machine this results in true */
+ return get_machine_class()->gs_allowed;
}
static char *machine_get_loadparm(Object *obj, Error **errp)
@@ -432,6 +419,9 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
+#define CCW_COMPAT_2_10 \
+ HW_COMPAT_2_10
+
#define CCW_COMPAT_2_9 \
HW_COMPAT_2_9 \
{\
@@ -506,8 +496,18 @@ bool css_migration_enabled(void)
.value = "0",\
},
+static void ccw_machine_2_11_instance_options(MachineState *machine)
+{
+}
+
+static void ccw_machine_2_11_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(2_11, "2.11", true);
+
static void ccw_machine_2_10_instance_options(MachineState *machine)
{
+ ccw_machine_2_11_instance_options(machine);
if (css_migration_enabled()) {
css_register_vmstate();
}
@@ -515,8 +515,10 @@ static void ccw_machine_2_10_instance_options(MachineState *machine)
static void ccw_machine_2_10_class_options(MachineClass *mc)
{
+ ccw_machine_2_11_class_options(mc);
+ SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_10);
}
-DEFINE_CCW_MACHINE(2_10, "2.10", true);
+DEFINE_CCW_MACHINE(2_10, "2.10", false);
static void ccw_machine_2_9_instance_options(MachineState *machine)
{
diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c
index afa4148e6b..da3f49e80e 100644
--- a/hw/s390x/s390-virtio.c
+++ b/hw/s390x/s390-virtio.c
@@ -33,7 +33,6 @@
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/virtio/virtio.h"
-#include "sysemu/kvm.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
@@ -93,11 +92,7 @@ void s390_init_cpus(MachineState *machine)
gchar *name;
if (machine->cpu_model == NULL) {
- if (kvm_enabled()) {
- machine->cpu_model = "host";
- } else {
- machine->cpu_model = "qemu";
- }
+ machine->cpu_model = s390_default_cpu_model_name();
}
cpu_states = g_new0(S390CPU *, max_cpus);
diff --git a/hw/s390x/s390-virtio.h b/hw/s390x/s390-virtio.h
index f2377a3e0e..ca97fd6814 100644
--- a/hw/s390x/s390-virtio.h
+++ b/hw/s390x/s390-virtio.h
@@ -30,4 +30,6 @@ void s390_create_virtio_net(BusState *bus, const char *name);
void s390_nmi(NMIState *n, int cpu_index, Error **errp);
void s390_machine_reset(void);
void s390_memory_init(ram_addr_t mem_size);
+void gtod_save(QEMUFile *f, void *opaque);
+int gtod_load(QEMUFile *f, void *opaque, int version_id);
#endif
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 9253dbbc64..fd097262c7 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -15,7 +15,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
-#include "sysemu/kvm.h"
#include "exec/memory.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
@@ -57,7 +56,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
CPUState *cpu;
int cpu_count = 0;
int rnsize, rnmax;
- int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
+ int slots = MIN(machine->ram_slots, s390_get_memslot_count());
IplParameterBlock *ipib = s390_ipl_get_iplb();
CPU_FOREACH(cpu) {
@@ -80,7 +79,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
prepare_cpu_entries(sclp, read_info->entries, cpu_count);
read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
- SCLP_HAS_PCI_RECONFIG);
+ SCLP_HAS_IOA_RECONFIG);
/* Memory Hotplug is only supported for the ccw machine type */
if (mhd) {
@@ -354,6 +353,35 @@ static void sclp_read_cpu_info(SCLPDevice *sclp, SCCB *sccb)
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}
+static void sclp_configure_io_adapter(SCLPDevice *sclp, SCCB *sccb,
+ bool configure)
+{
+ int rc;
+
+ if (be16_to_cpu(sccb->h.length) < 16) {
+ rc = SCLP_RC_INSUFFICIENT_SCCB_LENGTH;
+ goto out_err;
+ }
+
+ switch (((IoaCfgSccb *)sccb)->atype) {
+ case SCLP_RECONFIG_PCI_ATYPE:
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ if (configure) {
+ s390_pci_sclp_configure(sccb);
+ } else {
+ s390_pci_sclp_deconfigure(sccb);
+ }
+ return;
+ }
+ /* fallthrough */
+ default:
+ rc = SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED;
+ }
+
+ out_err:
+ sccb->h.response_code = cpu_to_be16(rc);
+}
+
static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
{
SCLPDeviceClass *sclp_c = SCLP_GET_CLASS(sclp);
@@ -384,11 +412,11 @@ static void sclp_execute(SCLPDevice *sclp, SCCB *sccb, uint32_t code)
case SCLP_UNASSIGN_STORAGE:
sclp_c->unassign_storage(sclp, sccb);
break;
- case SCLP_CMDW_CONFIGURE_PCI:
- s390_pci_sclp_configure(sccb);
+ case SCLP_CMDW_CONFIGURE_IOA:
+ sclp_configure_io_adapter(sclp, sccb, true);
break;
- case SCLP_CMDW_DECONFIGURE_PCI:
- s390_pci_sclp_deconfigure(sccb);
+ case SCLP_CMDW_DECONFIGURE_IOA:
+ sclp_configure_io_adapter(sclp, sccb, false);
break;
default:
efc->command_handler(ef, sccb, code);
diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c
index b1f3ef8c7d..023d059a46 100644
--- a/hw/s390x/sclpcpu.c
+++ b/hw/s390x/sclpcpu.c
@@ -18,7 +18,6 @@
#include "hw/s390x/event-facility.h"
#include "cpu.h"
#include "sysemu/cpus.h"
-#include "sysemu/kvm.h"
typedef struct ConfigMgtData {
EventBufferHeader ebh;
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index a7b64e2c40..47f289216a 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -121,6 +121,7 @@ static void wdt_diag288_class_init(ObjectClass *klass, void *data)
dc->realize = wdt_diag288_realize;
dc->unrealize = wdt_diag288_unrealize;
dc->reset = wdt_diag288_reset;
+ dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->vmsd = &vmstate_diag288;
diag288->handle_timer = wdt_diag288_handle_timer;
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 9c3d0a5868..040cdd2e60 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -163,8 +163,8 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
Error **errp);
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
-ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request);
-ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
+int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
+int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);
int nbd_client(int fd);
int nbd_disconnect(int fd);
diff --git a/include/hw/compat.h b/include/hw/compat.h
index 08f36004da..3e101f8f67 100644
--- a/include/hw/compat.h
+++ b/include/hw/compat.h
@@ -1,6 +1,9 @@
#ifndef HW_COMPAT_H
#define HW_COMPAT_H
+#define HW_COMPAT_2_10 \
+ /* empty */
+
#define HW_COMPAT_2_9 \
{\
.driver = "pci-bridge",\
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index e598b095eb..8bb6449dd7 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -10,6 +10,8 @@
#include "hw/pci/pcie.h"
+extern bool pci_available;
+
/* PCI bus */
#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 5c5fe6b202..0653d3c9be 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -16,6 +16,7 @@
#include "hw/s390x/adapter.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/ioinst.h"
+#include "sysemu/kvm.h"
/* Channel subsystem constants. */
#define MAX_DEVNO 65535
@@ -150,7 +151,8 @@ void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
void css_inject_io_interrupt(SubchDev *sch);
void css_reset(void);
void css_reset_sch(SubchDev *sch);
-void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
+void css_queue_crw(uint8_t rsc, uint8_t erc, int solicited,
+ int chain, uint16_t rsid);
void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
int hotplugged, int add);
void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h
index 92d15655e4..5f2db6949d 100644
--- a/include/hw/s390x/ioinst.h
+++ b/include/hw/s390x/ioinst.h
@@ -201,8 +201,16 @@ typedef struct CRW {
#define CRW_FLAGS_MASK_A 0x0080
#define CRW_FLAGS_MASK_ERC 0x003f
-#define CRW_ERC_INIT 0x02
-#define CRW_ERC_IPI 0x04
+#define CRW_ERC_EVENT 0x00 /* event information pending */
+#define CRW_ERC_AVAIL 0x01 /* available */
+#define CRW_ERC_INIT 0x02 /* initialized */
+#define CRW_ERC_TERROR 0x03 /* temporary error */
+#define CRW_ERC_IPI 0x04 /* installed parm initialized */
+#define CRW_ERC_TERM 0x05 /* terminal */
+#define CRW_ERC_PERRN 0x06 /* perm. error, facility not init */
+#define CRW_ERC_PERRI 0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD 0x08 /* installed parameters modified */
+#define CRW_ERC_IPR 0x0A /* installed parameters restored */
#define CRW_RSC_SUBCH 0x3
#define CRW_RSC_CHP 0x4
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
index e71d526605..a72d096081 100644
--- a/include/hw/s390x/sclp.h
+++ b/include/hw/s390x/sclp.h
@@ -44,10 +44,10 @@
#define SCLP_CMDW_DECONFIGURE_CPU 0x00100001
/* SCLP PCI codes */
-#define SCLP_HAS_PCI_RECONFIG 0x0000000040000000ULL
-#define SCLP_CMDW_CONFIGURE_PCI 0x001a0001
-#define SCLP_CMDW_DECONFIGURE_PCI 0x001b0001
-#define SCLP_RECONFIG_PCI_ATPYE 2
+#define SCLP_HAS_IOA_RECONFIG 0x0000000040000000ULL
+#define SCLP_CMDW_CONFIGURE_IOA 0x001a0001
+#define SCLP_CMDW_DECONFIGURE_IOA 0x001b0001
+#define SCLP_RECONFIG_PCI_ATYPE 2
/* SCLP response codes */
#define SCLP_RC_NORMAL_READ_COMPLETION 0x0010
@@ -59,6 +59,7 @@
#define SCLP_RC_INSUFFICIENT_SCCB_LENGTH 0x0300
#define SCLP_RC_STANDBY_READ_COMPLETION 0x0410
#define SCLP_RC_ADAPTER_IN_RESERVED_STATE 0x05f0
+#define SCLP_RC_ADAPTER_TYPE_NOT_RECOGNIZED 0x06f0
#define SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED 0x09f0
#define SCLP_RC_INVALID_FUNCTION 0x40f0
#define SCLP_RC_NO_EVENT_BUFFERS_STORED 0x60f0
@@ -167,6 +168,14 @@ typedef struct AssignStorage {
uint16_t rn;
} QEMU_PACKED AssignStorage;
+typedef struct IoaCfgSccb {
+ SCCBHeader header;
+ uint8_t atype;
+ uint8_t reserved1;
+ uint16_t reserved2;
+ uint32_t aid;
+} QEMU_PACKED IoaCfgSccb;
+
typedef struct SCCB {
SCCBHeader h;
char data[SCCB_DATA_LEN];
diff --git a/nbd/client.c b/nbd/client.c
index 0a17de80b5..68a0bc1ffc 100644
--- a/nbd/client.c
+++ b/nbd/client.c
@@ -399,12 +399,10 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
phase, but make sure it sent flags */
if (len) {
error_setg(errp, "server sent invalid NBD_REP_ACK");
- nbd_send_opt_abort(ioc);
return -1;
}
if (!info->flags) {
error_setg(errp, "broken server omitted NBD_INFO_EXPORT");
- nbd_send_opt_abort(ioc);
return -1;
}
trace_nbd_opt_go_success();
@@ -898,7 +896,7 @@ int nbd_disconnect(int fd)
}
#endif
-ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
+int nbd_send_request(QIOChannel *ioc, NBDRequest *request)
{
uint8_t buf[NBD_REQUEST_SIZE];
@@ -916,22 +914,22 @@ ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request)
return nbd_write(ioc, buf, sizeof(buf), NULL);
}
-ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
+/* nbd_receive_reply
+ * Returns 1 on success
+ * 0 on eof, when no data was read (errp is not set)
+ * negative errno on failure (errp is set)
+ */
+int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
{
uint8_t buf[NBD_REPLY_SIZE];
uint32_t magic;
- ssize_t ret;
+ int ret;
ret = nbd_read_eof(ioc, buf, sizeof(buf), errp);
if (ret <= 0) {
return ret;
}
- if (ret != sizeof(buf)) {
- error_setg(errp, "read failed");
- return -EINVAL;
- }
-
/* Reply
[ 0 .. 3] magic (NBD_REPLY_MAGIC)
[ 4 .. 7] error (0 == no error)
@@ -955,6 +953,7 @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
return -EINVAL;
}
- return sizeof(buf);
+
+ return 1;
}
diff --git a/nbd/nbd-internal.h b/nbd/nbd-internal.h
index 396ddb4d3e..03549e3f39 100644
--- a/nbd/nbd-internal.h
+++ b/nbd/nbd-internal.h
@@ -77,21 +77,36 @@
#define NBD_ESHUTDOWN 108
/* nbd_read_eof
- * Tries to read @size bytes from @ioc. Returns number of bytes actually read.
- * May return a value >= 0 and < size only on EOF, i.e. when iteratively called
- * qio_channel_readv() returns 0. So, there is no need to call nbd_read_eof
- * iteratively.
+ * Tries to read @size bytes from @ioc.
+ * Returns 1 on success
+ * 0 on eof, when no data was read (errp is not set)
+ * negative errno on failure (errp is set)
*/
-static inline ssize_t nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
- Error **errp)
+static inline int nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
+ Error **errp)
{
struct iovec iov = { .iov_base = buffer, .iov_len = size };
+ ssize_t ret;
+
/* Sockets are kept in blocking mode in the negotiation phase. After
* that, a non-readable socket simply means that another thread stole
* our request/reply. Synchronization is done with recv_coroutine, so
* that this is coroutine-safe.
*/
- return nbd_rwv(ioc, &iov, 1, size, true, errp);
+
+ assert(size);
+
+ ret = nbd_rwv(ioc, &iov, 1, size, true, errp);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ if (ret != size) {
+ error_setg(errp, "End of file");
+ return -EINVAL;
+ }
+
+ return 1;
}
/* nbd_read
@@ -100,9 +115,9 @@ static inline ssize_t nbd_read_eof(QIOChannel *ioc, void *buffer, size_t size,
static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
Error **errp)
{
- ssize_t ret = nbd_read_eof(ioc, buffer, size, errp);
+ int ret = nbd_read_eof(ioc, buffer, size, errp);
- if (ret >= 0 && ret != size) {
+ if (ret == 0) {
ret = -EINVAL;
error_setg(errp, "End of file");
}
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 0a08c3936a..0b039291a5 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index f5b4549ea3..55eaeee4b6 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -133,7 +133,7 @@ struct ccw1 {
__u8 flags;
__u16 count;
__u32 cda;
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(8)));
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
diff --git a/slirp/socket.c b/slirp/socket.c
index ecec0295a9..cb7b5b608d 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -60,29 +60,36 @@ socreate(Slirp *slirp)
}
/*
+ * Remove references to so from the given message queue.
+ */
+static void
+soqfree(struct socket *so, struct quehead *qh)
+{
+ struct mbuf *ifq;
+
+ for (ifq = (struct mbuf *) qh->qh_link;
+ (struct quehead *) ifq != qh;
+ ifq = ifq->ifq_next) {
+ if (ifq->ifq_so == so) {
+ struct mbuf *ifm;
+ ifq->ifq_so = NULL;
+ for (ifm = ifq->ifs_next; ifm != ifq; ifm = ifm->ifs_next) {
+ ifm->ifq_so = NULL;
+ }
+ }
+ }
+}
+
+/*
* remque and free a socket, clobber cache
*/
void
sofree(struct socket *so)
{
Slirp *slirp = so->slirp;
- struct mbuf *ifm;
- for (ifm = (struct mbuf *) slirp->if_fastq.qh_link;
- (struct quehead *) ifm != &slirp->if_fastq;
- ifm = ifm->ifq_next) {
- if (ifm->ifq_so == so) {
- ifm->ifq_so = NULL;
- }
- }
-
- for (ifm = (struct mbuf *) slirp->if_batchq.qh_link;
- (struct quehead *) ifm != &slirp->if_batchq;
- ifm = ifm->ifq_next) {
- if (ifm->ifq_so == so) {
- ifm->ifq_so = NULL;
- }
- }
+ soqfree(so, &slirp->if_fastq);
+ soqfree(so, &slirp->if_batchq);
if (so->so_emu==EMU_RSH && so->extra) {
sofree(so->extra);
diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs
index f42cd1f9cc..9615256d81 100644
--- a/target/s390x/Makefile.objs
+++ b/target/s390x/Makefile.objs
@@ -3,6 +3,7 @@ obj-$(CONFIG_TCG) += translate.o cc_helper.o excp_helper.o fpu_helper.o
obj-$(CONFIG_TCG) += int_helper.o mem_helper.o misc_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o diag.o
obj-$(CONFIG_KVM) += kvm.o
+obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
# build and run feature list generator
feat-src = $(SRC_PATH)/target/$(TARGET_BASE_ARCH)/
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index 96c9fb97cb..9b0bf92698 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -13,10 +13,10 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "elf.h"
#include "exec/cpu-all.h"
#include "sysemu/dump.h"
-#include "sysemu/kvm.h"
struct S390xUserRegsStruct {
diff --git a/target/s390x/cc_helper.c b/target/s390x/cc_helper.c
index 1cf855133e..f008897e84 100644
--- a/target/s390x/cc_helper.c
+++ b/target/s390x/cc_helper.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "qemu/host-utils.h"
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 489bc25334..7267b60d41 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -26,6 +26,9 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
+#include "sysemu/kvm.h"
#include "qemu-common.h"
#include "qemu/cutils.h"
#include "qemu/timer.h"
@@ -391,6 +394,92 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
return s390_count_running_cpus();
}
+
+int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_get_clock(tod_high, tod_low);
+ }
+ /* Fixme TCG */
+ *tod_high = 0;
+ *tod_low = 0;
+ return 0;
+}
+
+int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_set_clock(tod_high, tod_low);
+ }
+ /* Fixme TCG */
+ return 0;
+}
+
+int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_set_mem_limit(new_limit, hw_limit);
+ }
+ return 0;
+}
+
+void s390_cmma_reset(void)
+{
+ if (kvm_enabled()) {
+ kvm_s390_cmma_reset();
+ }
+}
+
+int s390_cpu_restart(S390CPU *cpu)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_cpu_restart(cpu);
+ }
+ return -ENOSYS;
+}
+
+int s390_get_memslot_count(void)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_get_memslot_count();
+ } else {
+ return MAX_AVAIL_SLOTS;
+ }
+}
+
+int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
+ int vq, bool assign)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
+ } else {
+ return 0;
+ }
+}
+
+void s390_crypto_reset(void)
+{
+ if (kvm_enabled()) {
+ kvm_s390_crypto_reset();
+ }
+}
+
+bool s390_get_squash_mcss(void)
+{
+ if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
+ NULL)) {
+ return true;
+ }
+
+ return false;
+}
+
+void s390_enable_css_support(S390CPU *cpu)
+{
+ if (kvm_enabled()) {
+ kvm_s390_enable_css_support(cpu);
+ }
+}
#endif
static gchar *s390_gdb_arch_name(CPUState *cs)
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 29fdd5d49a..4ec338077e 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -213,22 +213,6 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
extern const struct VMStateDescription vmstate_s390_cpu;
#endif
-void s390_cpu_do_interrupt(CPUState *cpu);
-bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
-void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
- int flags);
-int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
- int cpuid, void *opaque);
-
-hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
-hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
-int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
-int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
-void s390_cpu_gdb_init(CPUState *cs);
-void s390x_cpu_debug_excp_handler(CPUState *cs);
-
-#include "sysemu/kvm.h"
-
/* distinguish between 24 bit and 31 bit addressing */
#define HIGH_ORDER_BIT 0x80000000
@@ -366,17 +350,6 @@ void s390x_cpu_debug_excp_handler(CPUState *cs);
#define MMU_SECONDARY_IDX 1
#define MMU_HOME_IDX 2
-static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
-{
- uint16_t pkm = env->cregs[3] >> 16;
-
- if (env->psw.mask & PSW_MASK_PSTATE) {
- /* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
- return pkm & (0x80 >> psw_key);
- }
- return true;
-}
-
static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
{
switch (env->psw.mask & PSW_MASK_ASC) {
@@ -393,20 +366,6 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
}
}
-static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
-{
- switch (mmu_idx) {
- case MMU_PRIMARY_IDX:
- return PSW_ASC_PRIMARY;
- case MMU_SECONDARY_IDX:
- return PSW_ASC_SECONDARY;
- case MMU_HOME_IDX:
- return PSW_ASC_HOME;
- default:
- abort();
- }
-}
-
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
{
@@ -415,26 +374,6 @@ static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
*flags = (env->psw.mask >> FLAG_MASK_PSW_SHIFT) & FLAG_MASK_PSW;
}
-#define MAX_ILEN 6
-
-/* While the PoO talks about ILC (a number between 1-3) what is actually
- stored in LowCore is shifted left one bit (an even between 2-6). As
- this is the actual length of the insn and therefore more useful, that
- is what we want to pass around and manipulate. To make sure that we
- have applied this distinction universally, rename the "ILC" to "ILEN". */
-static inline int get_ilen(uint8_t opc)
-{
- switch (opc >> 6) {
- case 0:
- return 2;
- case 1:
- case 2:
- return 4;
- default:
- return 6;
- }
-}
-
/* PER bits from control register 9 */
#define PER_CR9_EVENT_BRANCH 0x80000000
#define PER_CR9_EVENT_IFETCH 0x40000000
@@ -451,203 +390,6 @@ static inline int get_ilen(uint8_t opc)
#define PER_CODE_EVENT_STORE_REAL 0x0800
#define PER_CODE_EVENT_NULLIFICATION 0x0100
-/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
- entry when a PER exception is triggered. */
-static inline uint8_t get_per_atmid(CPUS390XState *env)
-{
- return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
- ( (1 << 6) ) |
- ((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
- ((env->psw.mask & PSW_MASK_DAT)? (1 << 4) : 0) |
- ((env->psw.mask & PSW_ASC_SECONDARY)? (1 << 3) : 0) |
- ((env->psw.mask & PSW_ASC_ACCREG)? (1 << 2) : 0);
-}
-
-/* Check if an address is within the PER starting address and the PER
- ending address. The address range might loop. */
-static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
-{
- if (env->cregs[10] <= env->cregs[11]) {
- return env->cregs[10] <= addr && addr <= env->cregs[11];
- } else {
- return env->cregs[10] <= addr || addr <= env->cregs[11];
- }
-}
-
-S390CPU *cpu_s390x_init(const char *cpu_model);
-S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp);
-S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp);
-void s390x_translate_init(void);
-
-/* you can call this signal handler from your SIGBUS and SIGSEGV
- signal handlers to inform the virtual CPU of exceptions. non zero
- is returned if the signal was handled by the virtual CPU. */
-int cpu_s390x_signal_handler(int host_signum, void *pinfo,
- void *puc);
-int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
- int mmu_idx);
-
-
-#ifndef CONFIG_USER_ONLY
-void do_restart_interrupt(CPUS390XState *env);
-void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
- MMUAccessType access_type,
- int mmu_idx, uintptr_t retaddr);
-
-static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
- uint8_t *ar)
-{
- hwaddr addr = 0;
- uint8_t reg;
-
- reg = ipb >> 28;
- if (reg > 0) {
- addr = env->regs[reg];
- }
- addr += (ipb >> 16) & 0xfff;
- if (ar) {
- *ar = reg;
- }
-
- return addr;
-}
-
-/* Base/displacement are at the same locations. */
-#define decode_basedisp_rs decode_basedisp_s
-
-/* helper functions for run_on_cpu() */
-static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
-{
- S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
-
- scc->cpu_reset(cs);
-}
-static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
-{
- cpu_reset(cs);
-}
-
-void s390x_tod_timer(void *opaque);
-void s390x_cpu_timer(void *opaque);
-
-int s390_virtio_hypercall(CPUS390XState *env);
-
-#ifdef CONFIG_KVM
-void kvm_s390_service_interrupt(uint32_t parm);
-void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
-void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
-int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
-void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
-int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
- int len, bool is_write);
-int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
-int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
-#else
-static inline void kvm_s390_service_interrupt(uint32_t parm)
-{
-}
-static inline int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar,
- void *hostbuf, int len, bool is_write)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
- uint64_t te_code)
-{
-}
-#endif
-
-static inline int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- if (kvm_enabled()) {
- return kvm_s390_get_clock(tod_high, tod_low);
- }
- /* Fixme TCG */
- *tod_high = 0;
- *tod_low = 0;
- return 0;
-}
-
-static inline int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
-{
- if (kvm_enabled()) {
- return kvm_s390_set_clock(tod_high, tod_low);
- }
- /* Fixme TCG */
- return 0;
-}
-
-S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
-unsigned int s390_cpu_halt(S390CPU *cpu);
-void s390_cpu_unhalt(S390CPU *cpu);
-unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
-static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
-{
- return cpu->env.cpu_state;
-}
-
-void gtod_save(QEMUFile *f, void *opaque);
-int gtod_load(QEMUFile *f, void *opaque, int version_id);
-
-void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
- uint64_t param64);
-
-/* ioinst.c */
-void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
-void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
-void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
-int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
-void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
- uint32_t ipb);
-void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
-void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
-
-/* service interrupts are floating therefore we must not pass an cpustate */
-void s390_sclp_extint(uint32_t parm);
-
-#else
-static inline unsigned int s390_cpu_halt(S390CPU *cpu)
-{
- return 0;
-}
-
-static inline void s390_cpu_unhalt(S390CPU *cpu)
-{
-}
-
-static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
-{
- return 0;
-}
-#endif
-
-extern void subsystem_reset(void);
-
-#define cpu_init(model) CPU(cpu_s390x_init(model))
-#define cpu_signal_handler cpu_s390x_signal_handler
-
-void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
-#define cpu_list s390_cpu_list
-void s390_cpu_model_register_props(Object *obj);
-void s390_cpu_model_class_register_props(ObjectClass *oc);
-void s390_realize_cpu_model(CPUState *cs, Error **errp);
-ObjectClass *s390_cpu_class_by_name(const char *name);
-
#define EXCP_EXT 1 /* external interrupt */
#define EXCP_SVC 2 /* supervisor call (syscall) */
#define EXCP_PGM 3 /* program interruption */
@@ -683,115 +425,6 @@ ObjectClass *s390_cpu_class_by_name(const char *name);
/* Total Core Registers. */
#define S390_NUM_CORE_REGS 18
-/* CC optimization */
-
-/* Instead of computing the condition codes after each x86 instruction,
- * QEMU just stores the result (called CC_DST), the type of operation
- * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
- * CC_VR). When the condition codes are needed, the condition codes can
- * be calculated using this information. Condition codes are not generated
- * if they are only needed for conditional branches.
- */
-enum cc_op {
- CC_OP_CONST0 = 0, /* CC is 0 */
- CC_OP_CONST1, /* CC is 1 */
- CC_OP_CONST2, /* CC is 2 */
- CC_OP_CONST3, /* CC is 3 */
-
- CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
- CC_OP_STATIC, /* CC value is env->cc_op */
-
- CC_OP_NZ, /* env->cc_dst != 0 */
- CC_OP_LTGT_32, /* signed less/greater than (32bit) */
- CC_OP_LTGT_64, /* signed less/greater than (64bit) */
- CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
- CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
- CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
- CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
-
- CC_OP_ADD_64, /* overflow on add (64bit) */
- CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
- CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
- CC_OP_SUB_64, /* overflow on subtraction (64bit) */
- CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
- CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
- CC_OP_ABS_64, /* sign eval on abs (64bit) */
- CC_OP_NABS_64, /* sign eval on nabs (64bit) */
-
- CC_OP_ADD_32, /* overflow on add (32bit) */
- CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
- CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
- CC_OP_SUB_32, /* overflow on subtraction (32bit) */
- CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
- CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
- CC_OP_ABS_32, /* sign eval on abs (64bit) */
- CC_OP_NABS_32, /* sign eval on nabs (64bit) */
-
- CC_OP_COMP_32, /* complement */
- CC_OP_COMP_64, /* complement */
-
- CC_OP_TM_32, /* test under mask (32bit) */
- CC_OP_TM_64, /* test under mask (64bit) */
-
- CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
- CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
- CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
-
- CC_OP_ICM, /* insert characters under mask */
- CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
- CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
- CC_OP_FLOGR, /* find leftmost one */
- CC_OP_MAX
-};
-
-static const char *cc_names[] = {
- [CC_OP_CONST0] = "CC_OP_CONST0",
- [CC_OP_CONST1] = "CC_OP_CONST1",
- [CC_OP_CONST2] = "CC_OP_CONST2",
- [CC_OP_CONST3] = "CC_OP_CONST3",
- [CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
- [CC_OP_STATIC] = "CC_OP_STATIC",
- [CC_OP_NZ] = "CC_OP_NZ",
- [CC_OP_LTGT_32] = "CC_OP_LTGT_32",
- [CC_OP_LTGT_64] = "CC_OP_LTGT_64",
- [CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
- [CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
- [CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
- [CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
- [CC_OP_ADD_64] = "CC_OP_ADD_64",
- [CC_OP_ADDU_64] = "CC_OP_ADDU_64",
- [CC_OP_ADDC_64] = "CC_OP_ADDC_64",
- [CC_OP_SUB_64] = "CC_OP_SUB_64",
- [CC_OP_SUBU_64] = "CC_OP_SUBU_64",
- [CC_OP_SUBB_64] = "CC_OP_SUBB_64",
- [CC_OP_ABS_64] = "CC_OP_ABS_64",
- [CC_OP_NABS_64] = "CC_OP_NABS_64",
- [CC_OP_ADD_32] = "CC_OP_ADD_32",
- [CC_OP_ADDU_32] = "CC_OP_ADDU_32",
- [CC_OP_ADDC_32] = "CC_OP_ADDC_32",
- [CC_OP_SUB_32] = "CC_OP_SUB_32",
- [CC_OP_SUBU_32] = "CC_OP_SUBU_32",
- [CC_OP_SUBB_32] = "CC_OP_SUBB_32",
- [CC_OP_ABS_32] = "CC_OP_ABS_32",
- [CC_OP_NABS_32] = "CC_OP_NABS_32",
- [CC_OP_COMP_32] = "CC_OP_COMP_32",
- [CC_OP_COMP_64] = "CC_OP_COMP_64",
- [CC_OP_TM_32] = "CC_OP_TM_32",
- [CC_OP_TM_64] = "CC_OP_TM_64",
- [CC_OP_NZ_F32] = "CC_OP_NZ_F32",
- [CC_OP_NZ_F64] = "CC_OP_NZ_F64",
- [CC_OP_NZ_F128] = "CC_OP_NZ_F128",
- [CC_OP_ICM] = "CC_OP_ICM",
- [CC_OP_SLA_32] = "CC_OP_SLA_32",
- [CC_OP_SLA_64] = "CC_OP_SLA_64",
- [CC_OP_FLOGR] = "CC_OP_FLOGR",
-};
-
-static inline const char *cc_name(int cc_op)
-{
- return cc_names[cc_op];
-}
-
static inline void setcc(S390CPU *cpu, uint64_t cc)
{
CPUS390XState *env = &cpu->env;
@@ -801,130 +434,6 @@ static inline void setcc(S390CPU *cpu, uint64_t cc)
env->cc_op = cc;
}
-#ifndef CONFIG_USER_ONLY
-
-typedef struct LowCore
-{
- /* prefix area: defined by architecture */
- uint32_t ccw1[2]; /* 0x000 */
- uint32_t ccw2[4]; /* 0x008 */
- 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 */
- uint32_t mcck_interruption_code[2]; /* 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 */
- PSW return_psw; /* 0x200 */
- uint8_t irb[64]; /* 0x210 */
- uint64_t sync_enter_timer; /* 0x250 */
- uint64_t async_enter_timer; /* 0x258 */
- uint64_t exit_timer; /* 0x260 */
- uint64_t last_update_timer; /* 0x268 */
- uint64_t user_timer; /* 0x270 */
- uint64_t system_timer; /* 0x278 */
- uint64_t last_update_clock; /* 0x280 */
- uint64_t steal_clock; /* 0x288 */
- PSW return_mcck_psw; /* 0x290 */
- uint8_t pad9[0xc00-0x2a0]; /* 0x2a0 */
- /* System info area */
- uint64_t save_area[16]; /* 0xc00 */
- uint8_t pad10[0xd40-0xc80]; /* 0xc80 */
- uint64_t kernel_stack; /* 0xd40 */
- uint64_t thread_info; /* 0xd48 */
- uint64_t async_stack; /* 0xd50 */
- uint64_t kernel_asce; /* 0xd58 */
- uint64_t user_asce; /* 0xd60 */
- uint64_t panic_stack; /* 0xd68 */
- uint64_t user_exec_asce; /* 0xd70 */
- uint8_t pad11[0xdc0-0xd78]; /* 0xd78 */
-
- /* SMP info area: defined by DJB */
- uint64_t clock_comparator; /* 0xdc0 */
- uint64_t ext_call_fast; /* 0xdc8 */
- uint64_t percpu_offset; /* 0xdd0 */
- uint64_t current_task; /* 0xdd8 */
- uint32_t softirq_pending; /* 0xde0 */
- uint32_t pad_0x0de4; /* 0xde4 */
- uint64_t int_clock; /* 0xde8 */
- uint8_t pad12[0xe00-0xdf0]; /* 0xdf0 */
-
- /* 0xe00 is used as indicator for dump tools */
- /* whether the kernel died with panic() or not */
- uint32_t panic_magic; /* 0xe00 */
-
- uint8_t pad13[0x11b8-0xe04]; /* 0xe04 */
-
- /* 64 bit extparam used for pfault, diag 250 etc */
- uint64_t ext_params2; /* 0x11B8 */
-
- uint8_t pad14[0x1200-0x11C0]; /* 0x11C0 */
-
- /* System info area */
-
- uint64_t floating_pt_save_area[16]; /* 0x1200 */
- uint64_t gpregs_save_area[16]; /* 0x1280 */
- uint32_t st_status_fixed_logout[4]; /* 0x1300 */
- uint8_t pad15[0x1318-0x1310]; /* 0x1310 */
- uint32_t prefixreg_save_area; /* 0x1318 */
- uint32_t fpt_creg_save_area; /* 0x131c */
- uint8_t pad16[0x1324-0x1320]; /* 0x1320 */
- uint32_t tod_progreg_save_area; /* 0x1324 */
- uint32_t cpu_timer_save_area[2]; /* 0x1328 */
- uint32_t clock_comp_save_area[2]; /* 0x1330 */
- uint8_t pad17[0x1340-0x1338]; /* 0x1338 */
- uint32_t access_regs_save_area[16]; /* 0x1340 */
- uint64_t cregs_save_area[16]; /* 0x1380 */
-
- /* align to the top of the prefix area */
-
- uint8_t pad18[0x2000-0x1400]; /* 0x1400 */
-} QEMU_PACKED LowCore;
-
-LowCore *cpu_map_lowcore(CPUS390XState *env);
-void cpu_unmap_lowcore(LowCore *lowcore);
-
-#endif
-
/* STSI */
#define STSI_LEVEL_MASK 0x00000000f0000000ULL
#define STSI_LEVEL_CURRENT 0x0000000000000000ULL
@@ -1100,210 +609,10 @@ struct sysib_322 {
/* SIGP order code mask corresponding to bit positions 56-63 */
#define SIGP_ORDER_MASK 0x000000ff
-void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
-uint64_t get_psw_mask(CPUS390XState *env);
-target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
-int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
- target_ulong *raddr, int *flags, bool exc);
-int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
-uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
- uint64_t vr);
-void s390_cpu_recompute_watchpoints(CPUState *cs);
-
-int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
- int len, bool is_write);
-
-#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false)
-#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)
-#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \
- s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true)
-
-/* The value of the TOD clock for 1.1.1970. */
-#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
-
-/* Converts ns to s390's clock format */
-static inline uint64_t time2tod(uint64_t ns) {
- return (ns << 9) / 125;
-}
-
-/* Converts s390's clock format to ns */
-static inline uint64_t tod2time(uint64_t t) {
- return (t * 125) >> 9;
-}
-
/* from s390-virtio-ccw */
#define MEM_SECTION_SIZE 0x10000000UL
#define MAX_AVAIL_SLOTS 32
-/* fpu_helper.c */
-uint32_t set_cc_nz_f32(float32 v);
-uint32_t set_cc_nz_f64(float64 v);
-uint32_t set_cc_nz_f128(float128 v);
-
-/* misc_helper.c */
-#ifndef CONFIG_USER_ONLY
-int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
-void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
-#endif
-/* automatically detect the instruction length */
-#define ILEN_AUTO 0xff
-void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
-void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
-void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
- uintptr_t retaddr);
-
-#ifdef CONFIG_KVM
-void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code);
-void kvm_s390_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr, uint32_t io_int_parm,
- uint32_t io_int_word);
-void kvm_s390_crw_mchk(void);
-void kvm_s390_enable_css_support(S390CPU *cpu);
-int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
- int vq, bool assign);
-int kvm_s390_cpu_restart(S390CPU *cpu);
-int kvm_s390_get_memslot_count(KVMState *s);
-int kvm_s390_cmma_active(void);
-void kvm_s390_cmma_reset(void);
-int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
-void kvm_s390_reset_vcpu(S390CPU *cpu);
-int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit);
-void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
-int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
-int kvm_s390_get_ri(void);
-int kvm_s390_get_gs(void);
-void kvm_s390_crypto_reset(void);
-#else
-static inline void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code)
-{
-}
-static inline void kvm_s390_io_interrupt(uint16_t subchannel_id,
- uint16_t subchannel_nr,
- uint32_t io_int_parm,
- uint32_t io_int_word)
-{
-}
-static inline void kvm_s390_crw_mchk(void)
-{
-}
-static inline void kvm_s390_enable_css_support(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier,
- uint32_t sch, int vq,
- bool assign)
-{
- return -ENOSYS;
-}
-static inline int kvm_s390_cpu_restart(S390CPU *cpu)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_cmma_reset(void)
-{
-}
-static inline int kvm_s390_get_memslot_count(KVMState *s)
-{
- return MAX_AVAIL_SLOTS;
-}
-static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
-{
- return -ENOSYS;
-}
-static inline void kvm_s390_reset_vcpu(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit,
- uint64_t *hw_limit)
-{
- return 0;
-}
-static inline void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
-{
-}
-static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
-{
- return 0;
-}
-static inline int kvm_s390_get_ri(void)
-{
- return 0;
-}
-static inline int kvm_s390_get_gs(void)
-{
- return 0;
-}
-static inline void kvm_s390_crypto_reset(void)
-{
-}
-#endif
-
-static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
-{
- if (kvm_enabled()) {
- return kvm_s390_set_mem_limit(kvm_state, new_limit, hw_limit);
- }
- return 0;
-}
-
-static inline void s390_cmma_reset(void)
-{
- if (kvm_enabled()) {
- kvm_s390_cmma_reset();
- }
-}
-
-static inline int s390_cpu_restart(S390CPU *cpu)
-{
- if (kvm_enabled()) {
- return kvm_s390_cpu_restart(cpu);
- }
- return -ENOSYS;
-}
-
-static inline int s390_get_memslot_count(KVMState *s)
-{
- if (kvm_enabled()) {
- return kvm_s390_get_memslot_count(s);
- } else {
- return MAX_AVAIL_SLOTS;
- }
-}
-
-void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
- uint32_t io_int_parm, uint32_t io_int_word);
-void s390_crw_mchk(void);
-
-static inline int s390_assign_subch_ioeventfd(EventNotifier *notifier,
- uint32_t sch_id, int vq,
- bool assign)
-{
- if (kvm_enabled()) {
- return kvm_s390_assign_subch_ioeventfd(notifier, sch_id, vq, assign);
- } else {
- return 0;
- }
-}
-
-static inline void s390_crypto_reset(void)
-{
- if (kvm_enabled()) {
- kvm_s390_crypto_reset();
- }
-}
-
-static inline bool s390_get_squash_mcss(void)
-{
- if (object_property_get_bool(OBJECT(qdev_get_machine()), "s390-squash-mcss",
- NULL)) {
- return true;
- }
-
- return false;
-}
-
/* machine check interruption code */
/* subclasses */
@@ -1349,4 +658,72 @@ static inline bool s390_get_squash_mcss(void)
#define MCIC_VB_CT 0x0000000000020000ULL
#define MCIC_VB_CC 0x0000000000010000ULL
+
+/* cpu.c */
+int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low);
+int s390_set_clock(uint8_t *tod_high, uint64_t *tod_low);
+void s390_crypto_reset(void);
+bool s390_get_squash_mcss(void);
+int s390_get_memslot_count(void);
+int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
+void s390_cmma_reset(void);
+int s390_cpu_restart(S390CPU *cpu);
+void s390_enable_css_support(S390CPU *cpu);
+int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
+ int vq, bool assign);
+#ifndef CONFIG_USER_ONLY
+unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
+#else
+static inline unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
+{
+ return 0;
+}
+#endif /* CONFIG_USER_ONLY */
+
+
+/* cpu_models.c */
+void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
+#define cpu_list s390_cpu_list
+const char *s390_default_cpu_model_name(void);
+
+
+/* helper.c */
+S390CPU *cpu_s390x_init(const char *cpu_model);
+#define cpu_init(model) CPU(cpu_s390x_init(model))
+S390CPU *s390x_new_cpu(const char *cpu_model, int64_t id, Error **errp);
+/* you can call this signal handler from your SIGBUS and SIGSEGV
+ signal handlers to inform the virtual CPU of exceptions. non zero
+ is returned if the signal was handled by the virtual CPU. */
+int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc);
+#define cpu_signal_handler cpu_s390x_signal_handler
+
+
+/* interrupt.c */
+void s390_crw_mchk(void);
+void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
+ uint32_t io_int_parm, uint32_t io_int_word);
+/* automatically detect the instruction length */
+#define ILEN_AUTO 0xff
+void program_interrupt(CPUS390XState *env, uint32_t code, int ilen);
+/* service interrupts are floating therefore we must not pass an cpustate */
+void s390_sclp_extint(uint32_t parm);
+
+
+/* mmu_helper.c */
+int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, uint8_t ar, void *hostbuf,
+ int len, bool is_write);
+#define s390_cpu_virt_mem_read(cpu, laddr, ar, dest, len) \
+ s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, false)
+#define s390_cpu_virt_mem_write(cpu, laddr, ar, dest, len) \
+ s390_cpu_virt_mem_rw(cpu, laddr, ar, dest, len, true)
+#define s390_cpu_virt_mem_check_write(cpu, laddr, ar, len) \
+ s390_cpu_virt_mem_rw(cpu, laddr, ar, NULL, len, true)
+
+
+/* outside of target/s390x/ */
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
+extern void subsystem_reset(void);
+int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code);
+int s390_virtio_hypercall(CPUS390XState *env);
+
#endif
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index fa1338fc72..18cbf91d9c 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -12,6 +12,9 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
+#include "sysemu/kvm.h"
#include "gen-features.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
@@ -1200,6 +1203,14 @@ ObjectClass *s390_cpu_class_by_name(const char *name)
return oc;
}
+const char *s390_default_cpu_model_name(void)
+{
+ if (kvm_enabled()) {
+ return "host";
+ }
+ return "qemu";
+}
+
static const TypeInfo qemu_s390_cpu_type_info = {
.name = S390_CPU_TYPE_NAME("qemu"),
.parent = TYPE_S390_CPU,
diff --git a/target/s390x/diag.c b/target/s390x/diag.c
index 10ac845bcd..e6b5e6de37 100644
--- a/target/s390x/diag.c
+++ b/target/s390x/diag.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/address-spaces.h"
#include "exec/exec-all.h"
#include "hw/watchdog/wdt_diag288.h"
@@ -39,6 +40,13 @@ static int modified_clear_reset(S390CPU *cpu)
return 0;
}
+static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg)
+{
+ S390CPUClass *scc = S390_CPU_GET_CLASS(cs);
+
+ scc->cpu_reset(cs);
+}
+
static int load_normal_reset(S390CPU *cpu)
{
S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index d1833772d5..361f970db3 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "internal.h"
#include "qemu/timer.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
@@ -68,6 +69,20 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
#else /* !CONFIG_USER_ONLY */
+static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
+{
+ switch (mmu_idx) {
+ case MMU_PRIMARY_IDX:
+ return PSW_ASC_PRIMARY;
+ case MMU_SECONDARY_IDX:
+ return PSW_ASC_SECONDARY;
+ case MMU_HOME_IDX:
+ return PSW_ASC_HOME;
+ default:
+ abort();
+ }
+}
+
int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr,
int rw, int mmu_idx)
{
diff --git a/target/s390x/fpu_helper.c b/target/s390x/fpu_helper.c
index 26f124fe96..ffbeb3b2df 100644
--- a/target/s390x/fpu_helper.c
+++ b/target/s390x/fpu_helper.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
#include "exec/helper-proto.h"
diff --git a/target/s390x/gdbstub.c b/target/s390x/gdbstub.c
index a7efafee9f..b8c81dadcf 100644
--- a/target/s390x/gdbstub.c
+++ b/target/s390x/gdbstub.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/exec-all.h"
#include "exec/gdbstub.h"
#include "qemu/bitops.h"
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 0c989b1610..3adb9de122 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/gdbstub.h"
#include "qemu/timer.h"
#include "exec/exec-all.h"
@@ -352,3 +353,51 @@ void s390_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n");
}
+
+const char *cc_name(enum cc_op cc_op)
+{
+ static const char * const cc_names[] = {
+ [CC_OP_CONST0] = "CC_OP_CONST0",
+ [CC_OP_CONST1] = "CC_OP_CONST1",
+ [CC_OP_CONST2] = "CC_OP_CONST2",
+ [CC_OP_CONST3] = "CC_OP_CONST3",
+ [CC_OP_DYNAMIC] = "CC_OP_DYNAMIC",
+ [CC_OP_STATIC] = "CC_OP_STATIC",
+ [CC_OP_NZ] = "CC_OP_NZ",
+ [CC_OP_LTGT_32] = "CC_OP_LTGT_32",
+ [CC_OP_LTGT_64] = "CC_OP_LTGT_64",
+ [CC_OP_LTUGTU_32] = "CC_OP_LTUGTU_32",
+ [CC_OP_LTUGTU_64] = "CC_OP_LTUGTU_64",
+ [CC_OP_LTGT0_32] = "CC_OP_LTGT0_32",
+ [CC_OP_LTGT0_64] = "CC_OP_LTGT0_64",
+ [CC_OP_ADD_64] = "CC_OP_ADD_64",
+ [CC_OP_ADDU_64] = "CC_OP_ADDU_64",
+ [CC_OP_ADDC_64] = "CC_OP_ADDC_64",
+ [CC_OP_SUB_64] = "CC_OP_SUB_64",
+ [CC_OP_SUBU_64] = "CC_OP_SUBU_64",
+ [CC_OP_SUBB_64] = "CC_OP_SUBB_64",
+ [CC_OP_ABS_64] = "CC_OP_ABS_64",
+ [CC_OP_NABS_64] = "CC_OP_NABS_64",
+ [CC_OP_ADD_32] = "CC_OP_ADD_32",
+ [CC_OP_ADDU_32] = "CC_OP_ADDU_32",
+ [CC_OP_ADDC_32] = "CC_OP_ADDC_32",
+ [CC_OP_SUB_32] = "CC_OP_SUB_32",
+ [CC_OP_SUBU_32] = "CC_OP_SUBU_32",
+ [CC_OP_SUBB_32] = "CC_OP_SUBB_32",
+ [CC_OP_ABS_32] = "CC_OP_ABS_32",
+ [CC_OP_NABS_32] = "CC_OP_NABS_32",
+ [CC_OP_COMP_32] = "CC_OP_COMP_32",
+ [CC_OP_COMP_64] = "CC_OP_COMP_64",
+ [CC_OP_TM_32] = "CC_OP_TM_32",
+ [CC_OP_TM_64] = "CC_OP_TM_64",
+ [CC_OP_NZ_F32] = "CC_OP_NZ_F32",
+ [CC_OP_NZ_F64] = "CC_OP_NZ_F64",
+ [CC_OP_NZ_F128] = "CC_OP_NZ_F128",
+ [CC_OP_ICM] = "CC_OP_ICM",
+ [CC_OP_SLA_32] = "CC_OP_SLA_32",
+ [CC_OP_SLA_64] = "CC_OP_SLA_64",
+ [CC_OP_FLOGR] = "CC_OP_FLOGR",
+ };
+
+ return cc_names[cc_op];
+}
diff --git a/target/s390x/int_helper.c b/target/s390x/int_helper.c
index f26f36a904..0076bea047 100644
--- a/target/s390x/int_helper.c
+++ b/target/s390x/int_helper.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
new file mode 100644
index 0000000000..b4d3583b24
--- /dev/null
+++ b/target/s390x/internal.h
@@ -0,0 +1,391 @@
+/*
+ * s390x internal definitions and helpers
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef S390X_INTERNAL_H
+#define S390X_INTERNAL_H
+
+#include "cpu.h"
+
+#ifndef CONFIG_USER_ONLY
+typedef struct LowCore {
+ /* prefix area: defined by architecture */
+ uint32_t ccw1[2]; /* 0x000 */
+ uint32_t ccw2[4]; /* 0x008 */
+ 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 */
+ uint32_t mcck_interruption_code[2]; /* 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 */
+ PSW return_psw; /* 0x200 */
+ uint8_t irb[64]; /* 0x210 */
+ uint64_t sync_enter_timer; /* 0x250 */
+ uint64_t async_enter_timer; /* 0x258 */
+ uint64_t exit_timer; /* 0x260 */
+ uint64_t last_update_timer; /* 0x268 */
+ uint64_t user_timer; /* 0x270 */
+ uint64_t system_timer; /* 0x278 */
+ uint64_t last_update_clock; /* 0x280 */
+ uint64_t steal_clock; /* 0x288 */
+ PSW return_mcck_psw; /* 0x290 */
+ uint8_t pad9[0xc00 - 0x2a0]; /* 0x2a0 */
+ /* System info area */
+ uint64_t save_area[16]; /* 0xc00 */
+ uint8_t pad10[0xd40 - 0xc80]; /* 0xc80 */
+ uint64_t kernel_stack; /* 0xd40 */
+ uint64_t thread_info; /* 0xd48 */
+ uint64_t async_stack; /* 0xd50 */
+ uint64_t kernel_asce; /* 0xd58 */
+ uint64_t user_asce; /* 0xd60 */
+ uint64_t panic_stack; /* 0xd68 */
+ uint64_t user_exec_asce; /* 0xd70 */
+ uint8_t pad11[0xdc0 - 0xd78]; /* 0xd78 */
+
+ /* SMP info area: defined by DJB */
+ uint64_t clock_comparator; /* 0xdc0 */
+ uint64_t ext_call_fast; /* 0xdc8 */
+ uint64_t percpu_offset; /* 0xdd0 */
+ uint64_t current_task; /* 0xdd8 */
+ uint32_t softirq_pending; /* 0xde0 */
+ uint32_t pad_0x0de4; /* 0xde4 */
+ uint64_t int_clock; /* 0xde8 */
+ uint8_t pad12[0xe00 - 0xdf0]; /* 0xdf0 */
+
+ /* 0xe00 is used as indicator for dump tools */
+ /* whether the kernel died with panic() or not */
+ uint32_t panic_magic; /* 0xe00 */
+
+ uint8_t pad13[0x11b8 - 0xe04]; /* 0xe04 */
+
+ /* 64 bit extparam used for pfault, diag 250 etc */
+ uint64_t ext_params2; /* 0x11B8 */
+
+ uint8_t pad14[0x1200 - 0x11C0]; /* 0x11C0 */
+
+ /* System info area */
+
+ uint64_t floating_pt_save_area[16]; /* 0x1200 */
+ uint64_t gpregs_save_area[16]; /* 0x1280 */
+ uint32_t st_status_fixed_logout[4]; /* 0x1300 */
+ uint8_t pad15[0x1318 - 0x1310]; /* 0x1310 */
+ uint32_t prefixreg_save_area; /* 0x1318 */
+ uint32_t fpt_creg_save_area; /* 0x131c */
+ uint8_t pad16[0x1324 - 0x1320]; /* 0x1320 */
+ uint32_t tod_progreg_save_area; /* 0x1324 */
+ uint32_t cpu_timer_save_area[2]; /* 0x1328 */
+ uint32_t clock_comp_save_area[2]; /* 0x1330 */
+ uint8_t pad17[0x1340 - 0x1338]; /* 0x1338 */
+ uint32_t access_regs_save_area[16]; /* 0x1340 */
+ uint64_t cregs_save_area[16]; /* 0x1380 */
+
+ /* align to the top of the prefix area */
+
+ uint8_t pad18[0x2000 - 0x1400]; /* 0x1400 */
+} QEMU_PACKED LowCore;
+#endif /* CONFIG_USER_ONLY */
+
+#define MAX_ILEN 6
+
+/* While the PoO talks about ILC (a number between 1-3) what is actually
+ stored in LowCore is shifted left one bit (an even between 2-6). As
+ this is the actual length of the insn and therefore more useful, that
+ is what we want to pass around and manipulate. To make sure that we
+ have applied this distinction universally, rename the "ILC" to "ILEN". */
+static inline int get_ilen(uint8_t opc)
+{
+ switch (opc >> 6) {
+ case 0:
+ return 2;
+ case 1:
+ case 2:
+ return 4;
+ default:
+ return 6;
+ }
+}
+
+/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
+ entry when a PER exception is triggered. */
+static inline uint8_t get_per_atmid(CPUS390XState *env)
+{
+ return ((env->psw.mask & PSW_MASK_64) ? (1 << 7) : 0) |
+ (1 << 6) |
+ ((env->psw.mask & PSW_MASK_32) ? (1 << 5) : 0) |
+ ((env->psw.mask & PSW_MASK_DAT) ? (1 << 4) : 0) |
+ ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
+ ((env->psw.mask & PSW_ASC_ACCREG) ? (1 << 2) : 0);
+}
+
+/* CC optimization */
+
+/* Instead of computing the condition codes after each x86 instruction,
+ * QEMU just stores the result (called CC_DST), the type of operation
+ * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
+ * CC_VR). When the condition codes are needed, the condition codes can
+ * be calculated using this information. Condition codes are not generated
+ * if they are only needed for conditional branches.
+ */
+enum cc_op {
+ CC_OP_CONST0 = 0, /* CC is 0 */
+ CC_OP_CONST1, /* CC is 1 */
+ CC_OP_CONST2, /* CC is 2 */
+ CC_OP_CONST3, /* CC is 3 */
+
+ CC_OP_DYNAMIC, /* CC calculation defined by env->cc_op */
+ CC_OP_STATIC, /* CC value is env->cc_op */
+
+ CC_OP_NZ, /* env->cc_dst != 0 */
+ CC_OP_LTGT_32, /* signed less/greater than (32bit) */
+ CC_OP_LTGT_64, /* signed less/greater than (64bit) */
+ CC_OP_LTUGTU_32, /* unsigned less/greater than (32bit) */
+ CC_OP_LTUGTU_64, /* unsigned less/greater than (64bit) */
+ CC_OP_LTGT0_32, /* signed less/greater than 0 (32bit) */
+ CC_OP_LTGT0_64, /* signed less/greater than 0 (64bit) */
+
+ CC_OP_ADD_64, /* overflow on add (64bit) */
+ CC_OP_ADDU_64, /* overflow on unsigned add (64bit) */
+ CC_OP_ADDC_64, /* overflow on unsigned add-carry (64bit) */
+ CC_OP_SUB_64, /* overflow on subtraction (64bit) */
+ CC_OP_SUBU_64, /* overflow on unsigned subtraction (64bit) */
+ CC_OP_SUBB_64, /* overflow on unsigned sub-borrow (64bit) */
+ CC_OP_ABS_64, /* sign eval on abs (64bit) */
+ CC_OP_NABS_64, /* sign eval on nabs (64bit) */
+
+ CC_OP_ADD_32, /* overflow on add (32bit) */
+ CC_OP_ADDU_32, /* overflow on unsigned add (32bit) */
+ CC_OP_ADDC_32, /* overflow on unsigned add-carry (32bit) */
+ CC_OP_SUB_32, /* overflow on subtraction (32bit) */
+ CC_OP_SUBU_32, /* overflow on unsigned subtraction (32bit) */
+ CC_OP_SUBB_32, /* overflow on unsigned sub-borrow (32bit) */
+ CC_OP_ABS_32, /* sign eval on abs (64bit) */
+ CC_OP_NABS_32, /* sign eval on nabs (64bit) */
+
+ CC_OP_COMP_32, /* complement */
+ CC_OP_COMP_64, /* complement */
+
+ CC_OP_TM_32, /* test under mask (32bit) */
+ CC_OP_TM_64, /* test under mask (64bit) */
+
+ CC_OP_NZ_F32, /* FP dst != 0 (32bit) */
+ CC_OP_NZ_F64, /* FP dst != 0 (64bit) */
+ CC_OP_NZ_F128, /* FP dst != 0 (128bit) */
+
+ CC_OP_ICM, /* insert characters under mask */
+ CC_OP_SLA_32, /* Calculate shift left signed (32bit) */
+ CC_OP_SLA_64, /* Calculate shift left signed (64bit) */
+ CC_OP_FLOGR, /* find leftmost one */
+ CC_OP_MAX
+};
+
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
+/* Converts ns to s390's clock format */
+static inline uint64_t time2tod(uint64_t ns)
+{
+ return (ns << 9) / 125;
+}
+
+/* Converts s390's clock format to ns */
+static inline uint64_t tod2time(uint64_t t)
+{
+ return (t * 125) >> 9;
+}
+
+static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
+ uint8_t *ar)
+{
+ hwaddr addr = 0;
+ uint8_t reg;
+
+ reg = ipb >> 28;
+ if (reg > 0) {
+ addr = env->regs[reg];
+ }
+ addr += (ipb >> 16) & 0xfff;
+ if (ar) {
+ *ar = reg;
+ }
+
+ return addr;
+}
+
+/* Base/displacement are at the same locations. */
+#define decode_basedisp_rs decode_basedisp_s
+
+static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
+{
+ cpu_reset(cs);
+}
+
+static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
+{
+ return cpu->env.cpu_state;
+}
+
+
+/* arch_dump.c */
+int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque);
+
+
+/* cc_helper.c */
+const char *cc_name(enum cc_op cc_op);
+void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
+uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
+ uint64_t vr);
+
+
+/* cpu.c */
+#ifndef CONFIG_USER_ONLY
+unsigned int s390_cpu_halt(S390CPU *cpu);
+void s390_cpu_unhalt(S390CPU *cpu);
+#else
+static inline unsigned int s390_cpu_halt(S390CPU *cpu)
+{
+ return 0;
+}
+
+static inline void s390_cpu_unhalt(S390CPU *cpu)
+{
+}
+#endif /* CONFIG_USER_ONLY */
+
+
+/* cpu_models.c */
+void s390_cpu_model_register_props(Object *obj);
+void s390_cpu_model_class_register_props(ObjectClass *oc);
+void s390_realize_cpu_model(CPUState *cs, Error **errp);
+ObjectClass *s390_cpu_class_by_name(const char *name);
+
+
+/* excp_helper.c */
+void s390x_cpu_debug_excp_handler(CPUState *cs);
+void s390_cpu_do_interrupt(CPUState *cpu);
+bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
+int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
+ int mmu_idx);
+void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr);
+
+
+/* fpu_helper.c */
+uint32_t set_cc_nz_f32(float32 v);
+uint32_t set_cc_nz_f64(float64 v);
+uint32_t set_cc_nz_f128(float128 v);
+
+
+/* gdbstub.c */
+int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
+int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+void s390_cpu_gdb_init(CPUState *cs);
+
+
+/* helper.c */
+void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
+ int flags);
+hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
+uint64_t get_psw_mask(CPUS390XState *env);
+void s390_cpu_recompute_watchpoints(CPUState *cs);
+void s390x_tod_timer(void *opaque);
+void s390x_cpu_timer(void *opaque);
+S390CPU *cpu_s390x_create(const char *cpu_model, Error **errp);
+void do_restart_interrupt(CPUS390XState *env);
+#ifndef CONFIG_USER_ONLY
+LowCore *cpu_map_lowcore(CPUS390XState *env);
+void cpu_unmap_lowcore(LowCore *lowcore);
+#endif /* CONFIG_USER_ONLY */
+
+
+/* interrupt.c */
+void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
+void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
+ uint64_t param64);
+
+
+/* ioinst.c */
+void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb);
+void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb);
+void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb);
+int ioinst_handle_tpi(S390CPU *cpu, uint32_t ipb);
+void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
+ uint32_t ipb);
+void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1);
+void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1);
+
+
+/* mem_helper.c */
+target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
+
+
+/* mmu_helper.c */
+int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
+ target_ulong *raddr, int *flags, bool exc);
+
+
+/* misc_helper.c */
+void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
+ uintptr_t retaddr);
+int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
+void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3);
+
+
+/* translate.c */
+void s390x_translate_init(void);
+
+#endif /* S390X_INTERNAL_H */
diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c
index fde3da793a..058e219fe5 100644
--- a/target/s390x/interrupt.c
+++ b/target/s390x/interrupt.c
@@ -10,6 +10,8 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h"
+#include "kvm_s390x.h"
+#include "internal.h"
#include "exec/exec-all.h"
#include "sysemu/kvm.h"
#include "hw/s390x/ioinst.h"
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index 51fbea620d..47490f838a 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "hw/s390x/ioinst.h"
#include "trace.h"
#include "hw/s390x/s390-pci-bus.h"
@@ -599,6 +600,22 @@ static int chsc_sei_nt0_have_event(void)
return 0;
}
+static int chsc_sei_nt2_get_event(void *res)
+{
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return pci_chsc_sei_nt2_get_event(res);
+ }
+ return 1;
+}
+
+static int chsc_sei_nt2_have_event(void)
+{
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return pci_chsc_sei_nt2_have_event();
+ }
+ return 0;
+}
+
#define CHSC_SEI_NT0 (1ULL << 63)
#define CHSC_SEI_NT2 (1ULL << 61)
static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
new file mode 100644
index 0000000000..261e1cdc44
--- /dev/null
+++ b/target/s390x/kvm-stub.c
@@ -0,0 +1,111 @@
+/*
+ * QEMU KVM support -- s390x specific function stubs.
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "kvm_s390x.h"
+
+void kvm_s390_service_interrupt(uint32_t parm)
+{
+}
+
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code)
+{
+}
+
+int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
+ int len, bool is_write)
+{
+ return -ENOSYS;
+}
+
+void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code)
+{
+}
+
+void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
+ uint32_t io_int_parm, uint32_t io_int_word)
+{
+}
+
+void kvm_s390_crw_mchk(void)
+{
+}
+
+int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
+{
+ return -ENOSYS;
+}
+
+void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu)
+{
+}
+
+int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
+{
+ return 0;
+}
+
+int kvm_s390_get_ri(void)
+{
+ return 0;
+}
+
+int kvm_s390_get_gs(void)
+{
+ return 0;
+}
+
+int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ return -ENOSYS;
+}
+
+int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
+{
+ return -ENOSYS;
+}
+
+void kvm_s390_enable_css_support(S390CPU *cpu)
+{
+}
+
+int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
+ int vq, bool assign)
+{
+ return -ENOSYS;
+}
+
+int kvm_s390_cpu_restart(S390CPU *cpu)
+{
+ return -ENOSYS;
+}
+
+void kvm_s390_cmma_reset(void)
+{
+}
+
+int kvm_s390_get_memslot_count(void)
+{
+ return MAX_AVAIL_SLOTS;
+}
+
+void kvm_s390_reset_vcpu(S390CPU *cpu)
+{
+}
+
+int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
+{
+ return 0;
+}
+
+void kvm_s390_crypto_reset(void)
+{
+}
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index c4c5791d27..d07763ff2c 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -29,6 +29,8 @@
#include "qemu-common.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
#include "qemu/error-report.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
@@ -145,7 +147,7 @@ static int active_cmma;
static void *legacy_s390_alloc(size_t size, uint64_t *align);
-static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
+static int kvm_s390_query_mem_limit(uint64_t *memory_limit)
{
struct kvm_device_attr attr = {
.group = KVM_S390_VM_MEM_CTRL,
@@ -153,10 +155,10 @@ static int kvm_s390_query_mem_limit(KVMState *s, uint64_t *memory_limit)
.addr = (uint64_t) memory_limit,
};
- return kvm_vm_ioctl(s, KVM_GET_DEVICE_ATTR, &attr);
+ return kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
}
-int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
+int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
{
int rc;
@@ -166,18 +168,18 @@ int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit)
.addr = (uint64_t) &new_limit,
};
- if (!kvm_vm_check_mem_attr(s, KVM_S390_VM_MEM_LIMIT_SIZE)) {
+ if (!kvm_vm_check_mem_attr(kvm_state, KVM_S390_VM_MEM_LIMIT_SIZE)) {
return 0;
}
- rc = kvm_s390_query_mem_limit(s, hw_limit);
+ rc = kvm_s390_query_mem_limit(hw_limit);
if (rc) {
return rc;
} else if (*hw_limit < new_limit) {
return -E2BIG;
}
- return kvm_vm_ioctl(s, KVM_SET_DEVICE_ATTR, &attr);
+ return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
}
int kvm_s390_cmma_active(void)
@@ -1191,7 +1193,11 @@ static int kvm_clp_service_call(S390CPU *cpu, struct kvm_run *run)
{
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
- return clp_service_call(cpu, r2);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return clp_service_call(cpu, r2);
+ } else {
+ return -1;
+ }
}
static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1199,7 +1205,11 @@ static int kvm_pcilg_service_call(S390CPU *cpu, struct kvm_run *run)
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
- return pcilg_service_call(cpu, r1, r2);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return pcilg_service_call(cpu, r1, r2);
+ } else {
+ return -1;
+ }
}
static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1207,7 +1217,11 @@ static int kvm_pcistg_service_call(S390CPU *cpu, struct kvm_run *run)
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
- return pcistg_service_call(cpu, r1, r2);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return pcistg_service_call(cpu, r1, r2);
+ } else {
+ return -1;
+ }
}
static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1216,10 +1230,14 @@ static int kvm_stpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
uint64_t fiba;
uint8_t ar;
- cpu_synchronize_state(CPU(cpu));
- fiba = get_base_disp_rxy(cpu, run, &ar);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ cpu_synchronize_state(CPU(cpu));
+ fiba = get_base_disp_rxy(cpu, run, &ar);
- return stpcifc_service_call(cpu, r1, fiba, ar);
+ return stpcifc_service_call(cpu, r1, fiba, ar);
+ } else {
+ return -1;
+ }
}
static int kvm_sic_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1247,7 +1265,11 @@ static int kvm_rpcit_service_call(S390CPU *cpu, struct kvm_run *run)
uint8_t r1 = (run->s390_sieic.ipb & 0x00f00000) >> 20;
uint8_t r2 = (run->s390_sieic.ipb & 0x000f0000) >> 16;
- return rpcit_service_call(cpu, r1, r2);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ return rpcit_service_call(cpu, r1, r2);
+ } else {
+ return -1;
+ }
}
static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1257,10 +1279,14 @@ static int kvm_pcistb_service_call(S390CPU *cpu, struct kvm_run *run)
uint64_t gaddr;
uint8_t ar;
- cpu_synchronize_state(CPU(cpu));
- gaddr = get_base_disp_rsy(cpu, run, &ar);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ cpu_synchronize_state(CPU(cpu));
+ gaddr = get_base_disp_rsy(cpu, run, &ar);
- return pcistb_service_call(cpu, r1, r3, gaddr, ar);
+ return pcistb_service_call(cpu, r1, r3, gaddr, ar);
+ } else {
+ return -1;
+ }
}
static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
@@ -1269,10 +1295,14 @@ static int kvm_mpcifc_service_call(S390CPU *cpu, struct kvm_run *run)
uint64_t fiba;
uint8_t ar;
- cpu_synchronize_state(CPU(cpu));
- fiba = get_base_disp_rxy(cpu, run, &ar);
+ if (s390_has_feat(S390_FEAT_ZPCI)) {
+ cpu_synchronize_state(CPU(cpu));
+ fiba = get_base_disp_rxy(cpu, run, &ar);
- return mpcifc_service_call(cpu, r1, fiba, ar);
+ return mpcifc_service_call(cpu, r1, fiba, ar);
+ } else {
+ return -1;
+ }
}
static int handle_b9(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
@@ -2289,9 +2319,9 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
}
-int kvm_s390_get_memslot_count(KVMState *s)
+int kvm_s390_get_memslot_count(void)
{
- return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
+ return kvm_check_extension(kvm_state, KVM_CAP_NR_MEMSLOTS);
}
int kvm_s390_get_ri(void)
@@ -2662,7 +2692,9 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
}
/* We emulate a zPCI bus and AEN, therefore we don't need HW support */
- set_bit(S390_FEAT_ZPCI, model->features);
+ if (pci_available) {
+ set_bit(S390_FEAT_ZPCI, model->features);
+ }
set_bit(S390_FEAT_ADAPTER_EVENT_NOTIFICATION, model->features);
if (s390_known_cpu_type(cpu_type)) {
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
new file mode 100644
index 0000000000..2d594bd4ee
--- /dev/null
+++ b/target/s390x/kvm_s390x.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU KVM support -- s390x specific functions.
+ *
+ * Copyright (c) 2009 Ulrich Hecht
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef KVM_S390X_H
+#define KVM_S390X_H
+
+struct kvm_s390_irq;
+
+void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
+void kvm_s390_service_interrupt(uint32_t parm);
+void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
+void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
+int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, uint8_t ar, void *hostbuf,
+ int len, bool is_write);
+void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code);
+void kvm_s390_io_interrupt(uint16_t subchannel_id,
+ uint16_t subchannel_nr, uint32_t io_int_parm,
+ uint32_t io_int_word);
+void kvm_s390_crw_mchk(void);
+int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state);
+void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
+int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
+int kvm_s390_get_ri(void);
+int kvm_s390_get_gs(void);
+int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
+int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
+void kvm_s390_enable_css_support(S390CPU *cpu);
+int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
+ int vq, bool assign);
+int kvm_s390_cpu_restart(S390CPU *cpu);
+int kvm_s390_get_memslot_count(void);
+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_crypto_reset(void);
+
+/* implemented outside of target/s390x/ */
+int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
+
+#endif /* KVM_S390X_H */
diff --git a/target/s390x/machine.c b/target/s390x/machine.c
index 2dcadfdd29..097a147dbb 100644
--- a/target/s390x/machine.c
+++ b/target/s390x/machine.c
@@ -17,6 +17,8 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
#include "sysemu/kvm.h"
static int cpu_post_load(void *opaque, int version_id)
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index c71dce4b1e..ec4760e390 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/address-spaces.h"
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
@@ -56,6 +57,17 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
#define HELPER_LOG(x...)
#endif
+static inline bool psw_key_valid(CPUS390XState *env, uint8_t psw_key)
+{
+ uint16_t pkm = env->cregs[3] >> 16;
+
+ if (env->psw.mask & PSW_MASK_PSTATE) {
+ /* PSW key has range 0..15, it is valid if the bit is 1 in the PKM */
+ return pkm & (0x80 >> psw_key);
+ }
+ return true;
+}
+
/* Reduce the length so that addr + len doesn't cross a page boundary. */
static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr)
{
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index d23ffcd890..50cc046ca2 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "cpu.h"
+#include "internal.h"
#include "exec/memory.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
@@ -103,13 +104,17 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
handle_diag_308(env, r1, r3);
r = 0;
break;
+ case 0x288:
+ /* time bomb (watchdog) */
+ r = handle_diag_288(env, r1, r3);
+ break;
default:
r = -1;
break;
}
if (r) {
- program_interrupt(env, PGM_OPERATION, ILEN_AUTO);
+ program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
}
}
@@ -451,6 +456,17 @@ void HELPER(per_check_exception)(CPUS390XState *env)
}
}
+/* Check if an address is within the PER starting address and the PER
+ ending address. The address range might loop. */
+static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
+{
+ if (env->cregs[10] <= env->cregs[11]) {
+ return env->cregs[10] <= addr && addr <= env->cregs[11];
+ } else {
+ return env->cregs[10] <= addr || addr <= env->cregs[11];
+ }
+}
+
void HELPER(per_branch)(CPUS390XState *env, uint64_t from, uint64_t to)
{
if ((env->cregs[9] & PER_CR9_EVENT_BRANCH)) {
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c
index 1ad01584b4..b528c5921d 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -19,6 +19,8 @@
#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "cpu.h"
+#include "internal.h"
+#include "kvm_s390x.h"
#include "sysemu/kvm.h"
#include "trace.h"
#include "hw/s390x/storage-keys.h"
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index cd96a8dee2..4b0db7b7bd 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -30,6 +30,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "internal.h"
#include "disas/disas.h"
#include "exec/exec-all.h"
#include "tcg-op.h"
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 37c1bed683..f08b7418f0 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -283,8 +283,8 @@ ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),)
check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
endif
check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
-check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
-check-qtest-i386-y += tests/test-filter-redirector$(EXESUF)
+check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
+check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
check-qtest-i386-y += tests/postcopy-test$(EXESUF)
check-qtest-i386-y += tests/test-x86-cpuid-compat$(EXESUF)
check-qtest-i386-y += tests/numa-test$(EXESUF)
@@ -325,8 +325,8 @@ check-qtest-ppc64-y += tests/usb-hcd-xhci-test$(EXESUF)
gcov-files-ppc64-y += hw/usb/hcd-xhci.c
check-qtest-ppc64-y += $(check-qtest-virtio-y)
check-qtest-ppc64-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
-check-qtest-ppc64-y += tests/test-filter-mirror$(EXESUF)
-check-qtest-ppc64-y += tests/test-filter-redirector$(EXESUF)
+check-qtest-ppc64-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
+check-qtest-ppc64-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
check-qtest-ppc64-y += tests/display-vga-test$(EXESUF)
check-qtest-ppc64-y += tests/numa-test$(EXESUF)
check-qtest-ppc64-$(CONFIG_IVSHMEM) += tests/ivshmem-test$(EXESUF)
@@ -360,6 +360,10 @@ check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
+check-qtest-s390x-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
+check-qtest-s390x-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
+check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
+check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF)
check-qtest-generic-y += tests/qom-test$(EXESUF)
check-qtest-generic-y += tests/test-hmp$(EXESUF)
diff --git a/tests/boot-sector.c b/tests/boot-sector.c
index e3880f4455..9ee85370b0 100644
--- a/tests/boot-sector.c
+++ b/tests/boot-sector.c
@@ -21,13 +21,12 @@
#define SIGNATURE 0xdead
#define SIGNATURE_OFFSET 0x10
#define BOOT_SECTOR_ADDRESS 0x7c00
+#define SIGNATURE_ADDR (BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET)
-/* Boot sector code: write SIGNATURE into memory,
+/* x86 boot sector code: write SIGNATURE into memory,
* then halt.
- * Q35 machine requires a minimum 0x7e000 bytes disk.
- * (bug or feature?)
*/
-static uint8_t boot_sector[0x7e000] = {
+static uint8_t x86_boot_sector[512] = {
/* The first sector will be placed at RAM address 00007C00, and
* the BIOS transfers control to 00007C00
*/
@@ -50,8 +49,8 @@ static uint8_t boot_sector[0x7e000] = {
[0x07] = HIGH(SIGNATURE),
/* 7c08: mov %ax,0x7c10 */
[0x08] = 0xa3,
- [0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
- [0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+ [0x09] = LOW(SIGNATURE_ADDR),
+ [0x0a] = HIGH(SIGNATURE_ADDR),
/* 7c0b cli */
[0x0b] = 0xfa,
@@ -68,11 +67,28 @@ static uint8_t boot_sector[0x7e000] = {
[0x1FF] = 0xAA,
};
+/* For s390x, use a mini "kernel" with the appropriate signature */
+static const uint8_t s390x_psw[] = {
+ 0x00, 0x08, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00
+};
+static const uint8_t s390x_code[] = {
+ 0xa7, 0xf4, 0x00, 0x0a, /* j 0x10010 */
+ 0x00, 0x00, 0x00, 0x00,
+ 'S', '3', '9', '0',
+ 'E', 'P', 0x00, 0x01,
+ 0xa7, 0x38, HIGH(SIGNATURE_ADDR), LOW(SIGNATURE_ADDR), /* lhi r3,0x7c10 */
+ 0xa7, 0x48, LOW(SIGNATURE), HIGH(SIGNATURE), /* lhi r4,0xadde */
+ 0x40, 0x40, 0x30, 0x00, /* sth r4,0(r3) */
+ 0xa7, 0xf4, 0xff, 0xfa /* j 0x10010 */
+};
+
/* Create boot disk file. */
int boot_sector_init(char *fname)
{
int fd, ret;
- size_t len = sizeof boot_sector;
+ size_t len;
+ char *boot_code;
+ const char *arch = qtest_get_arch();
fd = mkstemp(fname);
if (fd < 0) {
@@ -80,16 +96,31 @@ int boot_sector_init(char *fname)
return 1;
}
- /* For Open Firmware based system, we can use a Forth script instead */
- if (strcmp(qtest_get_arch(), "ppc64") == 0) {
- len = sprintf((char *)boot_sector, "\\ Bootscript\n%x %x c! %x %x c!\n",
- LOW(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET,
- HIGH(SIGNATURE), BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+ if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64")) {
+ /* Q35 requires a minimum 0x7e000 bytes disk (bug or feature?) */
+ len = MAX(0x7e000, sizeof(x86_boot_sector));
+ boot_code = g_malloc0(len);
+ memcpy(boot_code, x86_boot_sector, sizeof(x86_boot_sector));
+ } else if (g_str_equal(arch, "ppc64")) {
+ /* For Open Firmware based system, use a Forth script */
+ boot_code = g_strdup_printf("\\ Bootscript\n%x %x c! %x %x c!\n",
+ LOW(SIGNATURE), SIGNATURE_ADDR,
+ HIGH(SIGNATURE), SIGNATURE_ADDR + 1);
+ len = strlen(boot_code);
+ } else if (g_str_equal(arch, "s390x")) {
+ len = 0x10000 + sizeof(s390x_code);
+ boot_code = g_malloc0(len);
+ memcpy(boot_code, s390x_psw, sizeof(s390x_psw));
+ memcpy(&boot_code[0x10000], s390x_code, sizeof(s390x_code));
+ } else {
+ g_assert_not_reached();
}
- ret = write(fd, boot_sector, len);
+ ret = write(fd, boot_code, len);
close(fd);
+ g_free(boot_code);
+
if (ret != len) {
fprintf(stderr, "Could not write \"%s\"", fname);
return 1;
@@ -115,8 +146,8 @@ void boot_sector_test(void)
* instruction.
*/
for (i = 0; i < TEST_CYCLES; ++i) {
- signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
- signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+ signature_low = readb(SIGNATURE_ADDR);
+ signature_high = readb(SIGNATURE_ADDR + 1);
signature = (signature_high << 8) | signature_low;
if (signature == SIGNATURE) {
break;
diff --git a/tests/pxe-test.c b/tests/pxe-test.c
index cf6e225330..0d70afccd6 100644
--- a/tests/pxe-test.c
+++ b/tests/pxe-test.c
@@ -51,6 +51,11 @@ static void test_pxe_spapr_vlan(void)
test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
}
+static void test_pxe_virtio_ccw(void)
+{
+ test_pxe_one("-device virtio-net-ccw,bootindex=1,netdev=" NETNAME, false);
+}
+
int main(int argc, char *argv[])
{
int ret;
@@ -68,6 +73,8 @@ int main(int argc, char *argv[])
} else if (strcmp(arch, "ppc64") == 0) {
qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
+ } else if (g_str_equal(arch, "s390x")) {
+ qtest_add_func("pxe/virtio-ccw", test_pxe_virtio_ccw);
}
ret = g_test_run();
boot_sector_cleanup(disk);
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
index bff9360048..0306f112da 100755
--- a/tests/qemu-iotests/083
+++ b/tests/qemu-iotests/083
@@ -27,6 +27,14 @@ echo "QA output created by $seq"
here=`pwd`
status=1 # failure is the default!
+_cleanup()
+{
+ rm -f nbd.sock
+ rm -f nbd-fault-injector.out
+ rm -f nbd-fault-injector.conf
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
# get standard environment, filters and checks
. ./common.rc
. ./common.filter
@@ -35,81 +43,105 @@ _supported_fmt generic
_supported_proto nbd
_supported_os Linux
-# Pick a TCP port based on our pid. This way multiple instances of this test
-# can run in parallel without conflicting.
-choose_tcp_port() {
- echo $((($$ % 31744) + 1024)) # 1024 <= port < 32768
-}
-
-wait_for_tcp_port() {
- while ! (netstat --tcp --listening --numeric | \
- grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") >/dev/null 2>&1; do
- sleep 0.1
+check_disconnect() {
+ local event export_name=foo extra_args nbd_addr nbd_url proto when
+
+ while true; do
+ case $1 in
+ --classic-negotiation)
+ shift
+ extra_args=--classic-negotiation
+ export_name=
+ ;;
+ --tcp)
+ shift
+ proto=tcp
+ ;;
+ --unix)
+ shift
+ proto=unix
+ ;;
+ *)
+ break
+ ;;
+ esac
done
-}
-check_disconnect() {
event=$1
when=$2
- negotiation=$3
echo "=== Check disconnect $when $event ==="
echo
- port=$(choose_tcp_port)
-
cat > "$TEST_DIR/nbd-fault-injector.conf" <<EOF
[inject-error]
event=$event
when=$when
EOF
- if [ "$negotiation" = "--classic-negotiation" ]; then
- extra_args=--classic-negotiation
- nbd_url="nbd:127.0.0.1:$port"
+ if [ "$proto" = "tcp" ]; then
+ nbd_addr="127.0.0.1:0"
else
- nbd_url="nbd:127.0.0.1:$port:exportname=foo"
+ nbd_addr="$TEST_DIR/nbd.sock"
+ fi
+
+ rm -f "$TEST_DIR/nbd.sock"
+
+ $PYTHON nbd-fault-injector.py $extra_args "$nbd_addr" "$TEST_DIR/nbd-fault-injector.conf" >"$TEST_DIR/nbd-fault-injector.out" 2>&1 &
+
+ # Wait for server to be ready
+ while ! grep -q 'Listening on ' "$TEST_DIR/nbd-fault-injector.out"; do
+ sleep 0.1
+ done
+
+ # Extract the final address (port number has now been assigned in tcp case)
+ nbd_addr=$(sed 's/Listening on \(.*\)$/\1/' "$TEST_DIR/nbd-fault-injector.out")
+
+ if [ "$proto" = "tcp" ]; then
+ nbd_url="nbd+tcp://$nbd_addr/$export_name"
+ else
+ nbd_url="nbd+unix:///$export_name?socket=$nbd_addr"
fi
- $PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" >/dev/null 2>&1 &
- wait_for_tcp_port "127\\.0\\.0\\.1:$port"
$QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
echo
}
-for event in neg1 "export" neg2 request reply data; do
- for when in before after; do
- check_disconnect "$event" "$when"
- done
-
- # Also inject short replies from the NBD server
- case "$event" in
- neg1)
- for when in 8 16; do
- check_disconnect "$event" "$when"
- done
- ;;
- "export")
- for when in 4 12 16; do
- check_disconnect "$event" "$when"
+for proto in tcp unix; do
+ for event in neg1 "export" neg2 request reply data; do
+ for when in before after; do
+ check_disconnect "--$proto" "$event" "$when"
done
- ;;
- neg2)
- for when in 8 10; do
- check_disconnect "$event" "$when"
- done
- ;;
- reply)
- for when in 4 8; do
- check_disconnect "$event" "$when"
- done
- ;;
- esac
-done
-# Also check classic negotiation without export information
-for when in before 8 16 24 28 after; do
- check_disconnect "neg-classic" "$when" --classic-negotiation
+ # Also inject short replies from the NBD server
+ case "$event" in
+ neg1)
+ for when in 8 16; do
+ check_disconnect "--$proto" "$event" "$when"
+ done
+ ;;
+ "export")
+ for when in 4 12 16; do
+ check_disconnect "--$proto" "$event" "$when"
+ done
+ ;;
+ neg2)
+ for when in 8 10; do
+ check_disconnect "--$proto" "$event" "$when"
+ done
+ ;;
+ reply)
+ for when in 4 8; do
+ check_disconnect "--$proto" "$event" "$when"
+ done
+ ;;
+ esac
+ done
+
+ # Also check classic negotiation without export information
+ for when in before 8 16 24 28 after; do
+ check_disconnect "--$proto" --classic-negotiation "neg-classic" "$when"
+ done
done
# success, all done
diff --git a/tests/qemu-iotests/083.out b/tests/qemu-iotests/083.out
index a24c6bfece..fb71b6f8ad 100644
--- a/tests/qemu-iotests/083.out
+++ b/tests/qemu-iotests/083.out
@@ -1,43 +1,43 @@
QA output created by 083
=== Check disconnect before neg1 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect after neg1 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 8 neg1 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 16 neg1 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect before export ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect after export ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 4 export ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 12 export ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 16 export ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect before neg2 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect after neg2 ===
@@ -45,11 +45,11 @@ read failed: Input/output error
=== Check disconnect 8 neg2 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect 10 neg2 ===
-can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd+tcp://127.0.0.1:PORT/foo
=== Check disconnect before request ===
@@ -69,12 +69,12 @@ read failed: Input/output error
=== Check disconnect 4 reply ===
-read failed
+End of file
read failed: Input/output error
=== Check disconnect 8 reply ===
-read failed
+End of file
read failed: Input/output error
=== Check disconnect before data ===
@@ -88,23 +88,134 @@ read 512/512 bytes at offset 0
=== Check disconnect before neg-classic ===
-can't open device nbd:127.0.0.1:PORT
+can't open device nbd+tcp://127.0.0.1:PORT/
=== Check disconnect 8 neg-classic ===
-can't open device nbd:127.0.0.1:PORT
+can't open device nbd+tcp://127.0.0.1:PORT/
=== Check disconnect 16 neg-classic ===
-can't open device nbd:127.0.0.1:PORT
+can't open device nbd+tcp://127.0.0.1:PORT/
=== Check disconnect 24 neg-classic ===
-can't open device nbd:127.0.0.1:PORT
+can't open device nbd+tcp://127.0.0.1:PORT/
=== Check disconnect 28 neg-classic ===
-can't open device nbd:127.0.0.1:PORT
+can't open device nbd+tcp://127.0.0.1:PORT/
+
+=== Check disconnect after neg-classic ===
+
+read failed: Input/output error
+
+=== Check disconnect before neg1 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect after neg1 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 8 neg1 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 16 neg1 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect before export ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect after export ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 4 export ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 12 export ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 16 export ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect before neg2 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect after neg2 ===
+
+read failed: Input/output error
+
+=== Check disconnect 8 neg2 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 10 neg2 ===
+
+can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect before request ===
+
+read failed: Input/output error
+
+=== Check disconnect after request ===
+
+read failed: Input/output error
+
+=== Check disconnect before reply ===
+
+read failed: Input/output error
+
+=== Check disconnect after reply ===
+
+read failed: Input/output error
+
+=== Check disconnect 4 reply ===
+
+End of file
+read failed: Input/output error
+
+=== Check disconnect 8 reply ===
+
+End of file
+read failed: Input/output error
+
+=== Check disconnect before data ===
+
+read failed: Input/output error
+
+=== Check disconnect after data ===
+
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Check disconnect before neg-classic ===
+
+can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 8 neg-classic ===
+
+can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 16 neg-classic ===
+
+can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 24 neg-classic ===
+
+can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
+
+=== Check disconnect 28 neg-classic ===
+
+can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
=== Check disconnect after neg-classic ===
diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194
index 8028111e21..a3e3bad664 100755
--- a/tests/qemu-iotests/194
+++ b/tests/qemu-iotests/194
@@ -46,16 +46,17 @@ iotests.log('Launching NBD server on destination...')
iotests.log(dest_vm.qmp('nbd-server-start', addr={'type': 'unix', 'data': {'path': nbd_sock_path}}))
iotests.log(dest_vm.qmp('nbd-server-add', device='drive0', writable=True))
-iotests.log('Starting drive-mirror on source...')
+iotests.log('Starting `drive-mirror` on source...')
iotests.log(source_vm.qmp(
'drive-mirror',
device='drive0',
target='nbd+unix:///drive0?socket={0}'.format(nbd_sock_path),
sync='full',
format='raw', # always raw, the server handles the format
- mode='existing'))
+ mode='existing',
+ job_id='mirror-job0'))
-iotests.log('Waiting for drive-mirror to complete...')
+iotests.log('Waiting for `drive-mirror` to complete...')
iotests.log(source_vm.event_wait('BLOCK_JOB_READY'),
filters=[iotests.filter_qmp_event])
@@ -67,7 +68,17 @@ dest_vm.qmp('migrate-set-capabilities',
iotests.log(source_vm.qmp('migrate', uri='unix:{0}'.format(migration_sock_path)))
while True:
- event = source_vm.event_wait('MIGRATION')
- iotests.log(event, filters=[iotests.filter_qmp_event])
- if event['data']['status'] in ('completed', 'failed'):
+ event1 = source_vm.event_wait('MIGRATION')
+ iotests.log(event1, filters=[iotests.filter_qmp_event])
+ if event1['data']['status'] in ('completed', 'failed'):
+ iotests.log('Gracefully ending the `drive-mirror` job on source...')
+ iotests.log(source_vm.qmp('block-job-cancel', device='mirror-job0'))
+ break
+
+while True:
+ event2 = source_vm.event_wait('BLOCK_JOB_COMPLETED')
+ iotests.log(event2, filters=[iotests.filter_qmp_event])
+ if event2['event'] == 'BLOCK_JOB_COMPLETED':
+ iotests.log('Stopping the NBD server on destination...')
+ iotests.log(dest_vm.qmp('nbd-server-stop'))
break
diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out
index ae501fecac..50ac50da5e 100644
--- a/tests/qemu-iotests/194.out
+++ b/tests/qemu-iotests/194.out
@@ -2,12 +2,17 @@ Launching VMs...
Launching NBD server on destination...
{u'return': {}}
{u'return': {}}
-Starting drive-mirror on source...
+Starting `drive-mirror` on source...
{u'return': {}}
-Waiting for drive-mirror to complete...
-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'drive0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'}
+Waiting for `drive-mirror` to complete...
+{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'}
Starting migration...
{u'return': {}}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'}
{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'}
+Gracefully ending the `drive-mirror` job on source...
+{u'return': {}}
+{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_COMPLETED'}
+Stopping the NBD server on destination...
+{u'return': {}}
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 7a58e57317..9d5442ecd9 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -170,9 +170,9 @@ _filter_nbd()
#
# Filter out the TCP port number since this changes between runs.
sed -e '/nbd\/.*\.c:/d' \
- -e 's#nbd:\(//\)\?127\.0\.0\.1:[0-9]*#nbd:\1127.0.0.1:PORT#g' \
+ -e 's#127\.0\.0\.1:[0-9]*#127.0.0.1:PORT#g' \
-e "s#?socket=$TEST_DIR#?socket=TEST_DIR#g" \
- -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#'
+ -e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
}
# make sure this script returns success
diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py
index 6c07191a5a..1c10dcb51c 100755
--- a/tests/qemu-iotests/nbd-fault-injector.py
+++ b/tests/qemu-iotests/nbd-fault-injector.py
@@ -235,11 +235,15 @@ def open_socket(path):
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, int(port)))
+
+ # If given port was 0 the final port number is now available
+ path = '%s:%d' % sock.getsockname()
else:
sock = socket.socket(socket.AF_UNIX)
sock.bind(path)
sock.listen(0)
print 'Listening on %s' % path
+ sys.stdout.flush() # another process may be waiting, show message now
return sock
def usage(args):
diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c
index 9f84402493..d569d27657 100644
--- a/tests/test-filter-mirror.c
+++ b/tests/test-filter-mirror.c
@@ -17,9 +17,6 @@
static void test_mirror(void)
{
-#ifndef _WIN32
-/* socketpair(PF_UNIX) which does not exist on windows */
-
int send_sock[2], recv_sock;
char *cmdline;
uint32_t ret = 0, len = 0;
@@ -28,6 +25,11 @@ static void test_mirror(void)
char *recv_buf;
uint32_t size = sizeof(send_buf);
size = htonl(size);
+ const char *devstr = "e1000";
+
+ if (g_str_equal(qtest_get_arch(), "s390x")) {
+ devstr = "virtio-net-ccw";
+ }
ret = socketpair(PF_UNIX, SOCK_STREAM, 0, send_sock);
g_assert_cmpint(ret, !=, -1);
@@ -36,10 +38,10 @@ static void test_mirror(void)
g_assert_cmpint(ret, !=, -1);
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
- "-device e1000,netdev=qtest-bn0,id=qtest-e0 "
+ "-device %s,netdev=qtest-bn0,id=qtest-e0 "
"-chardev socket,id=mirror0,path=%s,server,nowait "
"-object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0 "
- , send_sock[1], sock_path);
+ , send_sock[1], devstr, sock_path);
qtest_start(cmdline);
g_free(cmdline);
@@ -74,8 +76,6 @@ static void test_mirror(void)
g_free(recv_buf);
close(recv_sock);
unlink(sock_path);
-
-#endif
}
int main(int argc, char **argv)
diff --git a/tests/test-filter-redirector.c b/tests/test-filter-redirector.c
index 0c4b8d52ef..3afd41110d 100644
--- a/tests/test-filter-redirector.c
+++ b/tests/test-filter-redirector.c
@@ -57,11 +57,18 @@
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
-static void test_redirector_tx(void)
+static const char *get_devstr(void)
{
-#ifndef _WIN32
-/* socketpair(PF_UNIX) which does not exist on windows */
+ if (g_str_equal(qtest_get_arch(), "s390x")) {
+ return "virtio-net-ccw";
+ }
+
+ return "rtl8139";
+}
+
+static void test_redirector_tx(void)
+{
int backend_sock[2], recv_sock;
char *cmdline;
uint32_t ret = 0, len = 0;
@@ -81,7 +88,7 @@ static void test_redirector_tx(void)
g_assert_cmpint(ret, !=, -1);
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
- "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
+ "-device %s,netdev=qtest-bn0,id=qtest-e0 "
"-chardev socket,id=redirector0,path=%s,server,nowait "
"-chardev socket,id=redirector1,path=%s,server,nowait "
"-chardev socket,id=redirector2,path=%s,nowait "
@@ -90,8 +97,8 @@ static void test_redirector_tx(void)
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
"queue=tx,indev=redirector2 "
"-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
- "queue=tx,outdev=redirector1 "
- , backend_sock[1], sock_path0, sock_path1, sock_path0);
+ "queue=tx,outdev=redirector1 ", backend_sock[1], get_devstr(),
+ sock_path0, sock_path1, sock_path0);
qtest_start(cmdline);
g_free(cmdline);
@@ -129,15 +136,10 @@ static void test_redirector_tx(void)
unlink(sock_path0);
unlink(sock_path1);
qtest_end();
-
-#endif
}
static void test_redirector_rx(void)
{
-#ifndef _WIN32
-/* socketpair(PF_UNIX) which does not exist on windows */
-
int backend_sock[2], send_sock;
char *cmdline;
uint32_t ret = 0, len = 0;
@@ -157,7 +159,7 @@ static void test_redirector_rx(void)
g_assert_cmpint(ret, !=, -1);
cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
- "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
+ "-device %s,netdev=qtest-bn0,id=qtest-e0 "
"-chardev socket,id=redirector0,path=%s,server,nowait "
"-chardev socket,id=redirector1,path=%s,server,nowait "
"-chardev socket,id=redirector2,path=%s,nowait "
@@ -166,8 +168,8 @@ static void test_redirector_rx(void)
"-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
"queue=rx,outdev=redirector2 "
"-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
- "queue=rx,indev=redirector1 "
- , backend_sock[1], sock_path0, sock_path1, sock_path0);
+ "queue=rx,indev=redirector1 ", backend_sock[1], get_devstr(),
+ sock_path0, sock_path1, sock_path0);
qtest_start(cmdline);
g_free(cmdline);
@@ -203,8 +205,6 @@ static void test_redirector_rx(void)
unlink(sock_path0);
unlink(sock_path1);
qtest_end();
-
-#endif
}
int main(int argc, char **argv)
diff --git a/tests/test-netfilter.c b/tests/test-netfilter.c
index 8b5a9b21b5..2506473365 100644
--- a/tests/test-netfilter.c
+++ b/tests/test-netfilter.c
@@ -182,6 +182,12 @@ static void remove_netdev_with_multi_netfilter(void)
int main(int argc, char **argv)
{
int ret;
+ char *args;
+ const char *devstr = "e1000";
+
+ if (g_str_equal(qtest_get_arch(), "s390x")) {
+ devstr = "virtio-net-ccw";
+ }
g_test_init(&argc, &argv, NULL);
qtest_add_func("/netfilter/addremove_one", add_one_netfilter);
@@ -191,10 +197,13 @@ int main(int argc, char **argv)
qtest_add_func("/netfilter/remove_netdev_multi",
remove_netdev_with_multi_netfilter);
- qtest_start("-netdev user,id=qtest-bn0 -device e1000,netdev=qtest-bn0");
+ args = g_strdup_printf("-netdev user,id=qtest-bn0 "
+ "-device %s,netdev=qtest-bn0", devstr);
+ qtest_start(args);
ret = g_test_run();
qtest_end();
+ g_free(args);
return ret;
}