On Tue, 7 May 2019 11:31:16 -0400 Eric Farman <far...@linux.ibm.com> wrote:
> On 5/7/19 5:08 AM, Pierre Morel wrote: > > On 07/05/2019 10:12, Cornelia Huck wrote: > >> 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. > >> > >> Signed-off-by: Cornelia Huck <coh...@redhat.com> > >> --- > >> > >> v1 -> v2: fixed checks for command type [Eric] > >> > >> Still only lightly tested (it boots); I don't think I have a tool > >> generating channel programs with the skip flag handy. > > FWIW, my test program hits this code once (read of a single page, with > SLI and SKIP flags set) before getting into the passthrough codepath. Ah, good. > > >> > >> --- > >> 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 8fc9e35ba5d3..080ac7e5bc0b 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 = 0; > >> + } > >> 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 = 0; > >> + } > >> 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 & CCW_CMD_BASIC_SENSE) == CCW_CMD_BASIC_SENSE || > >> + (ccw->cmd_code & 0x02) == 0x02 /* read */ || > >> + (ccw->cmd_code & 0x0c) == 0x0c /* read backwards */); > > > > I think you should use masks like > > ((code & 0x3) == 2) => READ > > ((code & 0xf) == 0xc) => READ BACKWARD > > ((code & 0xf) == 0x4) => SENSE > > I think Pierre is right. In the v2 code, a control CCW (like NOP) would > still be flagged as a READ. Sigh. I hope third time's the charm.