From b6805e127c6b7815ea3abc6516b461a18d9c4d3d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 21 Sep 2017 14:59:08 +0200 Subject: s390x: use generic cpu_model parsing Define default CPU type in generic way in machine class_init and let common machine code handle cpu_model parsing. Signed-off-by: Igor Mammedov Reviewed-by: David Hildenbrand Message-Id: <1505998749-269631-1-git-send-email-imammedo@redhat.com> Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index fafbc6d4fe..1bcb7000ab 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -55,15 +55,8 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr) static void s390_init_cpus(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *typename; - gchar **model_pieces; - ObjectClass *oc; - CPUClass *cc; int i; - if (machine->cpu_model == NULL) { - machine->cpu_model = s390_default_cpu_model_name(); - } if (tcg_enabled() && max_cpus > 1) { error_report("Number of SMP CPUs requested (%d) exceeds max CPUs " "supported by TCG (1) on s390x", max_cpus); @@ -73,25 +66,8 @@ static void s390_init_cpus(MachineState *machine) /* initialize possible_cpus */ mc->possible_cpu_arch_ids(machine); - model_pieces = g_strsplit(machine->cpu_model, ",", 2); - if (!model_pieces[0]) { - error_report("Invalid/empty CPU model name"); - exit(1); - } - - oc = cpu_class_by_name(TYPE_S390_CPU, model_pieces[0]); - if (!oc) { - error_report("Unable to find CPU definition: %s", model_pieces[0]); - exit(1); - } - typename = object_class_get_name(oc); - cc = CPU_CLASS(oc); - /* after parsing, properties will be applied to all *typename* instances */ - cc->parse_features(typename, model_pieces[1], &error_fatal); - g_strfreev(model_pieces); - for (i = 0; i < smp_cpus; i++) { - s390x_new_cpu(typename, i, &error_fatal); + s390x_new_cpu(machine->cpu_type, i, &error_fatal); } } @@ -446,6 +422,8 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) mc->get_hotplug_handler = s390_get_hotplug_handler; mc->cpu_index_to_instance_props = s390_cpu_index_to_props; mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids; + /* it is overridden with 'host' cpu *in kvm_arch_init* */ + mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu"); hc->plug = s390_machine_device_plug; hc->unplug_request = s390_machine_device_unplug_request; nc->nmi_monitor_handler = s390_nmi; -- cgit v1.2.3 From 57065a70d00c36f5d20d430eb64d16db8e761c31 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 21 Sep 2017 20:08:37 +0200 Subject: s390x/css: introduce css data stream This is a preparation for introducing handling for indirect data addressing and modified indirect data addressing (CCW). Here we introduce an interface which should make the addressing scheme transparent for the client code. Here we implement only the basic scheme (no IDA or MIDA). Signed-off-by: Halil Pasic Reviewed-by: Dong Jia Shi Reviewed-by: Pierre Morel Message-Id: <20170921180841.24490-2-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/css.c b/hw/s390x/css.c index c59be1aad1..248e9d47e5 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -787,6 +787,61 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1) } return ret; } +/** + * If out of bounds marks the stream broken. If broken returns -EINVAL, + * otherwise the requested length (may be zero) + */ +static inline int cds_check_len(CcwDataStream *cds, int len) +{ + if (cds->at_byte + len > cds->count) { + cds->flags |= CDS_F_STREAM_BROKEN; + } + return cds->flags & CDS_F_STREAM_BROKEN ? -EINVAL : len; +} + +static int ccw_dstream_rw_noflags(CcwDataStream *cds, void *buff, int len, + CcwDataStreamOp op) +{ + int ret; + + ret = cds_check_len(cds, len); + if (ret <= 0) { + return ret; + } + if (op == CDS_OP_A) { + goto incr; + } + ret = address_space_rw(&address_space_memory, cds->cda, + MEMTXATTRS_UNSPECIFIED, buff, len, op); + if (ret != MEMTX_OK) { + cds->flags |= CDS_F_STREAM_BROKEN; + return -EINVAL; + } +incr: + cds->at_byte += len; + cds->cda += len; + return 0; +} + +void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb) +{ + /* + * We don't support MIDA (an optional facility) yet and we + * catch this earlier. Just for expressing the precondition. + */ + g_assert(!(orb->ctrl1 & ORB_CTRL1_MASK_MIDAW)); + cds->flags = (orb->ctrl0 & ORB_CTRL0_MASK_I2K ? CDS_F_I2K : 0) | + (orb->ctrl0 & ORB_CTRL0_MASK_C64 ? CDS_F_C64 : 0) | + (ccw->flags & CCW_FLAG_IDA ? CDS_F_IDA : 0); + cds->count = ccw->count; + cds->cda_orig = ccw->cda; + ccw_dstream_rewind(cds); + if (!(cds->flags & CDS_F_IDA)) { + cds->op_handler = ccw_dstream_rw_noflags; + } else { + assert(false); + } +} static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, bool suspend_allowed) -- cgit v1.2.3 From 0a22eac5aaf90b2c2c1a4c29eecc25ef508d520b Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 21 Sep 2017 20:08:38 +0200 Subject: s390x/css: use ccw data stream Replace direct access which implicitly assumes no IDA or MIDA with the new ccw data stream interface which should cope with these transparently in the future. Note that checking the return code for ccw_dstream_* will be done in a follow-on patch. Signed-off-by: Halil Pasic Reviewed-by: Dong Jia Shi Reviewed-by: Pierre Morel Message-Id: <20170921180841.24490-3-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 248e9d47e5..390c78f7d0 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -894,6 +894,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, } /* Look at the command. */ + ccw_dstream_init(&sch->cds, &ccw, &(sch->orb)); switch (ccw.cmd_code) { case CCW_CMD_NOOP: /* Nothing to do. */ @@ -907,8 +908,8 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, } } len = MIN(ccw.count, sizeof(sch->sense_data)); - cpu_physical_memory_write(ccw.cda, sch->sense_data, len); - sch->curr_status.scsw.count = ccw.count - len; + ccw_dstream_write_buf(&sch->cds, sch->sense_data, len); + sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds); memset(sch->sense_data, 0, sizeof(sch->sense_data)); ret = 0; break; @@ -934,8 +935,8 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr, } else { sense_id.reserved = 0; } - cpu_physical_memory_write(ccw.cda, &sense_id, len); - sch->curr_status.scsw.count = ccw.count - len; + ccw_dstream_write_buf(&sch->cds, &sense_id, len); + sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds); ret = 0; break; } -- cgit v1.2.3 From f57ba05823b7c444133f0862077b45824a6a89b5 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 21 Sep 2017 20:08:39 +0200 Subject: virtio-ccw: use ccw data stream Replace direct access which implicitly assumes no IDA or MIDA with the new ccw data stream interface which should cope with these transparently in the future. Note that checking the return code for ccw_dstream_* will be done in a follow-on patch. Signed-off-by: Halil Pasic Reviewed-by: Pierre Morel Reviewed-by: Dong Jia Shi Message-Id: <20170921180841.24490-4-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- hw/s390x/virtio-ccw.c | 155 +++++++++++++++----------------------------------- 1 file changed, 46 insertions(+), 109 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 62d69aa30b..085f17f871 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -289,49 +289,19 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len, return -EFAULT; } if (is_legacy) { - linfo.queue = address_space_ldq_be(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); - linfo.align = address_space_ldl_be(&address_space_memory, - ccw.cda + sizeof(linfo.queue), - MEMTXATTRS_UNSPECIFIED, - NULL); - linfo.index = address_space_lduw_be(&address_space_memory, - ccw.cda + sizeof(linfo.queue) - + sizeof(linfo.align), - MEMTXATTRS_UNSPECIFIED, - NULL); - linfo.num = address_space_lduw_be(&address_space_memory, - ccw.cda + sizeof(linfo.queue) - + sizeof(linfo.align) - + sizeof(linfo.index), - MEMTXATTRS_UNSPECIFIED, - NULL); + ccw_dstream_read(&sch->cds, linfo); + be64_to_cpus(&linfo.queue); + be32_to_cpus(&linfo.align); + be16_to_cpus(&linfo.index); + be16_to_cpus(&linfo.num); ret = virtio_ccw_set_vqs(sch, NULL, &linfo); } else { - info.desc = address_space_ldq_be(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); - info.index = address_space_lduw_be(&address_space_memory, - ccw.cda + sizeof(info.desc) - + sizeof(info.res0), - MEMTXATTRS_UNSPECIFIED, NULL); - info.num = address_space_lduw_be(&address_space_memory, - ccw.cda + sizeof(info.desc) - + sizeof(info.res0) - + sizeof(info.index), - MEMTXATTRS_UNSPECIFIED, NULL); - info.avail = address_space_ldq_be(&address_space_memory, - ccw.cda + sizeof(info.desc) - + sizeof(info.res0) - + sizeof(info.index) - + sizeof(info.num), - MEMTXATTRS_UNSPECIFIED, NULL); - info.used = address_space_ldq_be(&address_space_memory, - ccw.cda + sizeof(info.desc) - + sizeof(info.res0) - + sizeof(info.index) - + sizeof(info.num) - + sizeof(info.avail), - MEMTXATTRS_UNSPECIFIED, NULL); + ccw_dstream_read(&sch->cds, info); + be64_to_cpus(&info.desc); + be16_to_cpus(&info.index); + be16_to_cpus(&info.num); + be64_to_cpus(&info.avail); + be64_to_cpus(&info.used); ret = virtio_ccw_set_vqs(sch, &info, NULL); } sch->curr_status.scsw.count = 0; @@ -344,15 +314,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) VirtioRevInfo revinfo; uint8_t status; VirtioFeatDesc features; - void *config; hwaddr indicators; VqConfigBlock vq_config; VirtioCcwDevice *dev = sch->driver_data; VirtIODevice *vdev = virtio_ccw_get_vdev(sch); bool check_len; int len; - hwaddr hw_len; - VirtioThinintInfo *thinint; + VirtioThinintInfo thinint; if (!dev) { return -EINVAL; @@ -396,11 +364,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } else { VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); - features.index = address_space_ldub(&address_space_memory, - ccw.cda - + sizeof(features.features), - MEMTXATTRS_UNSPECIFIED, - NULL); + ccw_dstream_advance(&sch->cds, sizeof(features.features)); + ccw_dstream_read(&sch->cds, features.index); if (features.index == 0) { if (dev->revision >= 1) { /* Don't offer legacy features for modern devices. */ @@ -419,9 +384,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) /* Return zeroes if the guest supports more feature bits. */ features.features = 0; } - address_space_stl_le(&address_space_memory, ccw.cda, - features.features, MEMTXATTRS_UNSPECIFIED, - NULL); + ccw_dstream_rewind(&sch->cds); + cpu_to_le32s(&features.features); + ccw_dstream_write(&sch->cds, features.features); sch->curr_status.scsw.count = ccw.count - sizeof(features); ret = 0; } @@ -440,15 +405,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - features.index = address_space_ldub(&address_space_memory, - ccw.cda - + sizeof(features.features), - MEMTXATTRS_UNSPECIFIED, - NULL); - features.features = address_space_ldl_le(&address_space_memory, - ccw.cda, - MEMTXATTRS_UNSPECIFIED, - NULL); + ccw_dstream_read(&sch->cds, features); + le32_to_cpus(&features.features); if (features.index == 0) { virtio_set_features(vdev, (vdev->guest_features & 0xffffffff00000000ULL) | @@ -489,7 +447,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ret = -EFAULT; } else { virtio_bus_get_vdev_config(&dev->bus, vdev->config); - cpu_physical_memory_write(ccw.cda, vdev->config, len); + ccw_dstream_write_buf(&sch->cds, vdev->config, len); sch->curr_status.scsw.count = ccw.count - len; ret = 0; } @@ -502,20 +460,13 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } } len = MIN(ccw.count, vdev->config_len); - hw_len = len; if (!ccw.cda) { ret = -EFAULT; } else { - config = cpu_physical_memory_map(ccw.cda, &hw_len, 0); - if (!config) { - ret = -EFAULT; - } else { - len = hw_len; - memcpy(vdev->config, config, len); - cpu_physical_memory_unmap(config, hw_len, 0, hw_len); + ret = ccw_dstream_read_buf(&sch->cds, vdev->config, len); + if (!ret) { virtio_bus_set_vdev_config(&dev->bus, vdev->config); sch->curr_status.scsw.count = ccw.count - len; - ret = 0; } } break; @@ -553,8 +504,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - status = address_space_ldub(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); + ccw_dstream_read(&sch->cds, status); if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { virtio_ccw_stop_ioeventfd(dev); } @@ -597,8 +547,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - indicators = address_space_ldq_be(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); + ccw_dstream_read(&sch->cds, indicators); + be64_to_cpus(&indicators); dev->indicators = get_indicator(indicators, sizeof(uint64_t)); sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; @@ -618,8 +568,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - indicators = address_space_ldq_be(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); + ccw_dstream_read(&sch->cds, indicators); + be64_to_cpus(&indicators); dev->indicators2 = get_indicator(indicators, sizeof(uint64_t)); sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; @@ -639,67 +589,58 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!ccw.cda) { ret = -EFAULT; } else { - vq_config.index = address_space_lduw_be(&address_space_memory, - ccw.cda, - MEMTXATTRS_UNSPECIFIED, - NULL); + ccw_dstream_read(&sch->cds, vq_config.index); + be16_to_cpus(&vq_config.index); if (vq_config.index >= VIRTIO_QUEUE_MAX) { ret = -EINVAL; break; } vq_config.num_max = virtio_queue_get_num(vdev, vq_config.index); - address_space_stw_be(&address_space_memory, - ccw.cda + sizeof(vq_config.index), - vq_config.num_max, - MEMTXATTRS_UNSPECIFIED, - NULL); + cpu_to_be16s(&vq_config.num_max); + ccw_dstream_write(&sch->cds, vq_config.num_max); sch->curr_status.scsw.count = ccw.count - sizeof(vq_config); ret = 0; } break; case CCW_CMD_SET_IND_ADAPTER: if (check_len) { - if (ccw.count != sizeof(*thinint)) { + if (ccw.count != sizeof(thinint)) { ret = -EINVAL; break; } - } else if (ccw.count < sizeof(*thinint)) { + } else if (ccw.count < sizeof(thinint)) { /* Can't execute command. */ ret = -EINVAL; break; } - len = sizeof(*thinint); - hw_len = len; if (!ccw.cda) { ret = -EFAULT; } else if (dev->indicators && !sch->thinint_active) { /* Trigger a command reject. */ ret = -ENOSYS; } else { - thinint = cpu_physical_memory_map(ccw.cda, &hw_len, 0); - if (!thinint) { + if (ccw_dstream_read(&sch->cds, thinint)) { ret = -EFAULT; } else { - uint64_t ind_bit = ldq_be_p(&thinint->ind_bit); + be64_to_cpus(&thinint.ind_bit); + be64_to_cpus(&thinint.summary_indicator); + be64_to_cpus(&thinint.device_indicator); - len = hw_len; dev->summary_indicator = - get_indicator(ldq_be_p(&thinint->summary_indicator), - sizeof(uint8_t)); + get_indicator(thinint.summary_indicator, sizeof(uint8_t)); dev->indicators = - get_indicator(ldq_be_p(&thinint->device_indicator), - ind_bit / 8 + 1); - dev->thinint_isc = thinint->isc; - dev->routes.adapter.ind_offset = ind_bit; + get_indicator(thinint.device_indicator, + thinint.ind_bit / 8 + 1); + dev->thinint_isc = thinint.isc; + dev->routes.adapter.ind_offset = thinint.ind_bit; dev->routes.adapter.summary_offset = 7; - cpu_physical_memory_unmap(thinint, hw_len, 0, hw_len); dev->routes.adapter.adapter_id = css_get_adapter_id( CSS_IO_ADAPTER_VIRTIO, dev->thinint_isc); sch->thinint_active = ((dev->indicators != NULL) && (dev->summary_indicator != NULL)); - sch->curr_status.scsw.count = ccw.count - len; + sch->curr_status.scsw.count = ccw.count - sizeof(thinint); ret = 0; } } @@ -714,13 +655,9 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) ret = -EFAULT; break; } - revinfo.revision = - address_space_lduw_be(&address_space_memory, ccw.cda, - MEMTXATTRS_UNSPECIFIED, NULL); - revinfo.length = - address_space_lduw_be(&address_space_memory, - ccw.cda + sizeof(revinfo.revision), - MEMTXATTRS_UNSPECIFIED, NULL); + ccw_dstream_read_buf(&sch->cds, &revinfo, 4); + be16_to_cpus(&revinfo.revision); + be16_to_cpus(&revinfo.length); if (ccw.count < len + revinfo.length || (check_len && ccw.count > len + revinfo.length)) { ret = -EINVAL; -- cgit v1.2.3 From 62a2554ec2630896d1299e1a282a64c7f3b00da0 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 21 Sep 2017 20:08:40 +0200 Subject: 390x/css: introduce maximum data address checking The architecture mandates the addresses to be accessed on the first indirection level (that is, the data addresses without IDA, and the (M)IDAW addresses with (M)IDA) to be checked against an CCW format dependent limit maximum address. If a violation is detected, the storage access is not to be performed and a channel program check needs to be generated. As of today, we fail to do this check. Let us stick even closer to the architecture specification. Signed-off-by: Halil Pasic Message-Id: <20170921180841.24490-5-pasic@linux.vnet.ibm.com> Reviewed-by: Pierre Morel Reviewed-by: Dong Jia Shi Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 390c78f7d0..ab7333fde8 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -799,6 +799,11 @@ static inline int cds_check_len(CcwDataStream *cds, int len) return cds->flags & CDS_F_STREAM_BROKEN ? -EINVAL : len; } +static inline bool cds_ccw_addrs_ok(hwaddr addr, int len, bool ccw_fmt1) +{ + return (addr + len) < (ccw_fmt1 ? (1UL << 31) : (1UL << 24)); +} + static int ccw_dstream_rw_noflags(CcwDataStream *cds, void *buff, int len, CcwDataStreamOp op) { @@ -808,6 +813,9 @@ static int ccw_dstream_rw_noflags(CcwDataStream *cds, void *buff, int len, if (ret <= 0) { return ret; } + if (!cds_ccw_addrs_ok(cds->cda, len, cds->flags & CDS_F_FMT)) { + return -EINVAL; /* channel program check */ + } if (op == CDS_OP_A) { goto incr; } @@ -832,7 +840,9 @@ void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb) g_assert(!(orb->ctrl1 & ORB_CTRL1_MASK_MIDAW)); cds->flags = (orb->ctrl0 & ORB_CTRL0_MASK_I2K ? CDS_F_I2K : 0) | (orb->ctrl0 & ORB_CTRL0_MASK_C64 ? CDS_F_C64 : 0) | + (orb->ctrl0 & ORB_CTRL0_MASK_FMT ? CDS_F_FMT : 0) | (ccw->flags & CCW_FLAG_IDA ? CDS_F_IDA : 0); + cds->count = ccw->count; cds->cda_orig = ccw->cda; ccw_dstream_rewind(cds); -- cgit v1.2.3 From 93973f8f154e70d6cf22c418e82b0b80213d31b2 Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Thu, 21 Sep 2017 20:08:41 +0200 Subject: s390x/css: support ccw IDA Let's add indirect data addressing support for our virtual channel subsystem. This implementation does not bother with any kind of prefetching. We simply step through the IDAL on demand. Signed-off-by: Halil Pasic Message-Id: <20170921180841.24490-6-pasic@linux.vnet.ibm.com> Reviewed-by: Dong Jia Shi Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) (limited to 'hw/s390x') diff --git a/hw/s390x/css.c b/hw/s390x/css.c index ab7333fde8..35683d7954 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -831,6 +831,118 @@ incr: return 0; } +/* returns values between 1 and bsz, where bsz is a power of 2 */ +static inline uint16_t ida_continuous_left(hwaddr cda, uint64_t bsz) +{ + return bsz - (cda & (bsz - 1)); +} + +static inline uint64_t ccw_ida_block_size(uint8_t flags) +{ + if ((flags & CDS_F_C64) && !(flags & CDS_F_I2K)) { + return 1ULL << 12; + } + return 1ULL << 11; +} + +static inline int ida_read_next_idaw(CcwDataStream *cds) +{ + union {uint64_t fmt2; uint32_t fmt1; } idaw; + int ret; + hwaddr idaw_addr; + bool idaw_fmt2 = cds->flags & CDS_F_C64; + bool ccw_fmt1 = cds->flags & CDS_F_FMT; + + if (idaw_fmt2) { + idaw_addr = cds->cda_orig + sizeof(idaw.fmt2) * cds->at_idaw; + if (idaw_addr & 0x07 || !cds_ccw_addrs_ok(idaw_addr, 0, ccw_fmt1)) { + return -EINVAL; /* channel program check */ + } + ret = address_space_rw(&address_space_memory, idaw_addr, + MEMTXATTRS_UNSPECIFIED, (void *) &idaw.fmt2, + sizeof(idaw.fmt2), false); + cds->cda = be64_to_cpu(idaw.fmt2); + } else { + idaw_addr = cds->cda_orig + sizeof(idaw.fmt1) * cds->at_idaw; + if (idaw_addr & 0x03 || !cds_ccw_addrs_ok(idaw_addr, 0, ccw_fmt1)) { + return -EINVAL; /* channel program check */ + } + ret = address_space_rw(&address_space_memory, idaw_addr, + MEMTXATTRS_UNSPECIFIED, (void *) &idaw.fmt1, + sizeof(idaw.fmt1), false); + cds->cda = be64_to_cpu(idaw.fmt1); + if (cds->cda & 0x80000000) { + return -EINVAL; /* channel program check */ + } + } + ++(cds->at_idaw); + if (ret != MEMTX_OK) { + /* assume inaccessible address */ + return -EINVAL; /* channel program check */ + } + return 0; +} + +static int ccw_dstream_rw_ida(CcwDataStream *cds, void *buff, int len, + CcwDataStreamOp op) +{ + uint64_t bsz = ccw_ida_block_size(cds->flags); + int ret = 0; + uint16_t cont_left, iter_len; + + ret = cds_check_len(cds, len); + if (ret <= 0) { + return ret; + } + if (!cds->at_idaw) { + /* read first idaw */ + ret = ida_read_next_idaw(cds); + if (ret) { + goto err; + } + cont_left = ida_continuous_left(cds->cda, bsz); + } else { + cont_left = ida_continuous_left(cds->cda, bsz); + if (cont_left == bsz) { + ret = ida_read_next_idaw(cds); + if (ret) { + goto err; + } + if (cds->cda & (bsz - 1)) { + ret = -EINVAL; /* channel program check */ + goto err; + } + } + } + do { + iter_len = MIN(len, cont_left); + if (op != CDS_OP_A) { + ret = address_space_rw(&address_space_memory, cds->cda, + MEMTXATTRS_UNSPECIFIED, buff, iter_len, op); + if (ret != MEMTX_OK) { + /* assume inaccessible address */ + ret = -EINVAL; /* channel program check */ + goto err; + } + } + cds->at_byte += iter_len; + cds->cda += iter_len; + len -= iter_len; + if (!len) { + break; + } + ret = ida_read_next_idaw(cds); + if (ret) { + goto err; + } + cont_left = bsz; + } while (true); + return ret; +err: + cds->flags |= CDS_F_STREAM_BROKEN; + return ret; +} + void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb) { /* @@ -849,7 +961,7 @@ void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb) if (!(cds->flags & CDS_F_IDA)) { cds->op_handler = ccw_dstream_rw_noflags; } else { - assert(false); + cds->op_handler = ccw_dstream_rw_ida; } } -- cgit v1.2.3 From c1843e20924c9f79c8233ea34db31f3ae2a74677 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 28 Sep 2017 15:18:31 +0200 Subject: Revert "s390x/ccw: create s390 phb conditionally" This reverts commit d32bd032d8fde41281aae34c16a4aa97e9acfeac. Turns out that old QEMUs always created a pci host bridge and for many CPU models the migration from old QEMUs to new QEMUs will fail with qemu-system-s390x: Unknown savevm section or instance 'PCIBUS' 0 qemu-system-s390x: load of migration failed: Invalid argument As a quick fix we will revert the commit and always create the pci host bridge. Signed-off-by: Christian Borntraeger [fixed revert to keep the comment fixup, added a comment in the code] Cc: Cornelia Huck Cc: David Hildenbrand Message-Id: <20170928131831.81393-1-borntraeger@de.ibm.com> Reviewed-by: David Hildenbrand Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 1bcb7000ab..2c689d50bc 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -251,6 +251,7 @@ static void ccw_init(MachineState *machine) { int ret; VirtualCssBus *css_bus; + DeviceState *dev; s390_sclp_init(); s390_memory_init(machine->ram_size); @@ -266,13 +267,14 @@ static void ccw_init(MachineState *machine) machine->initrd_filename, "s390-ccw.img", "s390-netboot.img", true); - 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); - } + /* + * We cannot easily make the pci host bridge conditional as older QEMUs + * always created it. Doing so would break migration across QEMU versions. + */ + 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(); -- cgit v1.2.3 From 1baa2eb01e349889a25f7a038e6ae7c335f6246b Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Wed, 20 Sep 2017 19:23:13 +0200 Subject: s390x/3270: IDA support for 3270 via CcwDataStream Let us convert the 3270 code so it uses the recently introduced CcwDataStream abstraction instead of blindly assuming direct data access. This patch does not change behavior beyond introducing IDA support: for direct data access CCWs everything stays as-is. (If there are bugs, they are also preserved). Signed-off-by: Halil Pasic Acked-by: Christian Borntraeger Reviewed-by: Dong Jia Shi Message-Id: <20170920172314.102710-2-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck --- hw/s390x/3270-ccw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c index 1554aa2484..eaca28e224 100644 --- a/hw/s390x/3270-ccw.c +++ b/hw/s390x/3270-ccw.c @@ -28,7 +28,7 @@ static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw) return -EFAULT; } - len = ck->read_payload_3270(dev, ccw->cda, ccw->count); + len = ck->read_payload_3270(dev); ccw_dev->sch->curr_status.scsw.count = ccw->count - len; return 0; @@ -45,7 +45,7 @@ static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw) return -EFAULT; } - len = ck->write_payload_3270(dev, ccw->cmd_code, ccw->cda, ccw->count); + len = ck->write_payload_3270(dev, ccw->cmd_code); if (len <= 0) { return -EIO; -- cgit v1.2.3 From c5b934303cf83fe3dda31e8d3e5778458c8a9eeb Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Sep 2017 15:46:06 +0200 Subject: s390x: raise CPU hotplug irq after really hotplugged Let's move it into the machine, so we trigger the IRQ after setting ms->possible_cpus (which SCLP uses to construct the list of online CPUs). This also fixes a problem reported by Thomas Huth, whereby qemu can be crashed using the none machine qemu-s390x-softmmu -M none -monitor stdio -> device_add qemu-s390-cpu Reviewed-by: Christian Borntraeger Reviewed-by: Richard Henderson Signed-off-by: David Hildenbrand Message-Id: <20170928134609.16985-3-david@redhat.com> Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 2c689d50bc..679a1a858c 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -307,6 +307,10 @@ static void s390_cpu_plug(HotplugHandler *hotplug_dev, g_assert(!ms->possible_cpus->cpus[cpu->env.core_id].cpu); ms->possible_cpus->cpus[cpu->env.core_id].cpu = OBJECT(dev); + + if (dev->hotplugged) { + raise_irq_cpu_hotplug(); + } } static void s390_machine_reset(void) -- cgit v1.2.3 From f42dc44a1481949e900cd50846a42c60d756758e Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 28 Sep 2017 15:46:09 +0200 Subject: s390x: introduce and use S390_MAX_CPUS Will be handy in the future. Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Signed-off-by: David Hildenbrand Message-Id: <20170928134609.16985-6-david@redhat.com> Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 679a1a858c..14a0545e6f 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -423,7 +423,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) mc->no_parallel = 1; mc->no_sdcard = 1; mc->use_sclp = 1; - mc->max_cpus = 248; + mc->max_cpus = S390_MAX_CPUS; mc->has_hotpluggable_cpus = true; mc->get_hotplug_handler = s390_get_hotplug_handler; mc->cpu_index_to_instance_props = s390_cpu_index_to_props; -- cgit v1.2.3 From bd2aef10653e8ad1b61d9a56d3056b8b83cda389 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 4 Oct 2017 10:51:49 +0200 Subject: s390x: sort some devices into categories Add missing categorizations for some s390x devices: - zpci device -> misc - 3270 -> display - vfio-ccw -> misc Acked-by: Christian Borntraeger Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- hw/s390x/3270-ccw.c | 1 + hw/s390x/s390-pci-bus.c | 1 + 2 files changed, 2 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c index eaca28e224..081e3ef6f4 100644 --- a/hw/s390x/3270-ccw.c +++ b/hw/s390x/3270-ccw.c @@ -160,6 +160,7 @@ static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data) dc->bus_type = TYPE_VIRTUAL_CSS_BUS; dc->realize = emulated_ccw_3270_realize; dc->hotpluggable = false; + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); } static const TypeInfo emulated_ccw_3270_info = { diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 3b9965fde0..96116b7d1e 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -1032,6 +1032,7 @@ static void s390_pci_device_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->desc = "zpci device"; + set_bit(DEVICE_CATEGORY_MISC, dc->categories); dc->reset = s390_pci_device_reset; dc->bus_type = TYPE_S390_PCI_BUS; dc->realize = s390_pci_device_realize; -- cgit v1.2.3 From 489c909f097a387eb6913c89cf1851750397110c Mon Sep 17 00:00:00 2001 From: Halil Pasic Date: Wed, 4 Oct 2017 13:01:09 +0200 Subject: s390x/css: fix css migration compat handling Commit e996583eb3 ("s390x/css: activate ChannelSubSys migration", 2017-07-11) was supposed to enable css migration for virtio-ccw machines starting 2.10, but it ended up effectively enabling it only for 2.10 as the registration of the appropriate VMStateDescription happens in ccw_machine_2_10_instance_options which does not get called for machines more recent than 2_10. Let us move the corresponding chunk of code (which conditionally enables the migration based on the value of the corresponding class property) to ccw_init, which is called for each virtio-ccw machine instance. Signed-off-by: Halil Pasic Reported-by: Thomas Huth Message-Id: <20171004110109.16525-1-pasic@linux.vnet.ibm.com> Tested-by: Christian Borntraeger Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 14a0545e6f..76156ce873 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -291,6 +291,9 @@ static void ccw_init(MachineState *machine) ret = css_create_css_image(VIRTUAL_CSSID, true); } assert(ret == 0); + if (css_migration_enabled()) { + css_register_vmstate(); + } /* Create VirtIO network adapters */ s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); @@ -715,9 +718,6 @@ 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(); - } } static void ccw_machine_2_10_class_options(MachineClass *mc) -- cgit v1.2.3 From 28f8dbe85db3d28f0ecddb48c072533fe58a70ea Mon Sep 17 00:00:00 2001 From: "Collin L. Walling" Date: Wed, 4 Oct 2017 12:57:51 +0200 Subject: s390/kvm: make TOD setting failures fatal for migration If we fail to set a proper TOD clock on the target system, this can already result in some problematic cases. We print several warn messages on source and target in that case. If kvm fails to set a nonzero epoch index, then we must ultimately fail the migration as this will result in a giant time leap backwards. This patch lets the migration fail if we can not set the guest time on the target. On failure the guest will resume normally on the original host machine. Signed-off-by: Collin L. Walling Reviewed-by: Eric Farman Reviewed-by: Claudio Imbrenda Signed-off-by: Christian Borntraeger [split failure change from epoch index change, minor fixups] Message-Id: <20171004105751.24655-3-borntraeger@de.ibm.com> Reviewed-by: Thomas Huth Signed-off-by: Cornelia Huck --- hw/s390x/s390-virtio-ccw.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'hw/s390x') diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 76156ce873..32d3f11d8a 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -189,13 +189,10 @@ static int gtod_load(QEMUFile *f, void *opaque, int version_id) r = s390_set_clock(&tod_high, &tod_low); if (r) { - warn_report("Unable to set guest clock for migration: %s", - strerror(-r)); - error_printf("Guest clock will not be restored " - "which could cause the guest to hang."); + error_report("Unable to set KVM guest TOD clock: %s", strerror(-r)); } - return 0; + return r; } static SaveVMHandlers savevm_gtod = { -- cgit v1.2.3 From e6cb60bf158fe7ea4505d760fdbb7abe4dbf4362 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 4 Oct 2017 15:53:19 +0200 Subject: s390x/sclp: Mark the sclp device with user_creatable = false The "sclp" device is just an internal device that can not be instantiated by the users. If they try to use it, they only get a simple error message: $ qemu-system-s390x -nographic -device sclp qemu-system-s390x: Option '-device s390-sclp-event-facility' cannot be handled by this machine Since sclp_init() tries to create a TYPE_SCLP_EVENT_FACILITY which is a non-pluggable sysbus device, there is really no way that the "sclp" device can be used by the user, so let's set the user_creatable = false accordingly. Signed-off-by: Thomas Huth Message-Id: <1507125199-22562-1-git-send-email-thuth@redhat.com> Reviewed-by: Claudio Imbrenda Reviewed-by: Farhan Ali Acked-by: Halil Pasic Signed-off-by: Cornelia Huck --- hw/s390x/sclp.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c index 30aefbfd15..9be0cb80ad 100644 --- a/hw/s390x/sclp.c +++ b/hw/s390x/sclp.c @@ -606,6 +606,11 @@ static void sclp_class_init(ObjectClass *oc, void *data) dc->realize = sclp_realize; dc->hotpluggable = false; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + /* + * Reason: Creates TYPE_SCLP_EVENT_FACILITY in sclp_init + * which is a non-pluggable sysbus device + */ + dc->user_creatable = false; sc->read_SCP_info = read_SCP_info; sc->read_storage_element0_info = read_storage_element0_info; -- cgit v1.2.3 From 7aa4d85d2962a072931657bee964113727ebf0c8 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 4 Oct 2017 17:34:23 +0200 Subject: s390x/sclp: mark sclp-cpu-hotplug as non-usercreatable A TYPE_SCLP_CPU_HOTPLUG device for handling cpu hotplug events is already created by the sclp event facility. Adding a second TYPE_SCLP_CPU_HOTPLUG device via -device sclp-cpu-hotplug creates an ambiguity in raise_irq_cpu_hotplug(), leading to a crash once a cpu is hotplugged. To fix this, disallow creating a sclp-cpu-hotplug device manually. Reviewed-by: Thomas Huth Acked-by: Christian Borntraeger Signed-off-by: Cornelia Huck --- hw/s390x/sclpcpu.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'hw/s390x') diff --git a/hw/s390x/sclpcpu.c b/hw/s390x/sclpcpu.c index 023d059a46..3ee890b392 100644 --- a/hw/s390x/sclpcpu.c +++ b/hw/s390x/sclpcpu.c @@ -82,6 +82,12 @@ static void cpu_class_init(ObjectClass *oc, void *data) k->get_receive_mask = receive_mask; k->read_event_data = read_event_data; set_bit(DEVICE_CATEGORY_MISC, dc->categories); + /* + * Reason: raise_irq_cpu_hotplug() depends on an unique + * TYPE_SCLP_CPU_HOTPLUG device, which is already created + * by the sclp event facility + */ + dc->user_creatable = false; } static const TypeInfo sclp_cpu_info = { -- cgit v1.2.3 From b923ab3112ed5ab47c2ff35776f17ab54c60d651 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 5 Oct 2017 10:45:05 +0200 Subject: hw/s390x: Mark the "sclpquiesce" device with user_creatable = false The "sclpquiesce" device is just an internal device that should not be created by the user directly. Though it currently does not seem to cause any obvious trouble when the user instantiates an additional device, let's better mark it with user_creatable = false to avoid unexpected behavior, e.g. because the quiesce notifier gets registered multiple times. Signed-off-by: Thomas Huth Message-Id: <1507193105-15627-1-git-send-email-thuth@redhat.com> Reviewed-by: Halil Pasic Reviewed-by: Claudio Imbrenda Signed-off-by: Cornelia Huck --- hw/s390x/sclpquiesce.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'hw/s390x') diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c index 762cb184ac..02416435a1 100644 --- a/hw/s390x/sclpquiesce.c +++ b/hw/s390x/sclpquiesce.c @@ -118,8 +118,13 @@ static void quiesce_class_init(ObjectClass *klass, void *data) dc->reset = quiesce_reset; dc->vmsd = &vmstate_sclpquiesce; set_bit(DEVICE_CATEGORY_MISC, dc->categories); - k->init = quiesce_init; + /* + * Reason: This is just an internal device - the notifier should + * not be registered multiple times in quiesce_init() + */ + dc->user_creatable = false; + k->init = quiesce_init; k->get_send_mask = send_mask; k->get_receive_mask = receive_mask; k->can_handle_event = can_handle_event; -- cgit v1.2.3