diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/3270-ccw.c | 1 | ||||
-rw-r--r-- | hw/s390x/css.c | 87 | ||||
-rw-r--r-- | hw/s390x/s390-ccw.c | 1 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 3 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 1 | ||||
-rw-r--r-- | hw/vfio/ccw.c | 4 |
6 files changed, 73 insertions, 24 deletions
diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c index 13e93d8..69e6783 100644 --- a/hw/s390x/3270-ccw.c +++ b/hw/s390x/3270-ccw.c @@ -129,6 +129,7 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp) EMULATED_CCW_3270_CHPID_TYPE); sch->do_subchannel_work = do_subchannel_work_virtual; sch->ccw_cb = emulated_ccw_3270_cb; + sch->irb_cb = build_irb_virtual; ck->init(dev, &err); if (err) { diff --git a/hw/s390x/css.c b/hw/s390x/css.c index bed46f5..133ddea 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1335,6 +1335,14 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src) } } +void copy_esw_to_guest(ESW *dest, const ESW *src) +{ + dest->word0 = cpu_to_be32(src->word0); + dest->erw = cpu_to_be32(src->erw); + dest->word2 = cpu_to_be64(src->word2); + dest->word4 = cpu_to_be32(src->word4); +} + IOInstEnding css_do_stsch(SubchDev *sch, SCHIB *schib) { int ret; @@ -1604,9 +1612,8 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw, copy_scsw_to_guest(&dest->scsw, &src->scsw); - for (i = 0; i < ARRAY_SIZE(dest->esw); i++) { - dest->esw[i] = cpu_to_be32(src->esw[i]); - } + copy_esw_to_guest(&dest->esw, &src->esw); + for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) { dest->ecw[i] = cpu_to_be32(src->ecw[i]); } @@ -1632,6 +1639,55 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw, *irb_len = sizeof(*dest); } +static void build_irb_sense_data(SubchDev *sch, IRB *irb) +{ + int i; + + /* Attention: sense_data is already BE! */ + memcpy(irb->ecw, sch->sense_data, sizeof(sch->sense_data)); + for (i = 0; i < ARRAY_SIZE(irb->ecw); i++) { + irb->ecw[i] = be32_to_cpu(irb->ecw[i]); + } +} + +void build_irb_passthrough(SubchDev *sch, IRB *irb) +{ + /* Copy ESW from hardware */ + irb->esw = sch->esw; + + /* + * If (irb->esw.erw & ESW_ERW_SENSE) is true, then the contents + * of the ECW is sense data. If false, then it is model-dependent + * information. Either way, copy it into the IRB for the guest to + * read/decide what to do with. + */ + build_irb_sense_data(sch, irb); +} + +void build_irb_virtual(SubchDev *sch, IRB *irb) +{ + SCHIB *schib = &sch->curr_status; + uint16_t stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL; + + if (stctl & SCSW_STCTL_STATUS_PEND) { + if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK | + SCSW_CSTAT_CHN_CTRL_CHK | + SCSW_CSTAT_INTF_CTRL_CHK)) { + irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF; + irb->esw.word0 = 0x04804000; + } else { + irb->esw.word0 = 0x00800000; + } + /* If a unit check is pending, copy sense data. */ + if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) && + (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) { + irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL; + build_irb_sense_data(sch, irb); + irb->esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8); + } + } +} + int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len) { SCHIB *schib = &sch->curr_status; @@ -1650,29 +1706,12 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len) /* Copy scsw from current status. */ irb.scsw = schib->scsw; - if (stctl & SCSW_STCTL_STATUS_PEND) { - if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK | - SCSW_CSTAT_CHN_CTRL_CHK | - SCSW_CSTAT_INTF_CTRL_CHK)) { - irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF; - irb.esw[0] = 0x04804000; - } else { - irb.esw[0] = 0x00800000; - } - /* If a unit check is pending, copy sense data. */ - if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) && - (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) { - int i; - irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL; - /* Attention: sense_data is already BE! */ - memcpy(irb.ecw, sch->sense_data, sizeof(sch->sense_data)); - for (i = 0; i < ARRAY_SIZE(irb.ecw); i++) { - irb.ecw[i] = be32_to_cpu(irb.ecw[i]); - } - irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8); - } + /* Build other IRB data, if necessary */ + if (sch->irb_cb) { + sch->irb_cb(sch, &irb); } + /* Store the irb to the guest. */ p = schib->pmcw; copy_irb_to_guest(target_irb, &irb, &p, irb_len); diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index c227c77..2fc8bb9 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -124,6 +124,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp) } sch->driver_data = cdev; sch->do_subchannel_work = do_subchannel_work_passthrough; + sch->irb_cb = build_irb_passthrough; ccw_dev->sch = sch; ret = css_sch_build_schib(sch, &cdev->hostid); diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 7af27ca..e4b18ae 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -802,7 +802,10 @@ DEFINE_CCW_MACHINE(6_1, "6.1", true); static void ccw_machine_6_0_instance_options(MachineState *machine) { + static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_0 }; + ccw_machine_6_1_instance_options(machine); + s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat); } static void ccw_machine_6_0_class_options(MachineClass *mc) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 220b9ef..d68888f 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -753,6 +753,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) sch->id.reserved = 0xff; sch->id.cu_type = VIRTIO_CCW_CU_TYPE; sch->do_subchannel_work = do_subchannel_work_virtual; + sch->irb_cb = build_irb_virtual; ccw_dev->sch = sch; dev->indicators = NULL; dev->revision = -1; diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 139a3d9..000992f 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -321,6 +321,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque) SCHIB *schib = &sch->curr_status; SCSW s; IRB irb; + ESW esw; int size; if (!event_notifier_test_and_clear(&vcdev->io_notifier)) { @@ -371,6 +372,9 @@ static void vfio_ccw_io_notifier_handler(void *opaque) copy_scsw_to_guest(&s, &irb.scsw); schib->scsw = s; + copy_esw_to_guest(&esw, &irb.esw); + sch->esw = esw; + /* If a uint check is pending, copy sense data. */ if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) && (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) { |