Skip to content

Commit

Permalink
s390x/css: Refactor IRB construction
Browse files Browse the repository at this point in the history
Currently, all subchannel types have "sense data" copied into
the IRB.ECW space, and a couple flags enabled in the IRB.SCSW
and IRB.ESW. But for passthrough (vfio-ccw) subchannels,
this data isn't populated in the first place, so enabling
those flags leads to unexpected behavior if the guest tries to
process the sense data (zeros) in the IRB.ECW.

Let's add a subchannel callback that builds these portions of
the IRB, and move the existing code into a routine for those
virtual subchannels. The passthrough subchannels will be able
to piggy-back onto this later.

Signed-off-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20210617232537.1337506-4-farman@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
  • Loading branch information
efarman authored and cohuck committed Jun 21, 2021
1 parent 1b01ded commit 0599a04
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 16 deletions.
1 change: 1 addition & 0 deletions hw/s390x/3270-ccw.c
Expand Up @@ -129,6 +129,7 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
EMULATED_CCW_3270_CHPID_TYPE);
sch->do_subchannel_work = do_subchannel_work_virtual;
sch->ccw_cb = emulated_ccw_3270_cb;
sch->irb_cb = build_irb_virtual;

ck->init(dev, &err);
if (err) {
Expand Down
45 changes: 29 additions & 16 deletions hw/s390x/css.c
Expand Up @@ -1650,6 +1650,30 @@ static void build_irb_sense_data(SubchDev *sch, IRB *irb)
}
}

void build_irb_virtual(SubchDev *sch, IRB *irb)
{
SCHIB *schib = &sch->curr_status;
uint16_t stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL;

if (stctl & SCSW_STCTL_STATUS_PEND) {
if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
SCSW_CSTAT_CHN_CTRL_CHK |
SCSW_CSTAT_INTF_CTRL_CHK)) {
irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF;
irb->esw.word0 = 0x04804000;
} else {
irb->esw.word0 = 0x00800000;
}
/* If a unit check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
build_irb_sense_data(sch, irb);
irb->esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8);
}
}
}

int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
{
SCHIB *schib = &sch->curr_status;
Expand All @@ -1668,23 +1692,12 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)

/* Copy scsw from current status. */
irb.scsw = schib->scsw;
if (stctl & SCSW_STCTL_STATUS_PEND) {
if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
SCSW_CSTAT_CHN_CTRL_CHK |
SCSW_CSTAT_INTF_CTRL_CHK)) {
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF;
irb.esw.word0 = 0x04804000;
} else {
irb.esw.word0 = 0x00800000;
}
/* If a unit check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
build_irb_sense_data(sch, &irb);
irb.esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8);
}

/* Build other IRB data, if necessary */
if (sch->irb_cb) {
sch->irb_cb(sch, &irb);
}

/* Store the irb to the guest. */
p = schib->pmcw;
copy_irb_to_guest(target_irb, &irb, &p, irb_len);
Expand Down
1 change: 1 addition & 0 deletions hw/s390x/virtio-ccw.c
Expand Up @@ -753,6 +753,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
sch->do_subchannel_work = do_subchannel_work_virtual;
sch->irb_cb = build_irb_virtual;
ccw_dev->sch = sch;
dev->indicators = NULL;
dev->revision = -1;
Expand Down
2 changes: 2 additions & 0 deletions include/hw/s390x/css.h
Expand Up @@ -138,6 +138,7 @@ struct SubchDev {
int (*ccw_cb) (SubchDev *, CCW1);
void (*disable_cb)(SubchDev *);
IOInstEnding (*do_subchannel_work) (SubchDev *);
void (*irb_cb)(SubchDev *, IRB *);
SenseId id;
void *driver_data;
};
Expand Down Expand Up @@ -215,6 +216,7 @@ void css_clear_sei_pending(void);
IOInstEnding s390_ccw_cmd_request(SubchDev *sch);
IOInstEnding do_subchannel_work_virtual(SubchDev *sub);
IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
void build_irb_virtual(SubchDev *sch, IRB *irb);

int s390_ccw_halt(SubchDev *sch);
int s390_ccw_clear(SubchDev *sch);
Expand Down

0 comments on commit 0599a04

Please sign in to comment.