From 85fa94e16927af2717093e5b8fe225206ec39e16 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 6 May 2019 19:11:48 +0200 Subject: [PATCH] s390/css: handle CCW_FLAG_SKIP If a ccw has CCW_FLAG_SKIP set, and the command is of type read, read backwards, or sense, no data should be written to the guest for that command. Reviewed-by: Eric Farman Message-Id: <20190516133327.11430-1-cohuck@redhat.com> Signed-off-by: Cornelia Huck --- hw/s390x/css.c | 22 ++++++++++++++++++---- include/hw/s390x/css.h | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 8fc9e35ba5..ad310b9f94 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -830,8 +830,12 @@ static int ccw_dstream_rw_noflags(CcwDataStream *cds, void *buff, int len, if (op == CDS_OP_A) { goto incr; } - ret = address_space_rw(&address_space_memory, cds->cda, - MEMTXATTRS_UNSPECIFIED, buff, len, op); + if (!cds->do_skip) { + ret = address_space_rw(&address_space_memory, cds->cda, + MEMTXATTRS_UNSPECIFIED, buff, len, op); + } else { + ret = MEMTX_OK; + } if (ret != MEMTX_OK) { cds->flags |= CDS_F_STREAM_BROKEN; return -EINVAL; @@ -928,8 +932,13 @@ static int ccw_dstream_rw_ida(CcwDataStream *cds, void *buff, int len, 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 (!cds->do_skip) { + ret = address_space_rw(&address_space_memory, cds->cda, + MEMTXATTRS_UNSPECIFIED, buff, iter_len, + op); + } else { + ret = MEMTX_OK; + } if (ret != MEMTX_OK) { /* assume inaccessible address */ ret = -EINVAL; /* channel program check */ @@ -968,6 +977,11 @@ void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb) cds->count = ccw->count; cds->cda_orig = ccw->cda; + /* skip is only effective for read, read backwards, or sense commands */ + cds->do_skip = (ccw->flags & CCW_FLAG_SKIP) && + ((ccw->cmd_code & 0x0f) == CCW_CMD_BASIC_SENSE || + (ccw->cmd_code & 0x03) == 0x02 /* read */ || + (ccw->cmd_code & 0x0f) == 0x0c /* read backwards */); ccw_dstream_rewind(cds); if (!(cds->flags & CDS_F_IDA)) { cds->op_handler = ccw_dstream_rw_noflags; diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h index aae19c4272..7cc183ef43 100644 --- a/include/hw/s390x/css.h +++ b/include/hw/s390x/css.h @@ -97,6 +97,7 @@ typedef struct CcwDataStream { int (*op_handler)(struct CcwDataStream *cds, void *buff, int len, CcwDataStreamOp op); hwaddr cda; + bool do_skip; } CcwDataStream; /* -- 2.11.4.GIT