aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2014-05-27 12:40:44 +0200
committerCornelia Huck <cornelia.huck@de.ibm.com>2014-06-10 09:50:26 +0200
commitf068d320def7fd83bf0fcdca37b305f1c2ac5413 (patch)
tree4cdcf0f962d1211847f0dd15a0e7ba4688469579 /hw/s390x
parent7721a3044234c46cd6f5f899e7467dc9351f3c8d (diff)
downloadqemu-f068d320def7fd83bf0fcdca37b305f1c2ac5413.zip
qemu-f068d320def7fd83bf0fcdca37b305f1c2ac5413.tar.gz
qemu-f068d320def7fd83bf0fcdca37b305f1c2ac5413.tar.bz2
s390x/css: handle emw correctly for tsch
We should not try to store the emw portion of the irb if extended measurements are not applicable. In particular, we should not surprise the guest by storing a larger irb if it did not enable extended measurements. Cc: qemu-stable@nongnu.org Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Tested-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/css.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 2678e44..a813b23 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -779,9 +779,11 @@ out:
return ret;
}
-static void copy_irb_to_guest(IRB *dest, const IRB *src)
+static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw)
{
int i;
+ uint16_t stctl = src->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
+ uint16_t actl = src->scsw.ctrl & SCSW_CTRL_MASK_ACTL;
copy_scsw_to_guest(&dest->scsw, &src->scsw);
@@ -791,8 +793,22 @@ static void copy_irb_to_guest(IRB *dest, const IRB *src)
for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
dest->ecw[i] = cpu_to_be32(src->ecw[i]);
}
- for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
- dest->emw[i] = cpu_to_be32(src->emw[i]);
+ /* extended measurements enabled? */
+ if ((src->scsw.flags & SCSW_FLAGS_MASK_ESWF) ||
+ !(pmcw->flags & PMCW_FLAGS_MASK_TF) ||
+ !(pmcw->chars & PMCW_CHARS_MASK_XMWME)) {
+ return;
+ }
+ /* extended measurements pending? */
+ if (!(stctl & SCSW_STCTL_STATUS_PEND)) {
+ return;
+ }
+ if ((stctl & SCSW_STCTL_PRIMARY) ||
+ (stctl == SCSW_STCTL_SECONDARY) ||
+ ((stctl & SCSW_STCTL_INTERMEDIATE) && (actl & SCSW_ACTL_SUSP))) {
+ for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
+ dest->emw[i] = cpu_to_be32(src->emw[i]);
+ }
}
}
@@ -838,7 +854,7 @@ int css_do_tsch(SubchDev *sch, IRB *target_irb)
}
}
/* Store the irb to the guest. */
- copy_irb_to_guest(target_irb, &irb);
+ copy_irb_to_guest(target_irb, &irb, p);
/* Clear conditions on subchannel, if applicable. */
if (stctl & SCSW_STCTL_STATUS_PEND) {