summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390x/css.c16
-rw-r--r--hw/s390x/s390-ccw.c1
-rw-r--r--hw/vfio/ccw.c4
-rw-r--r--include/hw/s390x/css.h3
4 files changed, 23 insertions, 1 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1a3aad5163..133ddea575 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1335,7 +1335,7 @@ static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
}
}
-static void copy_esw_to_guest(ESW *dest, const ESW *src)
+void copy_esw_to_guest(ESW *dest, const ESW *src)
{
dest->word0 = cpu_to_be32(src->word0);
dest->erw = cpu_to_be32(src->erw);
@@ -1650,6 +1650,20 @@ static void build_irb_sense_data(SubchDev *sch, IRB *irb)
}
}
+void build_irb_passthrough(SubchDev *sch, IRB *irb)
+{
+ /* Copy ESW from hardware */
+ irb->esw = sch->esw;
+
+ /*
+ * If (irb->esw.erw & ESW_ERW_SENSE) is true, then the contents
+ * of the ECW is sense data. If false, then it is model-dependent
+ * information. Either way, copy it into the IRB for the guest to
+ * read/decide what to do with.
+ */
+ build_irb_sense_data(sch, irb);
+}
+
void build_irb_virtual(SubchDev *sch, IRB *irb)
{
SCHIB *schib = &sch->curr_status;
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index c227c77984..2fc8bb9c23 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -124,6 +124,7 @@ static void s390_ccw_realize(S390CCWDevice *cdev, char *sysfsdev, Error **errp)
}
sch->driver_data = cdev;
sch->do_subchannel_work = do_subchannel_work_passthrough;
+ sch->irb_cb = build_irb_passthrough;
ccw_dev->sch = sch;
ret = css_sch_build_schib(sch, &cdev->hostid);
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 139a3d9d1b..000992fb9f 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -321,6 +321,7 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
SCHIB *schib = &sch->curr_status;
SCSW s;
IRB irb;
+ ESW esw;
int size;
if (!event_notifier_test_and_clear(&vcdev->io_notifier)) {
@@ -371,6 +372,9 @@ static void vfio_ccw_io_notifier_handler(void *opaque)
copy_scsw_to_guest(&s, &irb.scsw);
schib->scsw = s;
+ copy_esw_to_guest(&esw, &irb.esw);
+ sch->esw = esw;
+
/* If a uint check is pending, copy sense data. */
if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
(schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 7c23a13f3d..10ed1df1bb 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -141,6 +141,7 @@ struct SubchDev {
void (*irb_cb)(SubchDev *, IRB *);
SenseId id;
void *driver_data;
+ ESW esw;
};
static inline void sch_gen_unit_exception(SubchDev *sch)
@@ -202,6 +203,7 @@ int css_sch_build_schib(SubchDev *sch, CssDevId *dev_id);
unsigned int css_find_free_chpid(uint8_t cssid);
uint16_t css_build_subchannel_id(SubchDev *sch);
void copy_scsw_to_guest(SCSW *dest, const SCSW *src);
+void copy_esw_to_guest(ESW *dest, const ESW *src);
void css_inject_io_interrupt(SubchDev *sch);
void css_reset(void);
void css_reset_sch(SubchDev *sch);
@@ -216,6 +218,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_passthrough(SubchDev *sch, IRB *irb);
void build_irb_virtual(SubchDev *sch, IRB *irb);
int s390_ccw_halt(SubchDev *sch);