diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2014-09-23 13:28:06 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2014-09-23 13:28:06 +0100 |
commit | cad684c5386ea01cd725418ff678d54af74068c3 (patch) | |
tree | 8af6051b9e8d8fa77ecd5e76e5bc393384137d1f /hw | |
parent | 380f649e02f9545159dc3158d7c1b2e70c1005e3 (diff) | |
parent | e8601dd5d0ffa909068ddefe33bf6a53d8af063a (diff) |
Merge remote-tracking branch 'remotes/borntraeger/tags/s390x-20140923' into staging
s390x/kvm: some fixes and cleanups
1. sclp: get of of duplicate defines
2. ccw: implement and fix handling of some special cases
# gpg: Signature made Tue 23 Sep 2014 13:10:47 BST using RSA key ID B5A61C7C
# gpg: Can't check signature: public key not found
* remotes/borntraeger/tags/s390x-20140923:
s390x/css: catch ccw sequence errors
s390x/css: support format-0 ccws
s390x: remove duplicate defines in SCLP code
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/css.c | 40 | ||||
-rw-r--r-- | hw/s390x/css.h | 2 |
2 files changed, 33 insertions, 9 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 49c2aaff1f..b67c039a70 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -243,17 +243,25 @@ static void copy_sense_id_to_guest(SenseId *dest, SenseId *src) } } -static CCW1 copy_ccw_from_guest(hwaddr addr) +static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1) { - CCW1 tmp; + CCW0 tmp0; + CCW1 tmp1; CCW1 ret; - cpu_physical_memory_read(addr, &tmp, sizeof(tmp)); - ret.cmd_code = tmp.cmd_code; - ret.flags = tmp.flags; - ret.count = be16_to_cpu(tmp.count); - ret.cda = be32_to_cpu(tmp.cda); - + if (fmt1) { + cpu_physical_memory_read(addr, &tmp1, sizeof(tmp1)); + ret.cmd_code = tmp1.cmd_code; + ret.flags = tmp1.flags; + ret.count = be16_to_cpu(tmp1.count); + 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); + } return ret; } @@ -268,7 +276,8 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) return -EIO; } - ccw = copy_ccw_from_guest(ccw_addr); + /* Translate everything to format-1 ccws - the information is the same. */ + ccw = copy_ccw_from_guest(ccw_addr, sch->ccw_fmt_1); /* Check for invalid command codes. */ if ((ccw.cmd_code & 0x0f) == 0) { @@ -285,6 +294,13 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr) check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); + if (!ccw.cda) { + if (sch->ccw_no_data_cnt == 255) { + return -EINVAL; + } + sch->ccw_no_data_cnt++; + } + /* Look at the command. */ switch (ccw.cmd_code) { case CCW_CMD_NOOP: @@ -386,6 +402,8 @@ static void sch_handle_start_func(SubchDev *sch, ORB *orb) s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND); return; } + sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT); + sch->ccw_no_data_cnt = 0; } else { s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND); } @@ -1347,6 +1365,8 @@ void subch_device_save(SubchDev *s, QEMUFile *f) qemu_put_byte(f, s->id.ciw[i].command); qemu_put_be16(f, s->id.ciw[i].count); } + qemu_put_byte(f, s->ccw_fmt_1); + qemu_put_byte(f, s->ccw_no_data_cnt); return; } @@ -1402,6 +1422,8 @@ int subch_device_load(SubchDev *s, QEMUFile *f) s->id.ciw[i].command = qemu_get_byte(f); s->id.ciw[i].count = qemu_get_be16(f); } + s->ccw_fmt_1 = qemu_get_byte(f); + s->ccw_no_data_cnt = qemu_get_byte(f); return 0; } diff --git a/hw/s390x/css.h b/hw/s390x/css.h index c864ea765b..33104ac58e 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -76,7 +76,9 @@ struct SubchDev { hwaddr channel_prog; CCW1 last_cmd; bool last_cmd_valid; + bool ccw_fmt_1; bool thinint_active; + uint8_t ccw_no_data_cnt; /* transport-provided data: */ int (*ccw_cb) (SubchDev *, CCW1); SenseId id; |