s390x/css: firm up handling of chained TIC CCWs
The logic in css_interpret_ccw() correctly returns -EINVAL if a
Transfer-In-Channel (TIC) CCW is command chained to another TIC CCW.
The same routine also correctly returns -EINVAL if 256 CCWs do not
perform a data transfer as part of the I/O operation [0].
What is missing, however, is a combination of these two, where a loop
can be generated that will continue processing CCWs but without
providing an opportunity to catch a breath. Fix this by capping
the number of TIC CCWs in a channel program at the same limit as
the CCWs without data transfer.
[0] See "Invalid Sequence" in z/Architecture Principles of Operation
(SA22-7832-14), p16-27
Cc: qemu-stable@nongnu.org
Signed-off-by: Eric Farman <farman@linux.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Message-ID: <20260713074708.884282-1-borntraeger@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
committed by
Cornelia Huck
parent
8a116a2853
commit
33bece0fa1
@@ -1078,6 +1078,12 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
/* Limit the number of TICs in a given channel program */
|
||||
if (sch->ccw_tic_cnt == 255) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
sch->ccw_tic_cnt++;
|
||||
sch->channel_prog = ccw.cda;
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
@@ -1129,6 +1135,7 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
|
||||
sch->ccw_fmt_1 = !!(orb->ctrl0 & ORB_CTRL0_MASK_FMT);
|
||||
schib->scsw.flags |= (sch->ccw_fmt_1) ? SCSW_FLAGS_MASK_FMT : 0;
|
||||
sch->ccw_no_data_cnt = 0;
|
||||
sch->ccw_tic_cnt = 0;
|
||||
suspend_allowed = !!(orb->ctrl0 & ORB_CTRL0_MASK_SPND);
|
||||
} else {
|
||||
/* Start Function resumed via rsch */
|
||||
|
||||
@@ -132,6 +132,7 @@ struct SubchDev {
|
||||
bool ccw_fmt_1;
|
||||
bool thinint_active;
|
||||
uint8_t ccw_no_data_cnt;
|
||||
uint8_t ccw_tic_cnt;
|
||||
uint16_t migrated_schid; /* used for mismatch detection */
|
||||
CcwDataStream cds;
|
||||
/* transport-provided data: */
|
||||
|
||||
Reference in New Issue
Block a user