diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/intc/s390_flic.c | 28 | ||||
-rw-r--r-- | hw/intc/s390_flic_kvm.c | 6 | ||||
-rw-r--r-- | hw/s390x/css.c | 15 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 9 | ||||
-rw-r--r-- | hw/s390x/s390-virtio.c | 10 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 109 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.h | 13 |
7 files changed, 161 insertions, 29 deletions
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index 6ab29efc65..bef4caf980 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -16,6 +16,8 @@ #include "migration/qemu-file.h" #include "hw/s390x/s390_flic.h" #include "trace.h" +#include "hw/qdev.h" +#include "qapi/error.h" S390FLICState *s390_get_flic(void) { @@ -85,6 +87,30 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data) fsc->clear_io_irq = qemu_s390_clear_io_flic; } +static Property s390_flic_common_properties[] = { + DEFINE_PROP_UINT32("adapter_routes_max_batch", S390FLICState, + adapter_routes_max_batch, ADAPTER_ROUTES_MAX_GSI), + DEFINE_PROP_END_OF_LIST(), +}; + +static void s390_flic_common_realize(DeviceState *dev, Error **errp) +{ + uint32_t max_batch = S390_FLIC_COMMON(dev)->adapter_routes_max_batch; + + if (max_batch > ADAPTER_ROUTES_MAX_GSI) { + error_setg(errp, "flic adapter_routes_max_batch too big" + "%d (%d allowed)", max_batch, ADAPTER_ROUTES_MAX_GSI); + } +} + +static void s390_flic_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->props = s390_flic_common_properties; + dc->realize = s390_flic_common_realize; +} + static const TypeInfo qemu_s390_flic_info = { .name = TYPE_QEMU_S390_FLIC, .parent = TYPE_S390_FLIC_COMMON, @@ -92,10 +118,12 @@ static const TypeInfo qemu_s390_flic_info = { .class_init = qemu_s390_flic_class_init, }; + static const TypeInfo s390_flic_common_info = { .name = TYPE_S390_FLIC_COMMON, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(S390FLICState), + .class_init = s390_flic_class_init, .class_size = sizeof(S390FLICStateClass), }; diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index e86a84e49a..cc44bc4e1e 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -293,6 +293,7 @@ static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size, int len = FLIC_SAVE_INITIAL_SIZE; void *buf; int count; + int r = 0; flic_disable_wait_pfault((struct KVMS390FLICState *) opaque); @@ -303,7 +304,7 @@ static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size, * migration state */ error_report("flic: couldn't allocate memory"); qemu_put_be64(f, FLIC_FAILED); - return 0; + return -ENOMEM; } count = __get_all_irqs(flic, &buf, len); @@ -314,6 +315,7 @@ static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size, * target system to fail when attempting to load irqs from the * migration state */ qemu_put_be64(f, FLIC_FAILED); + r = count; } else { qemu_put_be64(f, count); qemu_put_buffer(f, (uint8_t *) buf, @@ -321,7 +323,7 @@ static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size, } g_free(buf); - return 0; + return r; } /** diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 0f2580d644..e32b2a4d42 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -368,13 +368,16 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1) ret.cda = be32_to_cpu(tmp1.cda); } else { cpu_physical_memory_read(addr, &tmp0, sizeof(tmp0)); - ret.cmd_code = tmp0.cmd_code; - ret.flags = tmp0.flags; - ret.count = be16_to_cpu(tmp0.count); - ret.cda = be16_to_cpu(tmp0.cda1) | (tmp0.cda0 << 16); - if ((ret.cmd_code & 0x0f) == CCW_CMD_TIC) { - ret.cmd_code &= 0x0f; + if ((tmp0.cmd_code & 0x0f) == CCW_CMD_TIC) { + ret.cmd_code = CCW_CMD_TIC; + ret.flags = 0; + ret.count = 0; + } else { + ret.cmd_code = tmp0.cmd_code; + ret.flags = tmp0.flags; + ret.count = be16_to_cpu(tmp0.count); } + ret.cda = be16_to_cpu(tmp0.cda1) | (tmp0.cda0 << 16); } return ret; } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e9a676797a..4f0d62b2d8 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -63,7 +63,7 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) if (!sch || !css_subch_visible(sch)) { return -EINVAL; } - if (queue >= VIRTIO_CCW_QUEUE_MAX) { + if (queue >= VIRTIO_QUEUE_MAX) { return -EINVAL; } virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); @@ -336,7 +336,12 @@ static const TypeInfo ccw_machine_info = { type_init(ccw_machine_register_##suffix) #define CCW_COMPAT_2_8 \ - HW_COMPAT_2_8 + HW_COMPAT_2_8 \ + {\ + .driver = TYPE_S390_FLIC_COMMON,\ + .property = "adapter_routes_max_batch",\ + .value = "64",\ + }, #define CCW_COMPAT_2_7 \ HW_COMPAT_2_7 diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 7a3a7fe5fd..9cfb09057e 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -44,16 +44,6 @@ #include "hw/s390x/ipl.h" #include "cpu.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 MAX_BLK_DEVS 10 #define S390_TOD_CLOCK_VALUE_MISSING 0x00 diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 63c46373fb..00b3bde4e9 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -35,6 +35,8 @@ #include "trace.h" #include "hw/s390x/css-bridge.h" +#define NR_CLASSIC_INDICATOR_BITS 64 + static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size, VirtioCcwDevice *dev); @@ -126,7 +128,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info, uint16_t num = info ? info->num : linfo->num; uint64_t desc = info ? info->desc : linfo->queue; - if (index >= VIRTIO_CCW_QUEUE_MAX) { + if (index >= VIRTIO_QUEUE_MAX) { return -EINVAL; } @@ -162,7 +164,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info, virtio_queue_set_vector(vdev, index, index); } /* tell notify handler in case of config change */ - vdev->config_vector = VIRTIO_CCW_QUEUE_MAX; + vdev->config_vector = VIRTIO_QUEUE_MAX; return 0; } @@ -280,6 +282,15 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ccw.cmd_code); check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); + if (dev->force_revision_1 && dev->revision < 0 && + ccw.cmd_code != CCW_CMD_SET_VIRTIO_REV) { + /* + * virtio-1 drivers must start with negotiating to a revision >= 1, + * so post a command reject for all other commands + */ + return -ENOSYS; + } + /* Look at the command. */ switch (ccw.cmd_code) { case CCW_CMD_SET_VQ: @@ -500,6 +511,11 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ret = -ENOSYS; break; } + if (virtio_get_num_queues(vdev) > NR_CLASSIC_INDICATOR_BITS) { + /* More queues than indicator bits --> trigger a reject */ + ret = -ENOSYS; + break; + } if (!ccw.cda) { ret = -EFAULT; } else { @@ -549,7 +565,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ccw.cda, MEMTXATTRS_UNSPECIFIED, NULL); - if (vq_config.index >= VIRTIO_CCW_QUEUE_MAX) { + if (vq_config.index >= VIRTIO_QUEUE_MAX) { ret = -EINVAL; break; } @@ -638,7 +654,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) * need to fetch it here. Nothing to do for now, though. */ if (dev->revision >= 0 || - revinfo.revision > virtio_ccw_rev_max(dev)) { + revinfo.revision > virtio_ccw_rev_max(dev) || + (dev->force_revision_1 && !revinfo.revision)) { ret = -ENOSYS; break; } @@ -669,6 +686,12 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) if (!sch) { return; } + if (!virtio_ccw_rev_max(dev) && dev->force_revision_1) { + error_setg(&err, "Invalid value of property max_rev " + "(is %d expected >= 1)", virtio_ccw_rev_max(dev)); + error_propagate(errp, err); + return; + } sch->driver_data = dev; sch->ccw_cb = virtio_ccw_cb; @@ -878,6 +901,24 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp) NULL); } +static void virtio_ccw_crypto_realize(VirtioCcwDevice *ccw_dev, Error **errp) +{ + VirtIOCryptoCcw *dev = VIRTIO_CRYPTO_CCW(ccw_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + Error *err = NULL; + + qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus)); + object_property_set_bool(OBJECT(vdev), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + object_property_set_link(OBJECT(vdev), + OBJECT(dev->vdev.conf.cryptodev), "cryptodev", + NULL); +} + /* DeviceState to VirtioCcwDevice. Note: used on datapath, * be careful and test performance if you change this. */ @@ -919,11 +960,11 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector) uint64_t indicators; /* queue indicators + secondary indicators */ - if (vector >= VIRTIO_CCW_QUEUE_MAX + 64) { + if (vector >= VIRTIO_QUEUE_MAX + 64) { return; } - if (vector < VIRTIO_CCW_QUEUE_MAX) { + if (vector < VIRTIO_QUEUE_MAX) { if (!dev->indicators) { return; } @@ -1278,15 +1319,22 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) CcwDevice *ccw_dev = CCW_DEVICE(d); SubchDev *sch = ccw_dev->sch; int n = virtio_get_num_queues(vdev); + S390FLICState *flic = s390_get_flic(); if (!virtio_has_feature(vdev->host_features, VIRTIO_F_VERSION_1)) { dev->max_rev = 0; } - if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) { + if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) { + error_setg(errp, "The number of virtqueues %d " + "exceeds virtio limit %d", n, + VIRTIO_QUEUE_MAX); + return; + } + if (virtio_get_num_queues(vdev) > flic->adapter_routes_max_batch) { error_setg(errp, "The number of virtqueues %d " - "exceeds ccw limit %d", n, - VIRTIO_CCW_QUEUE_MAX); + "exceeds flic adapter route limit %d", n, + flic->adapter_routes_max_batch); return; } @@ -1518,6 +1566,48 @@ static const TypeInfo virtio_ccw_rng = { .class_init = virtio_ccw_rng_class_init, }; +static Property virtio_ccw_crypto_properties[] = { + DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id), + DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, + VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), + DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev, + VIRTIO_CCW_MAX_REV), + DEFINE_PROP_END_OF_LIST(), +}; + +static void virtio_ccw_crypto_instance_init(Object *obj) +{ + VirtIOCryptoCcw *dev = VIRTIO_CRYPTO_CCW(obj); + VirtioCcwDevice *ccw_dev = VIRTIO_CCW_DEVICE(obj); + + ccw_dev->force_revision_1 = true; + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VIRTIO_CRYPTO); + + object_property_add_alias(obj, "cryptodev", OBJECT(&dev->vdev), + "cryptodev", &error_abort); +} + +static void virtio_ccw_crypto_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass); + + k->realize = virtio_ccw_crypto_realize; + k->exit = virtio_ccw_exit; + dc->reset = virtio_ccw_reset; + dc->props = virtio_ccw_crypto_properties; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo virtio_ccw_crypto = { + .name = TYPE_VIRTIO_CRYPTO_CCW, + .parent = TYPE_VIRTIO_CCW_DEVICE, + .instance_size = sizeof(VirtIOCryptoCcw), + .instance_init = virtio_ccw_crypto_instance_init, + .class_init = virtio_ccw_crypto_class_init, +}; + static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp) { VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; @@ -1720,6 +1810,7 @@ static void virtio_ccw_register(void) #ifdef CONFIG_VHOST_VSOCK type_register_static(&vhost_vsock_ccw_info); #endif + type_register_static(&virtio_ccw_crypto); } type_init(virtio_ccw_register) diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 77d10f1671..41d4010378 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -22,6 +22,7 @@ #endif #include "hw/virtio/virtio-balloon.h" #include "hw/virtio/virtio-rng.h" +#include "hw/virtio/virtio-crypto.h" #include "hw/virtio/virtio-bus.h" #ifdef CONFIG_VHOST_VSOCK #include "hw/virtio/vhost-vsock.h" @@ -94,6 +95,7 @@ struct VirtioCcwDevice { IndAddr *indicators2; IndAddr *summary_indicator; uint64_t ind_bit; + bool force_revision_1; }; /* The maximum virtio revision we support. */ @@ -182,6 +184,17 @@ typedef struct VirtIORNGCcw { VirtIORNG vdev; } VirtIORNGCcw; +/* virtio-crypto-ccw */ + +#define TYPE_VIRTIO_CRYPTO_CCW "virtio-crypto-ccw" +#define VIRTIO_CRYPTO_CCW(obj) \ + OBJECT_CHECK(VirtIOCryptoCcw, (obj), TYPE_VIRTIO_CRYPTO_CCW) + +typedef struct VirtIOCryptoCcw { + VirtioCcwDevice parent_obj; + VirtIOCrypto vdev; +} VirtIOCryptoCcw; + VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); #ifdef CONFIG_VIRTFS |