aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x/css.c
diff options
context:
space:
mode:
authorHalil Pasic <pasic@linux.vnet.ibm.com>2017-09-21 20:08:37 +0200
committerCornelia Huck <cohuck@redhat.com>2017-10-06 10:53:01 +0200
commit57065a70d00c36f5d20d430eb64d16db8e761c31 (patch)
treeb4bff3acaaf06ac7baf1cb67575e7b7e7a3ff189 /hw/s390x/css.c
parent947a38bd6f1301a97f3c9c7485e7fa118bbc40cf (diff)
s390x/css: introduce css data stream
This is a preparation for introducing handling for indirect data addressing and modified indirect data addressing (CCW). Here we introduce an interface which should make the addressing scheme transparent for the client code. Here we implement only the basic scheme (no IDA or MIDA). Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com> Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com> Message-Id: <20170921180841.24490-2-pasic@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'hw/s390x/css.c')
-rw-r--r--hw/s390x/css.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c59be1aad1..248e9d47e5 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -787,6 +787,61 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1)
}
return ret;
}
+/**
+ * If out of bounds marks the stream broken. If broken returns -EINVAL,
+ * otherwise the requested length (may be zero)
+ */
+static inline int cds_check_len(CcwDataStream *cds, int len)
+{
+ if (cds->at_byte + len > cds->count) {
+ cds->flags |= CDS_F_STREAM_BROKEN;
+ }
+ return cds->flags & CDS_F_STREAM_BROKEN ? -EINVAL : len;
+}
+
+static int ccw_dstream_rw_noflags(CcwDataStream *cds, void *buff, int len,
+ CcwDataStreamOp op)
+{
+ int ret;
+
+ ret = cds_check_len(cds, len);
+ if (ret <= 0) {
+ return ret;
+ }
+ if (op == CDS_OP_A) {
+ goto incr;
+ }
+ ret = address_space_rw(&address_space_memory, cds->cda,
+ MEMTXATTRS_UNSPECIFIED, buff, len, op);
+ if (ret != MEMTX_OK) {
+ cds->flags |= CDS_F_STREAM_BROKEN;
+ return -EINVAL;
+ }
+incr:
+ cds->at_byte += len;
+ cds->cda += len;
+ return 0;
+}
+
+void ccw_dstream_init(CcwDataStream *cds, CCW1 const *ccw, ORB const *orb)
+{
+ /*
+ * We don't support MIDA (an optional facility) yet and we
+ * catch this earlier. Just for expressing the precondition.
+ */
+ g_assert(!(orb->ctrl1 & ORB_CTRL1_MASK_MIDAW));
+ cds->flags = (orb->ctrl0 & ORB_CTRL0_MASK_I2K ? CDS_F_I2K : 0) |
+ (orb->ctrl0 & ORB_CTRL0_MASK_C64 ? CDS_F_C64 : 0) |
+ (ccw->flags & CCW_FLAG_IDA ? CDS_F_IDA : 0);
+ cds->count = ccw->count;
+ cds->cda_orig = ccw->cda;
+ ccw_dstream_rewind(cds);
+ if (!(cds->flags & CDS_F_IDA)) {
+ cds->op_handler = ccw_dstream_rw_noflags;
+ } else {
+ assert(false);
+ }
+}
static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
bool suspend_allowed)