diff options
-rw-r--r-- | docs/qmp-events.txt | 14 | ||||
-rw-r--r-- | hw/char/virtio-serial-bus.c | 2 | ||||
-rw-r--r-- | hw/s390x/Makefile.objs | 2 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.c | 6 | ||||
-rw-r--r-- | hw/s390x/s390-pci-bus.h | 1 | ||||
-rw-r--r-- | hw/s390x/s390-pci-inst.c | 20 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.c | 758 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.h | 186 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 27 | ||||
-rw-r--r-- | hw/s390x/s390-virtio.c | 168 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 3 | ||||
-rw-r--r-- | include/migration/migration.h | 3 | ||||
-rw-r--r-- | migration/migration.c | 52 | ||||
-rw-r--r-- | migration/ram.c | 21 | ||||
-rw-r--r-- | migration/savevm.c | 22 | ||||
-rw-r--r-- | qapi/event.json | 13 | ||||
-rw-r--r-- | target-s390x/cpu.h | 3 | ||||
-rw-r--r-- | target-s390x/helper.c | 2 | ||||
-rw-r--r-- | vl.c | 7 |
19 files changed, 135 insertions, 1175 deletions
diff --git a/docs/qmp-events.txt b/docs/qmp-events.txt index d2f1ce497e..52eb7e2f5e 100644 --- a/docs/qmp-events.txt +++ b/docs/qmp-events.txt @@ -496,6 +496,20 @@ Example: {"timestamp": {"seconds": 1432121972, "microseconds": 744001}, "event": "MIGRATION", "data": {"status": "completed"}} +MIGRATION_PASS +-------------- + +Emitted from the source side of a migration at the start of each pass +(when it syncs the dirty bitmap) + +Data: None. + + - "pass": An incrementing count (starting at 1 on the first pass) + +Example: +{"timestamp": {"seconds": 1449669631, "microseconds": 239225}, + "event": "MIGRATION_PASS", "data": {"pass": 2}} + STOP ---- diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 497b0afd9f..2d2a6594fc 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -798,7 +798,7 @@ static const TypeInfo virtser_bus_info = { static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent) { - VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev); + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(qdev); monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n", indent, "", port->id, diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs index 527d75400a..220361782d 100644 --- a/hw/s390x/Makefile.objs +++ b/hw/s390x/Makefile.objs @@ -1,4 +1,4 @@ -obj-y = s390-virtio-bus.o s390-virtio.o +obj-y += s390-virtio.o obj-y += s390-virtio-hcall.o obj-y += sclp.o obj-y += event-facility.o diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 8de35ffa05..132588b758 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -317,7 +317,7 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; - if (!pbdev->configured || !pbdev->pdev) { + if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) { return ret; } @@ -428,6 +428,10 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, return; } + if (!(pbdev->fh & FH_ENABLED)) { + return; + } + ind_bit = pbdev->routes.adapter.ind_offset; sum_bit = pbdev->routes.adapter.summary_offset; diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h index 80345dacb1..d8ddb77281 100644 --- a/hw/s390x/s390-pci-bus.h +++ b/hw/s390x/s390-pci-bus.h @@ -23,6 +23,7 @@ #define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost" #define FH_VIRT 0x00ff0000 #define ENABLE_BIT_OFFSET 31 +#define FH_ENABLED (1 << ENABLE_BIT_OFFSET) #define S390_PCIPT_ADAPTER 2 #define S390_PCI_HOST_BRIDGE(obj) \ diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 8c1dc82b1f..1a6a3e781d 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -105,7 +105,8 @@ static int list_pci(ClpReqRspListPci *rrb, uint8_t *cc) pci_get_word(pbdev->pdev->config + PCI_DEVICE_ID)); stw_p(&rrb->response.fh_list[idx - resume_token].vendor_id, pci_get_word(pbdev->pdev->config + PCI_VENDOR_ID)); - stl_p(&rrb->response.fh_list[idx - resume_token].config, 0x80000000); + stl_p(&rrb->response.fh_list[idx - resume_token].config, + pbdev->configured << 31); stl_p(&rrb->response.fh_list[idx - resume_token].fid, pbdev->fid); stl_p(&rrb->response.fh_list[idx - resume_token].fh, pbdev->fh); @@ -208,12 +209,12 @@ int clp_service_call(S390CPU *cpu, uint8_t r2) switch (reqsetpci->oc) { case CLP_SET_ENABLE_PCI_FN: - pbdev->fh = pbdev->fh | 1 << ENABLE_BIT_OFFSET; + pbdev->fh = pbdev->fh | FH_ENABLED; stl_p(&ressetpci->fh, pbdev->fh); stw_p(&ressetpci->hdr.rsp, CLP_RC_OK); break; case CLP_SET_DISABLE_PCI_FN: - pbdev->fh = pbdev->fh & ~(1 << ENABLE_BIT_OFFSET); + pbdev->fh = pbdev->fh & ~FH_ENABLED; pbdev->error_state = false; pbdev->lgstg_blocked = false; stl_p(&ressetpci->fh, pbdev->fh); @@ -313,7 +314,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcilg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -430,7 +431,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) offset = env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcistg no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -521,8 +522,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2) end = start + env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(fh); - - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("rpcit no pci dev\n"); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); goto out; @@ -586,7 +586,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr, } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("pcistb no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -727,7 +727,7 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) } pbdev = s390_pci_find_dev_by_fh(fh); - if (!pbdev) { + if (!pbdev || !(pbdev->fh & FH_ENABLED)) { DPRINTF("mpcifc no pci dev fh 0x%x\n", fh); setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE); return 0; @@ -819,7 +819,7 @@ int stpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar) ((uint32_t)pbdev->sum << 7) | pbdev->routes.adapter.summary_offset; stl_p(&fib.data, data); - if (pbdev->fh >> ENABLE_BIT_OFFSET) { + if (pbdev->fh & FH_ENABLED) { fib.fc |= 0x80; } diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c deleted file mode 100644 index 98cb1293c2..0000000000 --- a/hw/s390x/s390-virtio-bus.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * QEMU S390 virtio target - * - * Copyright (c) 2009 Alexander Graf <agraf@suse.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "hw/hw.h" -#include "sysemu/block-backend.h" -#include "sysemu/sysemu.h" -#include "hw/boards.h" -#include "hw/loader.h" -#include "elf.h" -#include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-rng.h" -#include "hw/virtio/virtio-serial.h" -#include "hw/virtio/virtio-net.h" -#include "hw/virtio/vhost-scsi.h" -#include "hw/sysbus.h" -#include "sysemu/kvm.h" - -#include "hw/s390x/s390-virtio-bus.h" -#include "hw/virtio/virtio-bus.h" - -/* #define DEBUG_S390 */ - -#ifdef DEBUG_S390 -#define DPRINTF(fmt, ...) \ - do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) \ - do { } while (0) -#endif - -#define VIRTIO_S390_QUEUE_MAX 64 - -static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, - VirtIOS390Device *dev); - -static const TypeInfo s390_virtio_bus_info = { - .name = TYPE_S390_VIRTIO_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(VirtIOS390Bus), -}; - -static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev); - -/* length of VirtIO device pages */ -const hwaddr virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE; - -static void s390_virtio_bus_reset(void *opaque) -{ - VirtIOS390Bus *bus = opaque; - bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; -} - -void s390_virtio_reset_idx(VirtIOS390Device *dev) -{ - int i; - hwaddr idx_addr; - uint8_t num_vq; - - num_vq = s390_virtio_device_num_vq(dev); - for (i = 0; i < num_vq; i++) { - idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + - VIRTIO_VRING_AVAIL_IDX_OFFS; - address_space_stw(&address_space_memory, idx_addr, 0, - MEMTXATTRS_UNSPECIFIED, NULL); - idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + - virtio_queue_get_avail_size(dev->vdev, i); - address_space_stw(&address_space_memory, idx_addr, 0, - MEMTXATTRS_UNSPECIFIED, NULL); - idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + - VIRTIO_VRING_USED_IDX_OFFS; - address_space_stw(&address_space_memory, idx_addr, 0, - MEMTXATTRS_UNSPECIFIED, NULL); - idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + - virtio_queue_get_used_size(dev->vdev, i); - address_space_stw(&address_space_memory, idx_addr, 0, - MEMTXATTRS_UNSPECIFIED, NULL); - } -} - -VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size) -{ - VirtIOS390Bus *bus; - BusState *_bus; - DeviceState *dev; - - /* Create bridge device */ - dev = qdev_create(NULL, "s390-virtio-bridge"); - qdev_init_nofail(dev); - - /* Create bus on bridge device */ - - _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio"); - bus = DO_UPCAST(VirtIOS390Bus, bus, _bus); - - bus->dev_page = *ram_size; - bus->dev_offs = bus->dev_page; - bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE; - - /* Enable hotplugging */ - qbus_set_hotplug_handler(_bus, dev, &error_abort); - - /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */ - *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE; - - qemu_register_reset(s390_virtio_bus_reset, bus); - return bus; -} - -static void s390_virtio_device_init(VirtIOS390Device *dev, - VirtIODevice *vdev) -{ - VirtIOS390Bus *bus; - int dev_len; - - bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); - dev->vdev = vdev; - dev->dev_offs = bus->dev_offs; - dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */ - - dev_len = VIRTIO_DEV_OFFS_CONFIG; - dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN; - dev_len += dev->feat_len * 2; - dev_len += virtio_bus_get_vdev_config_len(&dev->bus); - - bus->dev_offs += dev_len; - - s390_virtio_device_sync(dev); - s390_virtio_reset_idx(dev); - if (dev->qdev.hotplugged) { - s390_virtio_irq(VIRTIO_PARAM_DEV_ADD, dev->dev_offs); - } -} - -static void s390_virtio_net_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - DeviceState *qdev = DEVICE(s390_dev); - VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - - virtio_net_set_netclient_name(&dev->vdev, qdev->id, - object_get_typename(OBJECT(qdev))); - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); -} - -static void s390_virtio_net_instance_init(Object *obj) -{ - VirtIONetS390 *dev = VIRTIO_NET_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_NET); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static void s390_virtio_blk_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - VirtIOBlkS390 *dev = VIRTIO_BLK_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); -} - -static void s390_virtio_blk_instance_init(Object *obj) -{ - VirtIOBlkS390 *dev = VIRTIO_BLK_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_BLK); - object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread", - &error_abort); - object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev), - "bootindex", &error_abort); -} - -static void s390_virtio_serial_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - DeviceState *qdev = DEVICE(s390_dev); - Error *err = NULL; - VirtIOS390Bus *bus; - char *bus_name; - - bus = DO_UPCAST(VirtIOS390Bus, bus, qdev->parent_bus); - - /* - * For command line compatibility, this sets the virtio-serial-device bus - * name as before. - */ - if (qdev->id) { - bus_name = g_strdup_printf("%s.0", qdev->id); - virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); - g_free(bus_name); - } - - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); - bus->console = s390_dev; -} - -static void s390_virtio_serial_instance_init(Object *obj) -{ - VirtIOSerialS390 *dev = VIRTIO_SERIAL_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_SERIAL); -} - -static void s390_virtio_scsi_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - DeviceState *qdev = DEVICE(s390_dev); - Error *err = NULL; - char *bus_name; - - /* - * For command line compatibility, this sets the virtio-scsi-device bus - * name as before. - */ - if (qdev->id) { - bus_name = g_strdup_printf("%s.0", qdev->id); - virtio_device_set_child_bus_name(VIRTIO_DEVICE(vdev), bus_name); - g_free(bus_name); - } - - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); -} - -static void s390_virtio_scsi_instance_init(Object *obj) -{ - VirtIOSCSIS390 *dev = VIRTIO_SCSI_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_SCSI); -} - -#ifdef CONFIG_VHOST_SCSI -static void s390_vhost_scsi_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - VHostSCSIS390 *dev = VHOST_SCSI_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); -} - -static void s390_vhost_scsi_instance_init(Object *obj) -{ - VHostSCSIS390 *dev = VHOST_SCSI_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VHOST_SCSI); -} -#endif - - -static void s390_virtio_rng_realize(VirtIOS390Device *s390_dev, Error **errp) -{ - VirtIORNGS390 *dev = VIRTIO_RNG_S390(s390_dev); - DeviceState *vdev = DEVICE(&dev->vdev); - Error *err = NULL; - - qdev_set_parent_bus(vdev, BUS(&s390_dev->bus)); - object_property_set_bool(OBJECT(vdev), true, "realized", &err); - if (err) { - error_propagate(errp, err); - return; - } - - object_property_set_link(OBJECT(dev), - OBJECT(dev->vdev.conf.rng), "rng", - NULL); - - s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev)); -} - -static void s390_virtio_rng_instance_init(Object *obj) -{ - VirtIORNGS390 *dev = VIRTIO_RNG_S390(obj); - - virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), - TYPE_VIRTIO_RNG); - object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), - "rng", &error_abort); -} - -static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) -{ - ram_addr_t token_off; - - token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + - (vq * VIRTIO_VQCONFIG_LEN) + - VIRTIO_VQCONFIG_OFFS_TOKEN; - - return address_space_ldq_be(&address_space_memory, token_off, - MEMTXATTRS_UNSPECIFIED, NULL); -} - -static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev) -{ - VirtIODevice *vdev = dev->vdev; - int num_vq; - - for (num_vq = 0; num_vq < VIRTIO_S390_QUEUE_MAX; num_vq++) { - if (!virtio_queue_get_num(vdev, num_vq)) { - break; - } - } - - return num_vq; -} - -static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus) -{ - ram_addr_t r = bus->next_ring; - - bus->next_ring += VIRTIO_RING_LEN; - return r; -} - -void s390_virtio_device_sync(VirtIOS390Device *dev) -{ - VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus); - ram_addr_t cur_offs; - uint8_t num_vq; - int i; - - virtio_reset(dev->vdev); - - /* Sync dev space */ - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, - dev->vdev->device_id, - MEMTXATTRS_UNSPECIFIED, - NULL); - - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, - s390_virtio_device_num_vq(dev), - MEMTXATTRS_UNSPECIFIED, - NULL); - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, - dev->feat_len, - MEMTXATTRS_UNSPECIFIED, - NULL); - - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, - dev->vdev->config_len, - MEMTXATTRS_UNSPECIFIED, - NULL); - - num_vq = s390_virtio_device_num_vq(dev); - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq, - MEMTXATTRS_UNSPECIFIED, NULL); - - /* Sync virtqueues */ - for (i = 0; i < num_vq; i++) { - ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) + - (i * VIRTIO_VQCONFIG_LEN); - ram_addr_t vring; - - vring = s390_virtio_next_ring(bus); - virtio_queue_set_addr(dev->vdev, i, vring); - virtio_queue_set_vector(dev->vdev, i, i); - address_space_stq_be(&address_space_memory, - vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring, - MEMTXATTRS_UNSPECIFIED, NULL); - address_space_stw_be(&address_space_memory, - vq + VIRTIO_VQCONFIG_OFFS_NUM, - virtio_queue_get_num(dev->vdev, i), - MEMTXATTRS_UNSPECIFIED, - NULL); - } - - cur_offs = dev->dev_offs; - cur_offs += VIRTIO_DEV_OFFS_CONFIG; - cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; - - /* Sync feature bitmap */ - address_space_stl_le(&address_space_memory, cur_offs, - dev->vdev->host_features, - MEMTXATTRS_UNSPECIFIED, NULL); - - dev->feat_offs = cur_offs + dev->feat_len; - cur_offs += dev->feat_len * 2; - - /* Sync config space */ - virtio_bus_get_vdev_config(&dev->bus, dev->vdev->config); - - cpu_physical_memory_write(cur_offs, - dev->vdev->config, dev->vdev->config_len); - cur_offs += dev->vdev->config_len; -} - -void s390_virtio_device_update_status(VirtIOS390Device *dev) -{ - VirtIODevice *vdev = dev->vdev; - uint32_t features; - - virtio_set_status(vdev, - address_space_ldub(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, - MEMTXATTRS_UNSPECIFIED, NULL)); - - /* Update guest supported feature bitmap */ - - features = bswap32(address_space_ldl_be(&address_space_memory, - dev->feat_offs, - MEMTXATTRS_UNSPECIFIED, NULL)); - virtio_set_features(vdev, features); -} - -/* Find a device by vring address */ -VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, - ram_addr_t mem, - int *vq_num) -{ - BusChild *kid; - int i; - - QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { - VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; - - for (i = 0; i < VIRTIO_S390_QUEUE_MAX; i++) { - if (!virtio_queue_get_addr(dev->vdev, i)) - break; - if (virtio_queue_get_addr(dev->vdev, i) == mem) { - if (vq_num) { - *vq_num = i; - } - return dev; - } - } - } - - return NULL; -} - -/* Find a device by device descriptor location */ -VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem) -{ - BusChild *kid; - - QTAILQ_FOREACH(kid, &bus->bus.children, sibling) { - VirtIOS390Device *dev = (VirtIOS390Device *)kid->child; - if (dev->dev_offs == mem) { - return dev; - } - } - - return NULL; -} - -/* DeviceState to VirtIOS390Device. Note: used on datapath, - * be careful and test performance if you change this. - */ -static inline VirtIOS390Device *to_virtio_s390_device_fast(DeviceState *d) -{ - return container_of(d, VirtIOS390Device, qdev); -} - -/* DeviceState to VirtIOS390Device. TODO: use QOM. */ -static inline VirtIOS390Device *to_virtio_s390_device(DeviceState *d) -{ - return container_of(d, VirtIOS390Device, qdev); -} - -static void virtio_s390_notify(DeviceState *d, uint16_t vector) -{ - VirtIOS390Device *dev = to_virtio_s390_device_fast(d); - uint64_t token = s390_virtio_device_vq_token(dev, vector); - - s390_virtio_irq(0, token); -} - -static void virtio_s390_device_plugged(DeviceState *d, Error **errp) -{ - VirtIOS390Device *dev = to_virtio_s390_device(d); - VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); - int n = virtio_get_num_queues(vdev); - - if (n > VIRTIO_S390_QUEUE_MAX) { - error_setg(errp, "The nubmer of virtqueues %d " - "exceeds s390 limit %d", n, - VIRTIO_S390_QUEUE_MAX); - } -} - -/**************** S390 Virtio Bus Device Descriptions *******************/ - -static void s390_virtio_net_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->realize = s390_virtio_net_realize; - set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); -} - -static const TypeInfo s390_virtio_net = { - .name = TYPE_VIRTIO_NET_S390, - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIONetS390), - .instance_init = s390_virtio_net_instance_init, - .class_init = s390_virtio_net_class_init, -}; - -static void s390_virtio_blk_class_init(ObjectClass *klass, void *data) -{ - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->realize = s390_virtio_blk_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); -} - -static const TypeInfo s390_virtio_blk = { - .name = "virtio-blk-s390", - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOBlkS390), - .instance_init = s390_virtio_blk_instance_init, - .class_init = s390_virtio_blk_class_init, -}; - -static void s390_virtio_serial_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->realize = s390_virtio_serial_realize; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); -} - -static const TypeInfo s390_virtio_serial = { - .name = TYPE_VIRTIO_SERIAL_S390, - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOSerialS390), - .instance_init = s390_virtio_serial_instance_init, - .class_init = s390_virtio_serial_class_init, -}; - -static void s390_virtio_rng_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->realize = s390_virtio_rng_realize; - set_bit(DEVICE_CATEGORY_MISC, dc->categories); -} - -static const TypeInfo s390_virtio_rng = { - .name = TYPE_VIRTIO_RNG_S390, - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIORNGS390), - .instance_init = s390_virtio_rng_instance_init, - .class_init = s390_virtio_rng_class_init, -}; - -static void s390_virtio_busdev_realize(DeviceState *dev, Error **errp) -{ - VirtIOS390Device *_dev = (VirtIOS390Device *)dev; - VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev); - - virtio_s390_bus_new(&_dev->bus, sizeof(_dev->bus), _dev); - - _info->realize(_dev, errp); -} - -static void s390_virtio_busdev_reset(DeviceState *dev) -{ - VirtIOS390Device *_dev = (VirtIOS390Device *)dev; - - virtio_reset(_dev->vdev); -} - -static void virtio_s390_device_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = s390_virtio_busdev_realize; - dc->bus_type = TYPE_S390_VIRTIO_BUS; - dc->reset = s390_virtio_busdev_reset; -} - -static const TypeInfo virtio_s390_device_info = { - .name = TYPE_VIRTIO_S390_DEVICE, - .parent = TYPE_DEVICE, - .instance_size = sizeof(VirtIOS390Device), - .class_init = virtio_s390_device_class_init, - .class_size = sizeof(VirtIOS390DeviceClass), - .abstract = true, -}; - -static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->realize = s390_virtio_scsi_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); -} - -static const TypeInfo s390_virtio_scsi = { - .name = TYPE_VIRTIO_SCSI_S390, - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VirtIOSCSIS390), - .instance_init = s390_virtio_scsi_instance_init, - .class_init = s390_virtio_scsi_class_init, -}; - -#ifdef CONFIG_VHOST_SCSI -static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); - - k->realize = s390_vhost_scsi_realize; - set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); -} - -static const TypeInfo s390_vhost_scsi = { - .name = TYPE_VHOST_SCSI_S390, - .parent = TYPE_VIRTIO_S390_DEVICE, - .instance_size = sizeof(VHostSCSIS390), - .instance_init = s390_vhost_scsi_instance_init, - .class_init = s390_vhost_scsi_class_init, -}; -#endif - -/***************** S390 Virtio Bus Bridge Device *******************/ -/* Only required to have the virtio bus as child in the system bus */ - -static int s390_virtio_bridge_init(SysBusDevice *dev) -{ - /* nothing */ - return 0; -} - -static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - k->init = s390_virtio_bridge_init; - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); -} - -static const TypeInfo s390_virtio_bridge_info = { - .name = "s390-virtio-bridge", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SysBusDevice), - .class_init = s390_virtio_bridge_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_HOTPLUG_HANDLER }, - { } - } -}; - -/* virtio-s390-bus */ - -static void virtio_s390_bus_new(VirtioBusState *bus, size_t bus_size, - VirtIOS390Device *dev) -{ - DeviceState *qdev = DEVICE(dev); - char virtio_bus_name[] = "virtio-bus"; - - qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_S390_BUS, - qdev, virtio_bus_name); -} - -static void virtio_s390_bus_class_init(ObjectClass *klass, void *data) -{ - VirtioBusClass *k = VIRTIO_BUS_CLASS(klass); - BusClass *bus_class = BUS_CLASS(klass); - bus_class->max_dev = 1; - k->notify = virtio_s390_notify; - k->device_plugged = virtio_s390_device_plugged; -} - -static const TypeInfo virtio_s390_bus_info = { - .name = TYPE_VIRTIO_S390_BUS, - .parent = TYPE_VIRTIO_BUS, - .instance_size = sizeof(VirtioS390BusState), - .class_init = virtio_s390_bus_class_init, -}; - -static void s390_virtio_register_types(void) -{ - type_register_static(&virtio_s390_bus_info); - type_register_static(&s390_virtio_bus_info); - type_register_static(&virtio_s390_device_info); - type_register_static(&s390_virtio_serial); - type_register_static(&s390_virtio_blk); - type_register_static(&s390_virtio_net); - type_register_static(&s390_virtio_scsi); -#ifdef CONFIG_VHOST_SCSI - type_register_static(&s390_vhost_scsi); -#endif - type_register_static(&s390_virtio_rng); - type_register_static(&s390_virtio_bridge_info); -} - -type_init(s390_virtio_register_types) diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h deleted file mode 100644 index 7ad295e68f..0000000000 --- a/hw/s390x/s390-virtio-bus.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * QEMU S390x VirtIO BUS definitions - * - * Copyright (c) 2009 Alexander Graf <agraf@suse.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ -#ifndef HW_S390_VIRTIO_BUS_H -#define HW_S390_VIRTIO_BUS_H 1 - -#include <stddef.h> - -#include "standard-headers/asm-s390/kvm_virtio.h" -#include "standard-headers/linux/virtio_ring.h" -#include "hw/virtio/virtio-blk.h" -#include "hw/virtio/virtio-net.h" -#include "hw/virtio/virtio-rng.h" -#include "hw/virtio/virtio-serial.h" -#include "hw/virtio/virtio-scsi.h" -#include "hw/virtio/virtio-bus.h" -#ifdef CONFIG_VHOST_SCSI -#include "hw/virtio/vhost-scsi.h" -#endif - -typedef struct kvm_device_desc KvmDeviceDesc; - -#define VIRTIO_DEV_OFFS_TYPE offsetof(KvmDeviceDesc, type) -#define VIRTIO_DEV_OFFS_NUM_VQ offsetof(KvmDeviceDesc, num_vq) -#define VIRTIO_DEV_OFFS_FEATURE_LEN offsetof(KvmDeviceDesc, feature_len) -#define VIRTIO_DEV_OFFS_CONFIG_LEN offsetof(KvmDeviceDesc, config_len) -#define VIRTIO_DEV_OFFS_STATUS offsetof(KvmDeviceDesc, status) -#define VIRTIO_DEV_OFFS_CONFIG offsetof(KvmDeviceDesc, config) - -typedef struct kvm_vqconfig KvmVqConfig; -#define VIRTIO_VQCONFIG_OFFS_TOKEN offsetof(KvmVqConfig,token) /* 64 bit */ -#define VIRTIO_VQCONFIG_OFFS_ADDRESS offsetof(KvmVqConfig, address) /* 64 bit */ -#define VIRTIO_VQCONFIG_OFFS_NUM offsetof(KvmVqConfig, num) /* 16 bit */ -#define VIRTIO_VQCONFIG_LEN sizeof(KvmVqConfig) - -#define VIRTIO_RING_LEN (TARGET_PAGE_SIZE * 3) -#define VIRTIO_VRING_AVAIL_IDX_OFFS offsetof(struct vring_avail, idx) -#define VIRTIO_VRING_USED_IDX_OFFS offsetof(struct vring_used, idx) -#define S390_DEVICE_PAGES 512 - -#define TYPE_VIRTIO_S390_DEVICE "virtio-s390-device" -#define VIRTIO_S390_DEVICE(obj) \ - OBJECT_CHECK(VirtIOS390Device, (obj), TYPE_VIRTIO_S390_DEVICE) -#define VIRTIO_S390_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtIOS390DeviceClass, (klass), TYPE_VIRTIO_S390_DEVICE) -#define VIRTIO_S390_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtIOS390DeviceClass, (obj), TYPE_VIRTIO_S390_DEVICE) - -#define TYPE_S390_VIRTIO_BUS "s390-virtio-bus" -#define S390_VIRTIO_BUS(obj) \ - OBJECT_CHECK(VirtIOS390Bus, (obj), TYPE_S390_VIRTIO_BUS) - -/* virtio-s390-bus */ - -typedef struct VirtioBusState VirtioS390BusState; -typedef struct VirtioBusClass VirtioS390BusClass; - -#define TYPE_VIRTIO_S390_BUS "virtio-s390-bus" -#define VIRTIO_S390_BUS(obj) \ - OBJECT_CHECK(VirtioS390BusState, (obj), TYPE_VIRTIO_S390_BUS) -#define VIRTIO_S390_BUS_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtioS390BusClass, obj, TYPE_VIRTIO_S390_BUS) -#define VIRTIO_S390_BUS_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtioS390BusClass, klass, TYPE_VIRTIO_S390_BUS) - - -typedef struct VirtIOS390Device VirtIOS390Device; - -typedef struct VirtIOS390DeviceClass { - DeviceClass qdev; - void (*realize)(VirtIOS390Device *dev, Error **errp); -} VirtIOS390DeviceClass; - -struct VirtIOS390Device { - DeviceState qdev; - ram_addr_t dev_offs; - ram_addr_t feat_offs; - uint8_t feat_len; - VirtIODevice *vdev; - VirtioBusState bus; -}; - -typedef struct VirtIOS390Bus { - BusState bus; - - VirtIOS390Device *console; - ram_addr_t dev_page; - ram_addr_t dev_offs; - ram_addr_t next_ring; -} VirtIOS390Bus; - - -void s390_virtio_device_update_status(VirtIOS390Device *dev); - -VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size); - -VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus, - ram_addr_t mem, int *vq_num); -VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem); -void s390_virtio_device_sync(VirtIOS390Device *dev); -void s390_virtio_reset_idx(VirtIOS390Device *dev); - -/* virtio-blk-s390 */ - -#define TYPE_VIRTIO_BLK_S390 "virtio-blk-s390" -#define VIRTIO_BLK_S390(obj) \ - OBJECT_CHECK(VirtIOBlkS390, (obj), TYPE_VIRTIO_BLK_S390) - -typedef struct VirtIOBlkS390 { - VirtIOS390Device parent_obj; - VirtIOBlock vdev; -} VirtIOBlkS390; - -/* virtio-scsi-s390 */ - -#define TYPE_VIRTIO_SCSI_S390 "virtio-scsi-s390" -#define VIRTIO_SCSI_S390(obj) \ - OBJECT_CHECK(VirtIOSCSIS390, (obj), TYPE_VIRTIO_SCSI_S390) - -typedef struct VirtIOSCSIS390 { - VirtIOS390Device parent_obj; - VirtIOSCSI vdev; -} VirtIOSCSIS390; - -/* virtio-serial-s390 */ - -#define TYPE_VIRTIO_SERIAL_S390 "virtio-serial-s390" -#define VIRTIO_SERIAL_S390(obj) \ - OBJECT_CHECK(VirtIOSerialS390, (obj), TYPE_VIRTIO_SERIAL_S390) - -typedef struct VirtIOSerialS390 { - VirtIOS390Device parent_obj; - VirtIOSerial vdev; -} VirtIOSerialS390; - -/* virtio-net-s390 */ - -#define TYPE_VIRTIO_NET_S390 "virtio-net-s390" -#define VIRTIO_NET_S390(obj) \ - OBJECT_CHECK(VirtIONetS390, (obj), TYPE_VIRTIO_NET_S390) - -typedef struct VirtIONetS390 { - VirtIOS390Device parent_obj; - VirtIONet vdev; -} VirtIONetS390; - -/* vhost-scsi-s390 */ - -#ifdef CONFIG_VHOST_SCSI -#define TYPE_VHOST_SCSI_S390 "vhost-scsi-s390" -#define VHOST_SCSI_S390(obj) \ - OBJECT_CHECK(VHostSCSIS390, (obj), TYPE_VHOST_SCSI_S390) - -typedef struct VHostSCSIS390 { - VirtIOS390Device parent_obj; - VHostSCSI vdev; -} VHostSCSIS390; -#endif - -/* virtio-rng-s390 */ - -#define TYPE_VIRTIO_RNG_S390 "virtio-rng-s390" -#define VIRTIO_RNG_S390(obj) \ - OBJECT_CHECK(VirtIORNGS390, (obj), TYPE_VIRTIO_RNG_S390) - -typedef struct VirtIORNGS390 { - VirtIOS390Device parent_obj; - VirtIORNG vdev; -} VirtIORNGS390; - -#endif diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 5a52ff26eb..586ddbb39a 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -235,7 +235,11 @@ static const TypeInfo ccw_machine_info = { }, }; +#define CCW_COMPAT_2_5 \ + HW_COMPAT_2_5 + #define CCW_COMPAT_2_4 \ + CCW_COMPAT_2_5 \ HW_COMPAT_2_4 \ {\ .driver = TYPE_S390_SKEYS,\ @@ -296,10 +300,13 @@ static const TypeInfo ccw_machine_2_4_info = { static void ccw_machine_2_5_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + static GlobalProperty compat_props[] = { + CCW_COMPAT_2_5 + { /* end of list */ } + }; - mc->alias = "s390-ccw-virtio"; mc->desc = "VirtIO-ccw based S390 machine v2.5"; - mc->is_default = 1; + mc->compat_props = compat_props; } static const TypeInfo ccw_machine_2_5_info = { @@ -308,11 +315,27 @@ static const TypeInfo ccw_machine_2_5_info = { .class_init = ccw_machine_2_5_class_init, }; +static void ccw_machine_2_6_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->alias = "s390-ccw-virtio"; + mc->desc = "VirtIO-ccw based S390 machine v2.6"; + mc->is_default = 1; +} + +static const TypeInfo ccw_machine_2_6_info = { + .name = MACHINE_TYPE_NAME("s390-ccw-virtio-2.6"), + .parent = TYPE_S390_CCW_MACHINE, + .class_init = ccw_machine_2_6_class_init, +}; + static void ccw_machine_register_types(void) { type_register_static(&ccw_machine_info); type_register_static(&ccw_machine_2_4_info); type_register_static(&ccw_machine_2_5_info); + type_register_static(&ccw_machine_2_6_info); } type_init(ccw_machine_register_types) diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index ae55760d64..946325f9fe 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -35,7 +35,6 @@ #include "exec/address-spaces.h" #include "sysemu/qtest.h" -#include "hw/s390x/s390-virtio-bus.h" #include "hw/s390x/sclp.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/s390-virtio.h" @@ -61,7 +60,6 @@ #define S390_TOD_CLOCK_VALUE_MISSING 0x00 #define S390_TOD_CLOCK_VALUE_PRESENT 0x01 -static VirtIOS390Bus *s390_bus; static S390CPU **ipi_states; S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) @@ -73,78 +71,6 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) return ipi_states[cpu_addr]; } -static int s390_virtio_hcall_notify(const uint64_t *args) -{ - uint64_t mem = args[0]; - int r = 0, i; - - if (mem > ram_size) { - VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, mem, &i); - if (dev) { - /* - * Older kernels will use the virtqueue before setting DRIVER_OK. - * In this case the feature bits are not yet up to date, meaning - * that several funny things can happen, e.g. the guest thinks - * EVENT_IDX is on and QEMU thinks it is off. Let's force a feature - * and status sync. - */ - if (!(dev->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { - s390_virtio_device_update_status(dev); - } - virtio_queue_notify(dev->vdev, i); - } else { - r = -EINVAL; - } - } else { - /* Early printk */ - } - return r; -} - -static int s390_virtio_hcall_reset(const uint64_t *args) -{ - uint64_t mem = args[0]; - VirtIOS390Device *dev; - - dev = s390_virtio_bus_find_mem(s390_bus, mem); - if (dev == NULL) { - return -EINVAL; - } - virtio_reset(dev->vdev); - address_space_stb(&address_space_memory, - dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0, - MEMTXATTRS_UNSPECIFIED, NULL); - s390_virtio_device_sync(dev); - s390_virtio_reset_idx(dev); - - return 0; -} - -static int s390_virtio_hcall_set_status(const uint64_t *args) -{ - uint64_t mem = args[0]; - int r = 0; - VirtIOS390Device *dev; - - dev = s390_virtio_bus_find_mem(s390_bus, mem); - if (dev) { - s390_virtio_device_update_status(dev); - } else { - r = -EINVAL; - } - return r; -} - -static void s390_virtio_register_hcalls(void) -{ - s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY, - s390_virtio_hcall_notify); - s390_register_virtio_hypercall(KVM_S390_VIRTIO_RESET, - s390_virtio_hcall_reset); - s390_register_virtio_hypercall(KVM_S390_VIRTIO_SET_STATUS, - s390_virtio_hcall_set_status); -} - void s390_init_ipl_dev(const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, @@ -205,10 +131,7 @@ void s390_create_virtio_net(BusState *bus, const char *name) nd->model = g_strdup("virtio"); } - if (strcmp(nd->model, "virtio")) { - fprintf(stderr, "S390 only supports VirtIO nics\n"); - exit(1); - } + qemu_check_nic_model(nd, "virtio"); dev = qdev_create(bus, name); qdev_set_nic_properties(dev, nd); @@ -261,58 +184,6 @@ int gtod_load(QEMUFile *f, void *opaque, int version_id) return 0; } -/* PC hardware initialisation */ -static void s390_init(MachineState *machine) -{ - ram_addr_t my_ram_size; - void *virtio_region; - hwaddr virtio_region_len; - hwaddr virtio_region_start; - - if (!qtest_enabled()) { - error_printf("WARNING\n" - "The s390-virtio machine (non-ccw) is deprecated.\n" - "It will be removed in 2.6. Please use s390-ccw-virtio\n"); - } - - if (machine->ram_slots) { - error_report("Memory hotplug not supported by the selected machine."); - exit(EXIT_FAILURE); - } - s390_sclp_init(); - my_ram_size = machine->ram_size; - - /* get a BUS */ - s390_bus = s390_virtio_bus_init(&my_ram_size); - s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, - machine->initrd_filename, ZIPL_FILENAME, false); - s390_flic_init(); - - /* register hypercalls */ - s390_virtio_register_hcalls(); - - /* allocate RAM */ - s390_memory_init(my_ram_size); - - /* clear virtio region */ - virtio_region_len = my_ram_size - ram_size; - virtio_region_start = ram_size; - virtio_region = cpu_physical_memory_map(virtio_region_start, - &virtio_region_len, true); - memset(virtio_region, 0, virtio_region_len); - cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1, - virtio_region_len); - - /* init CPUs */ - s390_init_cpus(machine->cpu_model); - - /* Create VirtIO network adapters */ - s390_create_virtio_net((BusState *)s390_bus, "virtio-net-s390"); - - /* Register savevm handler for guest TOD clock */ - register_savevm(NULL, "todclock", 0, 1, gtod_save, gtod_load, NULL); -} - void s390_nmi(NMIState *n, int cpu_index, Error **errp) { CPUState *cs = qemu_get_cpu(cpu_index); @@ -334,40 +205,3 @@ void s390_machine_reset(void) s390_ipl_prepare_cpu(ipl_cpu); s390_cpu_set_state(CPU_STATE_OPERATING, ipl_cpu); } - -static void s390_machine_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - NMIClass *nc = NMI_CLASS(oc); - - mc->alias = "s390"; - mc->desc = "VirtIO based S390 machine (deprecated)"; - mc->init = s390_init; - mc->reset = s390_machine_reset; - mc->block_default_type = IF_VIRTIO; - mc->max_cpus = 255; - mc->no_serial = 1; - mc->no_parallel = 1; - mc->use_virtcon = 1; - mc->no_floppy = 1; - mc->no_cdrom = 1; - mc->no_sdcard = 1; - nc->nmi_monitor_handler = s390_nmi; -} - -static const TypeInfo s390_machine_info = { - .name = TYPE_S390_MACHINE, - .parent = TYPE_MACHINE, - .class_init = s390_machine_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_NMI }, - { } - }, -}; - -static void s390_machine_register_types(void) -{ - type_register_static(&s390_machine_info); -} - -type_init(s390_machine_register_types) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 63da303864..95a6c142b8 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1177,7 +1177,8 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector) SubchDev *sch = dev->sch; uint64_t indicators; - if (vector >= 128) { + /* queue indicators + secondary indicators */ + if (vector >= VIRTIO_CCW_QUEUE_MAX + 64) { return; } diff --git a/include/migration/migration.h b/include/migration/migration.h index d9494b895e..0fc1ffa9a9 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -105,6 +105,7 @@ struct MigrationIncomingState { QemuMutex rp_mutex; /* We send replies from multiple threads */ void *postcopy_tmp_page; + int state; /* See savevm.c */ LoadStateEntry_Head loadvm_handlers; }; @@ -169,6 +170,8 @@ struct MigrationState RAMBlock *last_req_rb; }; +void migrate_set_state(int *state, int old_state, int new_state); + void process_incoming_migration(QEMUFile *f); void qemu_start_incoming_migration(const char *uri, Error **errp); diff --git a/migration/migration.c b/migration/migration.c index c842499575..bc611e453b 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -111,6 +111,7 @@ MigrationIncomingState *migration_incoming_state_new(QEMUFile* f) { mis_current = g_new0(MigrationIncomingState, 1); mis_current->from_src_file = f; + mis_current->state = MIGRATION_STATUS_NONE; QLIST_INIT(&mis_current->loadvm_handlers); qemu_mutex_init(&mis_current->rp_mutex); qemu_event_init(&mis_current->main_thread_load_event, false); @@ -331,8 +332,8 @@ static void process_incoming_migration_co(void *opaque) mis = migration_incoming_state_new(f); postcopy_state_set(POSTCOPY_INCOMING_NONE); - migrate_generate_event(MIGRATION_STATUS_ACTIVE); - + migrate_set_state(&mis->state, MIGRATION_STATUS_NONE, + MIGRATION_STATUS_ACTIVE); ret = qemu_loadvm_state(f); ps = postcopy_state_get(); @@ -358,10 +359,10 @@ static void process_incoming_migration_co(void *opaque) qemu_fclose(f); free_xbzrle_decoded_buf(); - migration_incoming_state_destroy(); if (ret < 0) { - migrate_generate_event(MIGRATION_STATUS_FAILED); + migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); error_report("load of migration failed: %s", strerror(-ret)); migrate_decompress_threads_join(); exit(EXIT_FAILURE); @@ -370,7 +371,8 @@ static void process_incoming_migration_co(void *opaque) /* Make sure all file formats flush their mutable metadata */ bdrv_invalidate_cache_all(&local_err); if (local_err) { - migrate_generate_event(MIGRATION_STATUS_FAILED); + migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); error_report_err(local_err); migrate_decompress_threads_join(); exit(EXIT_FAILURE); @@ -402,7 +404,9 @@ static void process_incoming_migration_co(void *opaque) * observer sees this event they might start to prod at the VM assuming * it's ready to use. */ - migrate_generate_event(MIGRATION_STATUS_COMPLETED); + migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_COMPLETED); + migration_incoming_state_destroy(); } void process_incoming_migration(QEMUFile *f) @@ -787,9 +791,9 @@ void qmp_migrate_start_postcopy(Error **errp) /* shared migration helpers */ -static void migrate_set_state(MigrationState *s, int old_state, int new_state) +void migrate_set_state(int *state, int old_state, int new_state) { - if (atomic_cmpxchg(&s->state, old_state, new_state) == old_state) { + if (atomic_cmpxchg(state, old_state, new_state) == old_state) { trace_migrate_set_state(new_state); migrate_generate_event(new_state); } @@ -822,7 +826,7 @@ static void migrate_fd_cleanup(void *opaque) (s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE)); if (s->state == MIGRATION_STATUS_CANCELLING) { - migrate_set_state(s, MIGRATION_STATUS_CANCELLING, + migrate_set_state(&s->state, MIGRATION_STATUS_CANCELLING, MIGRATION_STATUS_CANCELLED); } @@ -833,7 +837,8 @@ void migrate_fd_error(MigrationState *s) { trace_migrate_fd_error(); assert(s->file == NULL); - migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); + migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, + MIGRATION_STATUS_FAILED); notifier_list_notify(&migration_state_notifiers, s); } @@ -853,7 +858,7 @@ static void migrate_fd_cancel(MigrationState *s) if (!migration_is_setup_or_active(old_state)) { break; } - migrate_set_state(s, old_state, MIGRATION_STATUS_CANCELLING); + migrate_set_state(&s->state, old_state, MIGRATION_STATUS_CANCELLING); } while (s->state != MIGRATION_STATUS_CANCELLING); /* @@ -927,7 +932,7 @@ MigrationState *migrate_init(const MigrationParams *params) s->migration_thread_running = false; s->last_req_rb = NULL; - migrate_set_state(s, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); + migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP); QSIMPLEQ_INIT(&s->src_page_requests); @@ -1026,7 +1031,8 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } else { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); - migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); + migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, + MIGRATION_STATUS_FAILED); return; } @@ -1405,7 +1411,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) int ret; const QEMUSizedBuffer *qsb; int64_t time_at_stop = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); - migrate_set_state(ms, MIGRATION_STATUS_ACTIVE, + migrate_set_state(&ms->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_POSTCOPY_ACTIVE); trace_postcopy_start(); @@ -1496,7 +1502,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) ret = qemu_file_get_error(ms->file); if (ret) { error_report("postcopy_start: Migration stream errored"); - migrate_set_state(ms, MIGRATION_STATUS_POSTCOPY_ACTIVE, + migrate_set_state(&ms->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, MIGRATION_STATUS_FAILED); } @@ -1505,7 +1511,7 @@ static int postcopy_start(MigrationState *ms, bool *old_vm_running) fail_closefb: qemu_fclose(fb); fail: - migrate_set_state(ms, MIGRATION_STATUS_POSTCOPY_ACTIVE, + migrate_set_state(&ms->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, MIGRATION_STATUS_FAILED); qemu_mutex_unlock_iothread(); return -1; @@ -1574,11 +1580,13 @@ static void migration_completion(MigrationState *s, int current_active_state, goto fail; } - migrate_set_state(s, current_active_state, MIGRATION_STATUS_COMPLETED); + migrate_set_state(&s->state, current_active_state, + MIGRATION_STATUS_COMPLETED); return; fail: - migrate_set_state(s, current_active_state, MIGRATION_STATUS_FAILED); + migrate_set_state(&s->state, current_active_state, + MIGRATION_STATUS_FAILED); } /* @@ -1623,7 +1631,8 @@ static void *migration_thread(void *opaque) s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; current_active_state = MIGRATION_STATUS_ACTIVE; - migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_ACTIVE); + migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, + MIGRATION_STATUS_ACTIVE); trace_migration_thread_setup_complete(); @@ -1666,7 +1675,8 @@ static void *migration_thread(void *opaque) } if (qemu_file_get_error(s->file)) { - migrate_set_state(s, current_active_state, MIGRATION_STATUS_FAILED); + migrate_set_state(&s->state, current_active_state, + MIGRATION_STATUS_FAILED); trace_migration_thread_file_err(); break; } @@ -1747,7 +1757,7 @@ void migrate_fd_connect(MigrationState *s) if (migrate_postcopy_ram()) { if (open_return_path_on_source(s)) { error_report("Unable to open return-path for postcopy"); - migrate_set_state(s, MIGRATION_STATUS_SETUP, + migrate_set_state(&s->state, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_FAILED); migrate_fd_cleanup(s); return; diff --git a/migration/ram.c b/migration/ram.c index 5bfcca3884..4e606ab1a4 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -27,6 +27,7 @@ */ #include <stdint.h> #include <zlib.h> +#include "qapi-event.h" #include "qemu/bitops.h" #include "qemu/bitmap.h" #include "qemu/timer.h" @@ -285,7 +286,6 @@ static bool quit_comp_thread; static bool quit_decomp_thread; static DecompressParam *decomp_param; static QemuThread *decompress_threads; -static uint8_t *compressed_data_buf; static int do_compress_ram_page(CompressParam *param); @@ -682,6 +682,9 @@ static void migration_bitmap_sync(void) num_dirty_pages_period = 0; } s->dirty_sync_count = bitmap_sync_count; + if (migrate_use_events()) { + qapi_event_send_migration_pass(bitmap_sync_count, NULL); + } } /** @@ -2084,10 +2087,12 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) { unsigned int xh_len; int xh_flags; + uint8_t *loaded_data; if (!xbzrle_decoded_buf) { xbzrle_decoded_buf = g_malloc(TARGET_PAGE_SIZE); } + loaded_data = xbzrle_decoded_buf; /* extract RLE header */ xh_flags = qemu_get_byte(f); @@ -2103,10 +2108,10 @@ static int load_xbzrle(QEMUFile *f, ram_addr_t addr, void *host) return -1; } /* load data and decode */ - qemu_get_buffer(f, xbzrle_decoded_buf, xh_len); + qemu_get_buffer_in_place(f, &loaded_data, xh_len); /* decode RLE */ - if (xbzrle_decode_buffer(xbzrle_decoded_buf, xh_len, host, + if (xbzrle_decode_buffer(loaded_data, xh_len, host, TARGET_PAGE_SIZE) == -1) { error_report("Failed to load XBZRLE page - decode error!"); return -1; @@ -2201,7 +2206,6 @@ void migrate_decompress_threads_create(void) thread_count = migrate_decompress_threads(); decompress_threads = g_new0(QemuThread, thread_count); decomp_param = g_new0(DecompressParam, thread_count); - compressed_data_buf = g_malloc0(compressBound(TARGET_PAGE_SIZE)); quit_decomp_thread = false; for (i = 0; i < thread_count; i++) { qemu_mutex_init(&decomp_param[i].mutex); @@ -2232,13 +2236,11 @@ void migrate_decompress_threads_join(void) } g_free(decompress_threads); g_free(decomp_param); - g_free(compressed_data_buf); decompress_threads = NULL; decomp_param = NULL; - compressed_data_buf = NULL; } -static void decompress_data_with_multi_threads(uint8_t *compbuf, +static void decompress_data_with_multi_threads(QEMUFile *f, void *host, int len) { int idx, thread_count; @@ -2247,7 +2249,7 @@ static void decompress_data_with_multi_threads(uint8_t *compbuf, while (true) { for (idx = 0; idx < thread_count; idx++) { if (!decomp_param[idx].start) { - memcpy(decomp_param[idx].compbuf, compbuf, len); + qemu_get_buffer(f, decomp_param[idx].compbuf, len); decomp_param[idx].des = host; decomp_param[idx].len = len; start_decompression(&decomp_param[idx]); @@ -2492,8 +2494,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) ret = -EINVAL; break; } - qemu_get_buffer(f, compressed_data_buf, len); - decompress_data_with_multi_threads(compressed_data_buf, host, len); + decompress_data_with_multi_threads(f, host, len); break; case RAM_SAVE_FLAG_XBZRLE: diff --git a/migration/savevm.c b/migration/savevm.c index 540eb288af..b9caf597dc 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1399,6 +1399,8 @@ static void *postcopy_ram_listen_thread(void *opaque) MigrationIncomingState *mis = migration_incoming_get_current(); int load_res; + migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_POSTCOPY_ACTIVE); qemu_sem_post(&mis->listen_thread_sem); trace_postcopy_ram_listen_thread_start(); @@ -1415,6 +1417,8 @@ static void *postcopy_ram_listen_thread(void *opaque) if (load_res < 0) { error_report("%s: loadvm failed: %d", __func__, load_res); qemu_file_set_error(f, load_res); + migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, + MIGRATION_STATUS_FAILED); } else { /* * This looks good, but it's possible that the device loading in the @@ -1424,13 +1428,6 @@ static void *postcopy_ram_listen_thread(void *opaque) qemu_event_wait(&mis->main_thread_load_event); } postcopy_ram_incoming_cleanup(mis); - /* - * If everything has worked fine, then the main thread has waited - * for us to start, and we're the last use of the mis. - * (If something broke then qemu will have to exit anyway since it's - * got a bad migration state). - */ - migration_incoming_state_destroy(); if (load_res < 0) { /* @@ -1442,6 +1439,17 @@ static void *postcopy_ram_listen_thread(void *opaque) exit(EXIT_FAILURE); } + migrate_set_state(&mis->state, MIGRATION_STATUS_POSTCOPY_ACTIVE, + MIGRATION_STATUS_COMPLETED); + /* + * If everything has worked fine, then the main thread has waited + * for us to start, and we're the last use of the mis. + * (If something broke then qemu will have to exit anyway since it's + * got a bad migration state). + */ + migration_incoming_state_destroy(); + + return NULL; } diff --git a/qapi/event.json b/qapi/event.json index f0cef010f0..390fd45788 100644 --- a/qapi/event.json +++ b/qapi/event.json @@ -255,6 +255,19 @@ 'data': {'status': 'MigrationStatus'}} ## +# @MIGRATION_PASS +# +# Emitted from the source side of a migration at the start of each pass +# (when it syncs the dirty bitmap) +# +# @pass: An incrementing count (starting at 1 on the first pass) +# +# Since: 2.6 +## +{ 'event': 'MIGRATION_PASS', + 'data': { 'pass': 'int' } } + +## # @ACPI_DEVICE_OST # # Emitted when guest executes ACPI _OST method. diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 658cd9d554..06ca60b25f 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -545,9 +545,6 @@ int gtod_load(QEMUFile *f, void *opaque, int version_id); /* service interrupts are floating therefore we must not pass an cpustate */ void s390_sclp_extint(uint32_t parm); -/* from s390-virtio-bus */ -extern const hwaddr virtio_size; - #else static inline unsigned int s390_cpu_halt(S390CPU *cpu) { diff --git a/target-s390x/helper.c b/target-s390x/helper.c index aa58f39db4..e541d69724 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -133,7 +133,7 @@ int s390_cpu_handle_mmu_fault(CPUState *cs, vaddr orig_vaddr, } /* check out of RAM access */ - if (raddr > (ram_size + virtio_size)) { + if (raddr > ram_size) { DPRINTF("%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n", __func__, (uint64_t)raddr, (uint64_t)ram_size); trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_LATER); @@ -227,7 +227,6 @@ static struct { { .driver = "ide-drive", .flag = &default_cdrom }, { .driver = "scsi-cd", .flag = &default_cdrom }, { .driver = "virtio-serial-pci", .flag = &default_virtcon }, - { .driver = "virtio-serial-s390", .flag = &default_virtcon }, { .driver = "virtio-serial", .flag = &default_virtcon }, { .driver = "VGA", .flag = &default_vga }, { .driver = "isa-vga", .flag = &default_vga }, @@ -2548,11 +2547,7 @@ static int virtcon_parse(const char *devname) } bus_opts = qemu_opts_create(device, NULL, 0, &error_abort); - if (arch_type == QEMU_ARCH_S390X) { - qemu_opt_set(bus_opts, "driver", "virtio-serial-s390", &error_abort); - } else { - qemu_opt_set(bus_opts, "driver", "virtio-serial-pci", &error_abort); - } + qemu_opt_set(bus_opts, "driver", "virtio-serial", &error_abort); dev_opts = qemu_opts_create(device, NULL, 0, &error_abort); qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort); |