diff mbox series

[v1,1/1] s390x: css: report errors from ccw_dstream_read/write

Message ID 1617695053-7328-2-git-send-email-pmorel@linux.ibm.com
State New
Headers show
Series s390x: css: report errors from ccw_dstream_read/write | expand

Commit Message

Pierre Morel April 6, 2021, 7:44 a.m. UTC
ccw_dstream_read/write functions returned values are sometime
not taking into account and reported back to the upper level
of interpretation of CCW instructions.

It follows that accessing an invalid address does not trigger
a subchannel status program check to the guest as it should.

Let's test the return values of ccw_dstream_write[_buf] and
ccw_dstream_read[_buf] and report it to the caller.

Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
 hw/char/terminal3270.c | 11 +++++--
 hw/s390x/3270-ccw.c    |  3 ++
 hw/s390x/css.c         | 16 +++++-----
 hw/s390x/virtio-ccw.c  | 66 ++++++++++++++++++++++++++++++------------
 4 files changed, 69 insertions(+), 27 deletions(-)

Comments

Cornelia Huck April 6, 2021, 3:03 p.m. UTC | #1
On Tue,  6 Apr 2021 09:44:13 +0200
Pierre Morel <pmorel@linux.ibm.com> wrote:

> ccw_dstream_read/write functions returned values are sometime
> not taking into account and reported back to the upper level
> of interpretation of CCW instructions.
> 
> It follows that accessing an invalid address does not trigger
> a subchannel status program check to the guest as it should.
> 
> Let's test the return values of ccw_dstream_write[_buf] and
> ccw_dstream_read[_buf] and report it to the caller.

Yes, checking/propagating the return code is something that was missing
in several places.

> 
> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
> ---
>  hw/char/terminal3270.c | 11 +++++--
>  hw/s390x/3270-ccw.c    |  3 ++
>  hw/s390x/css.c         | 16 +++++-----
>  hw/s390x/virtio-ccw.c  | 66 ++++++++++++++++++++++++++++++------------
>  4 files changed, 69 insertions(+), 27 deletions(-)
> 
> diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
> index a9a46c8ed3..82e85fac2e 100644
> --- a/hw/char/terminal3270.c
> +++ b/hw/char/terminal3270.c
> @@ -200,9 +200,13 @@ static int read_payload_3270(EmulatedCcw3270Device *dev)
>  {
>      Terminal3270 *t = TERMINAL_3270(dev);
>      int len;
> +    int ret;
>  
>      len = MIN(ccw_dstream_avail(get_cds(t)), t->in_len);
> -    ccw_dstream_write_buf(get_cds(t), t->inv, len);
> +    ret = ccw_dstream_write_buf(get_cds(t), t->inv, len);
> +    if (ret < 0) {
> +        return ret;
> +    }

This looks correct: together with the change below, you end up
propagating a negative error value to the ccw callback handling.

>      t->in_len -= len;
>  
>      return len;
> @@ -260,7 +264,10 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd)
>  
>      t->outv[out_len++] = cmd;
>      do {
> -        ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
> +        retval = ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
> +        if (retval < 0) {
> +            return retval;

Here, however, I'm not sure. Returning a negative error here is fine,
but handle_payload_3270_write (not changed in this patch) seems to
match everything to -EIO. Shouldn't it just be propagated, and maybe 0
mapped to -EIO only? If I'm not confused, we'll end up mapping every
error to intervention required.

> +        }
>          count = ccw_dstream_avail(get_cds(t));
>          out_len += len;
>  
> diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
> index 821319eee6..cc1371f01c 100644
> --- a/hw/s390x/3270-ccw.c
> +++ b/hw/s390x/3270-ccw.c
> @@ -31,6 +31,9 @@ static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
>      }
>  
>      len = ck->read_payload_3270(dev);
> +    if (len < 0) {
> +        return len;
> +    }
>      ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
>  
>      return 0;
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index fe47751df4..99e476f193 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -1055,10 +1055,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
>              }
>          }
>          len = MIN(ccw.count, sizeof(sch->sense_data));
> -        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;
> +        ret = ccw_dstream_write_buf(&sch->cds, sch->sense_data, len);
> +        if (!ret) {
> +            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);

I'm wondering about the residual count here. Table 16-7 "Contents of
Count Field in SCSW" in the PoP looks a bit more complicated for some
error conditions, especially if IDALs are involved. Not sure if we
should attempt to write something to count in those conditions; but on
the other hand, I don't think our error conditions are as complex
anyway, and we can make this simplification.

> +            memset(sch->sense_data, 0, sizeof(sch->sense_data));
> +        }
>          break;
>      case CCW_CMD_SENSE_ID:
>      {
> @@ -1083,9 +1084,10 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
>          } else {
>              sense_id[0] = 0;
>          }
> -        ccw_dstream_write_buf(&sch->cds, sense_id, len);
> -        sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
> -        ret = 0;
> +        ret = ccw_dstream_write_buf(&sch->cds, sense_id, len);
> +        if (!ret) {
> +            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
> +        }
>          break;
>      }
>      case CCW_CMD_TIC:

(...)

Otherwise, looks good.
Pierre Morel April 7, 2021, 11:41 a.m. UTC | #2
On 4/6/21 5:03 PM, Cornelia Huck wrote:
> On Tue,  6 Apr 2021 09:44:13 +0200
> Pierre Morel <pmorel@linux.ibm.com> wrote:
> 
>> ccw_dstream_read/write functions returned values are sometime
>> not taking into account and reported back to the upper level
>> of interpretation of CCW instructions.
>>
>> It follows that accessing an invalid address does not trigger
>> a subchannel status program check to the guest as it should.
>>
>> Let's test the return values of ccw_dstream_write[_buf] and
>> ccw_dstream_read[_buf] and report it to the caller.
> 
> Yes, checking/propagating the return code is something that was missing
> in several places.
> 
>>
>> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
>> ---
>>   hw/char/terminal3270.c | 11 +++++--
>>   hw/s390x/3270-ccw.c    |  3 ++
>>   hw/s390x/css.c         | 16 +++++-----
>>   hw/s390x/virtio-ccw.c  | 66 ++++++++++++++++++++++++++++++------------
>>   4 files changed, 69 insertions(+), 27 deletions(-)
>>
>> diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
>> index a9a46c8ed3..82e85fac2e 100644
>> --- a/hw/char/terminal3270.c
>> +++ b/hw/char/terminal3270.c
>> @@ -200,9 +200,13 @@ static int read_payload_3270(EmulatedCcw3270Device *dev)
>>   {
>>       Terminal3270 *t = TERMINAL_3270(dev);
>>       int len;
>> +    int ret;
>>   
>>       len = MIN(ccw_dstream_avail(get_cds(t)), t->in_len);
>> -    ccw_dstream_write_buf(get_cds(t), t->inv, len);
>> +    ret = ccw_dstream_write_buf(get_cds(t), t->inv, len);
>> +    if (ret < 0) {
>> +        return ret;
>> +    }
> 
> This looks correct: together with the change below, you end up
> propagating a negative error value to the ccw callback handling.
> 
>>       t->in_len -= len;
>>   
>>       return len;
>> @@ -260,7 +264,10 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd)
>>   
>>       t->outv[out_len++] = cmd;
>>       do {
>> -        ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
>> +        retval = ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
>> +        if (retval < 0) {
>> +            return retval;
> 
> Here, however, I'm not sure. Returning a negative error here is fine,
> but handle_payload_3270_write (not changed in this patch) seems to
> match everything to -EIO. Shouldn't it just be propagated, and maybe 0
> mapped to -EIO only? If I'm not confused, we'll end up mapping every
> error to intervention required.

I know very little about the 3270 but in my opinion accessing memory is 
not the problem of the device but of the subchannel.
So we should certainly propagate the error instead of returning -EIO for 
any error.

---> what about

diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
index cc1371f01c..f3e7342b1e 100644
--- a/hw/s390x/3270-ccw.c
+++ b/hw/s390x/3270-ccw.c
@@ -53,7 +53,7 @@ static int 
handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
      len = ck->write_payload_3270(dev, ccw->cmd_code);

      if (len <= 0) {
-        return -EIO;
+        return len ? len : -EIO;
      }

      ccw_dev->sch->curr_status.scsw.count = ccw->count - len;

-----------------

> 
>> +        }
>>           count = ccw_dstream_avail(get_cds(t));
>>           out_len += len;
>>   
>> diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
>> index 821319eee6..cc1371f01c 100644
>> --- a/hw/s390x/3270-ccw.c
>> +++ b/hw/s390x/3270-ccw.c
>> @@ -31,6 +31,9 @@ static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
>>       }
>>   
>>       len = ck->read_payload_3270(dev);
>> +    if (len < 0) {
>> +        return len;
>> +    }
>>       ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
>>   
>>       return 0;
>> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
>> index fe47751df4..99e476f193 100644
>> --- a/hw/s390x/css.c
>> +++ b/hw/s390x/css.c
>> @@ -1055,10 +1055,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
>>               }
>>           }
>>           len = MIN(ccw.count, sizeof(sch->sense_data));
>> -        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;
>> +        ret = ccw_dstream_write_buf(&sch->cds, sch->sense_data, len);
>> +        if (!ret) {
>> +            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
> 
> I'm wondering about the residual count here. Table 16-7 "Contents of
> Count Field in SCSW" in the PoP looks a bit more complicated for some
> error conditions, especially if IDALs are involved. Not sure if we
> should attempt to write something to count in those conditions; but on
> the other hand, I don't think our error conditions are as complex
> anyway, and we can make this simplification.

I think you are right.
ccw_dstream_residual_count() should know what to do return there and we 
should not ignore it.

On the other hand erasing should only be done if all went OK because a 
following sense, with the right parameters, may succeed.
What do you think?


> 
>> +            memset(sch->sense_data, 0, sizeof(sch->sense_data));
>> +        }
>>           break;
>>       case CCW_CMD_SENSE_ID:
>>       {
>> @@ -1083,9 +1084,10 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
>>           } else {
>>               sense_id[0] = 0;
>>           }
>> -        ccw_dstream_write_buf(&sch->cds, sense_id, len);
>> -        sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
>> -        ret = 0;
>> +        ret = ccw_dstream_write_buf(&sch->cds, sense_id, len);
>> +        if (!ret) {
>> +            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
>> +        }
>>           break;
>>       }
>>       case CCW_CMD_TIC:
> 
> (...)
> 
> Otherwise, looks good.
> 

Thanks,
Pierre
Halil Pasic April 7, 2021, 4:54 p.m. UTC | #3
On Wed, 7 Apr 2021 13:41:57 +0200
Pierre Morel <pmorel@linux.ibm.com> wrote:

> > Here, however, I'm not sure. Returning a negative error here is fine,
> > but handle_payload_3270_write (not changed in this patch) seems to
> > match everything to -EIO. Shouldn't it just be propagated, and maybe 0
> > mapped to -EIO only? If I'm not confused, we'll end up mapping every
> > error to intervention required.  
> 
> I know very little about the 3270 but in my opinion accessing memory is 
> not the problem of the device but of the subchannel.
> So we should certainly propagate the error instead of returning -EIO for 
> any error.

I agree, what condition needs to be indicated when we encounter an
invalid CCW, IDAW or MIDAW address is clear. In the PoP this is
described under Chapter 16. I/O Interruptions > Subchannel-Status Word >
Subchannel-Status Field > Program Check in the paragraphs on "Invalid
IDAW or MIDAW Address and "Invalid CCW Address".

My guess about handle_payload_3270_write() is that IMHO the initial 3270
emulation code was, let's say of mixed quality in the first place, so
wouldn't seek some hidden meaning/sense, behind the -EIO. IMHO first
mapping architectural conditions to "errno-style" error codes, passing
these around, and then mapping them back is a litle non-intuitive. If one
looks at the purpose of handle_payload_3270_write(), it is basically
emulating an IO data transfer from the device into the main storage. If
that sort of operation. So with -EIO the original author probably wanted
to say: hey there was an input/output error, which ain't that wrong. The
problem is that somewhere up the call stack EIO gets interpreted in a
very peculiar way, and along with other errnos mapped to CIO
architecture stuff like SCSW bits.

Regards,
Halil
Halil Pasic April 7, 2021, 5:47 p.m. UTC | #4
On Tue,  6 Apr 2021 09:44:13 +0200
Pierre Morel <pmorel@linux.ibm.com> wrote:

> ccw_dstream_read/write functions returned values are sometime
> not taking into account and reported back to the upper level
> of interpretation of CCW instructions.


The return values of ccw_dstream_write/read were intentionally ignored
in commit f57ba05823 ("virtio-ccw: use ccw data stream") to avoid
changes in behavior that wound not contribute to the objective of the
patch-set, like silently doing more error checking and handling.

If we consider the first hunk:


--- 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);

we can see, that the original code did not contain any error checking regarding
the invalidity of the guest physical address.

What was the behavior there? The last argument of address_space_* where we pass
the NULL is actually an optional pointer to the MemTxResult, which would tell
us if the operation succeeded or failed. Passing NULL there means, we don't care.

My guess is that when those loads fail (or the read fails) we will just carry on
with the garbage we found on the stack.

So this begs the question, do we need this fixed for old releases as well?

My answer is yes we do. Conny what do you think?

Regards,
Halil
Cornelia Huck April 8, 2021, 8:53 a.m. UTC | #5
On Wed, 7 Apr 2021 18:54:26 +0200
Halil Pasic <pasic@linux.ibm.com> wrote:

> On Wed, 7 Apr 2021 13:41:57 +0200
> Pierre Morel <pmorel@linux.ibm.com> wrote:
> 
> > > Here, however, I'm not sure. Returning a negative error here is fine,
> > > but handle_payload_3270_write (not changed in this patch) seems to
> > > match everything to -EIO. Shouldn't it just be propagated, and maybe 0
> > > mapped to -EIO only? If I'm not confused, we'll end up mapping every
> > > error to intervention required.    
> > 
> > I know very little about the 3270 but in my opinion accessing memory is 
> > not the problem of the device but of the subchannel.
> > So we should certainly propagate the error instead of returning -EIO for 
> > any error.  
> 
> I agree, what condition needs to be indicated when we encounter an
> invalid CCW, IDAW or MIDAW address is clear. In the PoP this is
> described under Chapter 16. I/O Interruptions > Subchannel-Status Word >
> Subchannel-Status Field > Program Check in the paragraphs on "Invalid
> IDAW or MIDAW Address and "Invalid CCW Address".
> 
> My guess about handle_payload_3270_write() is that IMHO the initial 3270
> emulation code was, let's say of mixed quality in the first place, so
> wouldn't seek some hidden meaning/sense, behind the -EIO. IMHO first
> mapping architectural conditions to "errno-style" error codes, passing
> these around, and then mapping them back is a litle non-intuitive. If one
> looks at the purpose of handle_payload_3270_write(), it is basically
> emulating an IO data transfer from the device into the main storage. If
> that sort of operation. So with -EIO the original author probably wanted
> to say: hey there was an input/output error, which ain't that wrong. The
> problem is that somewhere up the call stack EIO gets interpreted in a
> very peculiar way, and along with other errnos mapped to CIO
> architecture stuff like SCSW bits.

It's not quite clear to me what the 3270 is supposed to do (I remember
some requirements for the aforementioned intervention required, but
posting unit checks does not look like the right thing to do for all of
the possible errors.)

Let's just loop the error through? I doubt that this is the last
problem in the 3270 code :) Fortunately, it is a rather obscure device
to be used with QEMU.
Cornelia Huck April 8, 2021, 9:02 a.m. UTC | #6
On Wed, 7 Apr 2021 19:47:11 +0200
Halil Pasic <pasic@linux.ibm.com> wrote:

> So this begs the question, do we need this fixed for old releases as well?
> 
> My answer is yes we do. Conny what do you think?

What do you mean with "old releases"? The dstream rework was in 2.11,
and I doubt that anyone is using anything older, or a downstream
release that is based on pre-2.11.

If you mean "include in stable", then yes, we can do that; if we want
the commit in 6.0, I need the final version soon.
Pierre Morel April 8, 2021, 12:32 p.m. UTC | #7
On 4/8/21 11:02 AM, Cornelia Huck wrote:
> On Wed, 7 Apr 2021 19:47:11 +0200
> Halil Pasic <pasic@linux.ibm.com> wrote:
> 
>> So this begs the question, do we need this fixed for old releases as well?
>>
>> My answer is yes we do. Conny what do you think?
> 
> What do you mean with "old releases"? The dstream rework was in 2.11,
> and I doubt that anyone is using anything older, or a downstream
> release that is based on pre-2.11.
> 
> If you mean "include in stable", then yes, we can do that; if we want
> the commit in 6.0, I need the final version soon.
> 
> 

OK, are you OK with the two change propositions I sent?

1) let the 3270 decide for internal errors (-EIO) but return the error 
for CSS errors in handle_payload_3270_write()

2) for senseid, always ask CSS to update the residual count
but only erase the senseid if the write succeeded
Halil Pasic April 8, 2021, 12:39 p.m. UTC | #8
On Thu, 8 Apr 2021 11:02:32 +0200
Cornelia Huck <cohuck@redhat.com> wrote:

> On Wed, 7 Apr 2021 19:47:11 +0200
> Halil Pasic <pasic@linux.ibm.com> wrote:
> 
> > So this begs the question, do we need this fixed for old releases as well?
> > 
> > My answer is yes we do. Conny what do you think?  
> 
> What do you mean with "old releases"? The dstream rework was in 2.11,
> and I doubt that anyone is using anything older, or a downstream
> release that is based on pre-2.11.
> 
> If you mean "include in stable", then yes, we can do that; if we want
> the commit in 6.0, I need the final version soon.

With old releases, I wanted to say any QEMU that is still supported by
us ;). For upstream it is backport to the stable versions currently in
support.

The commit message does not tell us if this is an enhancement or a
bugfix, stable is not mentioned, and neither do we get the information
since when is this problem existent. I simply wanted to have that
discussion.

Would it make sense to split this up into a virtio-ccw a css and a 3270
patch? That way if there was a problem with let's say 3270, we could
still keep the other two?

Regards,
Halil
Cornelia Huck April 8, 2021, 1:23 p.m. UTC | #9
On Thu, 8 Apr 2021 14:32:11 +0200
Pierre Morel <pmorel@linux.ibm.com> wrote:

> On 4/8/21 11:02 AM, Cornelia Huck wrote:
> > On Wed, 7 Apr 2021 19:47:11 +0200
> > Halil Pasic <pasic@linux.ibm.com> wrote:
> >   
> >> So this begs the question, do we need this fixed for old releases as well?
> >>
> >> My answer is yes we do. Conny what do you think?  
> > 
> > What do you mean with "old releases"? The dstream rework was in 2.11,
> > and I doubt that anyone is using anything older, or a downstream
> > release that is based on pre-2.11.
> > 
> > If you mean "include in stable", then yes, we can do that; if we want
> > the commit in 6.0, I need the final version soon.
> > 
> >   
> 
> OK, are you OK with the two change propositions I sent?
> 
> 1) let the 3270 decide for internal errors (-EIO) but return the error 
> for CSS errors in handle_payload_3270_write()
> 
> 2) for senseid, always ask CSS to update the residual count
> but only erase the senseid if the write succeeded
> 
> 

I think both make sense.
Cornelia Huck April 8, 2021, 1:26 p.m. UTC | #10
On Thu, 8 Apr 2021 14:39:59 +0200
Halil Pasic <pasic@linux.ibm.com> wrote:

> On Thu, 8 Apr 2021 11:02:32 +0200
> Cornelia Huck <cohuck@redhat.com> wrote:
> 
> > On Wed, 7 Apr 2021 19:47:11 +0200
> > Halil Pasic <pasic@linux.ibm.com> wrote:
> >   
> > > So this begs the question, do we need this fixed for old releases as well?
> > > 
> > > My answer is yes we do. Conny what do you think?    
> > 
> > What do you mean with "old releases"? The dstream rework was in 2.11,
> > and I doubt that anyone is using anything older, or a downstream
> > release that is based on pre-2.11.
> > 
> > If you mean "include in stable", then yes, we can do that; if we want
> > the commit in 6.0, I need the final version soon.  
> 
> With old releases, I wanted to say any QEMU that is still supported by
> us ;). For upstream it is backport to the stable versions currently in
> support.
> 
> The commit message does not tell us if this is an enhancement or a
> bugfix, stable is not mentioned, and neither do we get the information
> since when is this problem existent. I simply wanted to have that
> discussion.
> 
> Would it make sense to split this up into a virtio-ccw a css and a 3270
> patch? That way if there was a problem with let's say 3270, we could
> still keep the other two?

I'm not sure that makes sense; it's not too complicated.
Pierre Morel April 8, 2021, 4:18 p.m. UTC | #11
On 4/8/21 3:23 PM, Cornelia Huck wrote:
> On Thu, 8 Apr 2021 14:32:11 +0200
> Pierre Morel <pmorel@linux.ibm.com> wrote:
> 
>> On 4/8/21 11:02 AM, Cornelia Huck wrote:
>>> On Wed, 7 Apr 2021 19:47:11 +0200
>>> Halil Pasic <pasic@linux.ibm.com> wrote:
>>>    
>>>> So this begs the question, do we need this fixed for old releases as well?
>>>>
>>>> My answer is yes we do. Conny what do you think?
>>>
>>> What do you mean with "old releases"? The dstream rework was in 2.11,
>>> and I doubt that anyone is using anything older, or a downstream
>>> release that is based on pre-2.11.
>>>
>>> If you mean "include in stable", then yes, we can do that; if we want
>>> the commit in 6.0, I need the final version soon.
>>>
>>>    
>>
>> OK, are you OK with the two change propositions I sent?
>>
>> 1) let the 3270 decide for internal errors (-EIO) but return the error
>> for CSS errors in handle_payload_3270_write()
>>
>> 2) for senseid, always ask CSS to update the residual count
>> but only erase the senseid if the write succeeded
>>
>>
> 
> I think both make sense.
> 

OK I send a v2
Thanks

Pierre
diff mbox series

Patch

diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c
index a9a46c8ed3..82e85fac2e 100644
--- a/hw/char/terminal3270.c
+++ b/hw/char/terminal3270.c
@@ -200,9 +200,13 @@  static int read_payload_3270(EmulatedCcw3270Device *dev)
 {
     Terminal3270 *t = TERMINAL_3270(dev);
     int len;
+    int ret;
 
     len = MIN(ccw_dstream_avail(get_cds(t)), t->in_len);
-    ccw_dstream_write_buf(get_cds(t), t->inv, len);
+    ret = ccw_dstream_write_buf(get_cds(t), t->inv, len);
+    if (ret < 0) {
+        return ret;
+    }
     t->in_len -= len;
 
     return len;
@@ -260,7 +264,10 @@  static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd)
 
     t->outv[out_len++] = cmd;
     do {
-        ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
+        retval = ccw_dstream_read_buf(get_cds(t), &t->outv[out_len], len);
+        if (retval < 0) {
+            return retval;
+        }
         count = ccw_dstream_avail(get_cds(t));
         out_len += len;
 
diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
index 821319eee6..cc1371f01c 100644
--- a/hw/s390x/3270-ccw.c
+++ b/hw/s390x/3270-ccw.c
@@ -31,6 +31,9 @@  static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
     }
 
     len = ck->read_payload_3270(dev);
+    if (len < 0) {
+        return len;
+    }
     ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
 
     return 0;
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index fe47751df4..99e476f193 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1055,10 +1055,11 @@  static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
             }
         }
         len = MIN(ccw.count, sizeof(sch->sense_data));
-        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;
+        ret = ccw_dstream_write_buf(&sch->cds, sch->sense_data, len);
+        if (!ret) {
+            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
+            memset(sch->sense_data, 0, sizeof(sch->sense_data));
+        }
         break;
     case CCW_CMD_SENSE_ID:
     {
@@ -1083,9 +1084,10 @@  static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
         } else {
             sense_id[0] = 0;
         }
-        ccw_dstream_write_buf(&sch->cds, sense_id, len);
-        sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
-        ret = 0;
+        ret = ccw_dstream_write_buf(&sch->cds, sense_id, len);
+        if (!ret) {
+            sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
+        }
         break;
     }
     case CCW_CMD_TIC:
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 314ed7b245..8195f3546e 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -288,14 +288,20 @@  static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
         return -EFAULT;
     }
     if (is_legacy) {
-        ccw_dstream_read(&sch->cds, linfo);
+        ret = ccw_dstream_read(&sch->cds, linfo);
+        if (ret) {
+            return ret;
+        }
         linfo.queue = be64_to_cpu(linfo.queue);
         linfo.align = be32_to_cpu(linfo.align);
         linfo.index = be16_to_cpu(linfo.index);
         linfo.num = be16_to_cpu(linfo.num);
         ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
     } else {
-        ccw_dstream_read(&sch->cds, info);
+        ret = ccw_dstream_read(&sch->cds, info);
+        if (ret) {
+            return ret;
+        }
         info.desc = be64_to_cpu(info.desc);
         info.index = be16_to_cpu(info.index);
         info.num = be16_to_cpu(info.num);
@@ -371,7 +377,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
 
             ccw_dstream_advance(&sch->cds, sizeof(features.features));
-            ccw_dstream_read(&sch->cds, features.index);
+            ret = ccw_dstream_read(&sch->cds, features.index);
+            if (ret) {
+                break;
+            }
             if (features.index == 0) {
                 if (dev->revision >= 1) {
                     /* Don't offer legacy features for modern devices. */
@@ -392,9 +401,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             }
             ccw_dstream_rewind(&sch->cds);
             features.features = cpu_to_le32(features.features);
-            ccw_dstream_write(&sch->cds, features.features);
-            sch->curr_status.scsw.count = ccw.count - sizeof(features);
-            ret = 0;
+            ret = ccw_dstream_write(&sch->cds, features.features);
+            if (!ret) {
+                sch->curr_status.scsw.count = ccw.count - sizeof(features);
+            }
         }
         break;
     case CCW_CMD_WRITE_FEAT:
@@ -411,7 +421,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            ccw_dstream_read(&sch->cds, features);
+            ret = ccw_dstream_read(&sch->cds, features);
+            if (ret) {
+                break;
+            }
             features.features = le32_to_cpu(features.features);
             if (features.index == 0) {
                 virtio_set_features(vdev,
@@ -454,9 +467,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             ret = -EFAULT;
         } else {
             virtio_bus_get_vdev_config(&dev->bus, vdev->config);
-            ccw_dstream_write_buf(&sch->cds, vdev->config, len);
-            sch->curr_status.scsw.count = ccw.count - len;
-            ret = 0;
+            ret = ccw_dstream_write_buf(&sch->cds, vdev->config, len);
+            if (ret) {
+                sch->curr_status.scsw.count = ccw.count - len;
+            }
         }
         break;
     case CCW_CMD_WRITE_CONF:
@@ -511,7 +525,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            ccw_dstream_read(&sch->cds, status);
+            ret = ccw_dstream_read(&sch->cds, status);
+            if (ret) {
+                break;
+            }
             if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
                 virtio_ccw_stop_ioeventfd(dev);
             }
@@ -554,7 +571,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            ccw_dstream_read(&sch->cds, indicators);
+            ret = ccw_dstream_read(&sch->cds, indicators);
+            if (ret) {
+                break;
+            }
             indicators = be64_to_cpu(indicators);
             dev->indicators = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
@@ -575,7 +595,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            ccw_dstream_read(&sch->cds, indicators);
+            ret = ccw_dstream_read(&sch->cds, indicators);
+            if (ret) {
+                break;
+            }
             indicators = be64_to_cpu(indicators);
             dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
@@ -596,7 +619,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (!ccw.cda) {
             ret = -EFAULT;
         } else {
-            ccw_dstream_read(&sch->cds, vq_config.index);
+            ret = ccw_dstream_read(&sch->cds, vq_config.index);
+            if (ret) {
+                break;
+            }
             vq_config.index = be16_to_cpu(vq_config.index);
             if (vq_config.index >= VIRTIO_QUEUE_MAX) {
                 ret = -EINVAL;
@@ -605,9 +631,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             vq_config.num_max = virtio_queue_get_num(vdev,
                                                      vq_config.index);
             vq_config.num_max = cpu_to_be16(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;
+            ret = ccw_dstream_write(&sch->cds, vq_config.num_max);
+            if (!ret) {
+                sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
+            }
         }
         break;
     case CCW_CMD_SET_IND_ADAPTER:
@@ -664,7 +691,10 @@  static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
             ret = -EFAULT;
             break;
         }
-        ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
+        ret = ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
+        if (ret < 0) {
+            break;
+        }
         revinfo.revision = be16_to_cpu(revinfo.revision);
         revinfo.length = be16_to_cpu(revinfo.length);
         if (ccw.count < len + revinfo.length ||