Commit 9a51c9ee authored by Halil Pasic's avatar Halil Pasic Committed by Cornelia Huck
Browse files

vfio-ccw: add force unlimited prefetch property



There is at least one guest (OS) such that although it does not rely on
the guarantees provided by ORB 1 word 9 bit (aka unlimited prefetch, aka
P bit) not being set, it fails to tell this to the machine.

Usually this ain't a big deal, as the original purpose of the P bit is to
allow for performance optimizations. vfio-ccw however can not provide the
guarantees required if the bit is not set.

It is not possible to implement support for the P bit not set without
transitioning to lower level protocols for vfio-ccw.  So let's give the
user the opportunity to force setting the P bit, if the user knows this
is safe.  For self modifying channel programs forcing the P bit is not
safe.  If the P bit is forced for a self modifying channel program things
are expected to break in strange ways.

Let's also avoid warning multiple about P bit not set in the ORB in case
P bit is not told to be forced, and designate the affected vfio-ccw
device.

Signed-off-by: default avatarHalil Pasic <pasic@linux.ibm.com>
Suggested-by: default avatarDong Jia Shi <bjsdjshi@linux.ibm.com>
Acked-by: default avatarJason J. Herne <jjherne@linux.ibm.com>
Tested-by: default avatarJason J. Herne <jjherne@linux.ibm.com>
Message-Id: <20180524175828.3143-2-pasic@linux.ibm.com>
Signed-off-by: default avatarCornelia Huck <cohuck@redhat.com>
parent 7a5342e7
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -1204,8 +1204,7 @@ static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
     * Only support prefetch enable mode.
     * Only support 64bit addressing idal.
     */
    if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
        !(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
    if (!(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
        warn_report("vfio-ccw requires PFCH and C64 flags set");
        sch_gen_unit_exception(sch);
        css_inject_io_interrupt(sch);
+35 −0
Original line number Diff line number Diff line
@@ -33,8 +33,30 @@ typedef struct VFIOCCWDevice {
    uint64_t io_region_offset;
    struct ccw_io_region *io_region;
    EventNotifier io_notifier;
    bool force_orb_pfch;
    bool warned_orb_pfch;
} VFIOCCWDevice;

static inline void warn_once(bool *warned, const char *fmt, ...)
{
    va_list ap;

    if (!warned || *warned) {
        return;
    }
    *warned = true;
    va_start(ap, fmt);
    warn_vreport(fmt, ap);
    va_end(ap);
}

static inline void warn_once_pfch(VFIOCCWDevice *vcdev, SubchDev *sch,
                                  const char *msg)
{
    warn_once(&vcdev->warned_orb_pfch, "vfio-ccw (devno %x.%x.%04x): %s",
              sch->cssid, sch->ssid, sch->devno, msg);
}

static void vfio_ccw_compute_needs_reset(VFIODevice *vdev)
{
    vdev->needs_reset = false;
@@ -55,6 +77,18 @@ static IOInstEnding vfio_ccw_handle_request(SubchDev *sch)
    struct ccw_io_region *region = vcdev->io_region;
    int ret;

    if (!(sch->orb.ctrl0 & ORB_CTRL0_MASK_PFCH)) {
        if (!(vcdev->force_orb_pfch)) {
            warn_once_pfch(vcdev, sch, "requires PFCH flag set");
            sch_gen_unit_exception(sch);
            css_inject_io_interrupt(sch);
            return IOINST_CC_EXPECTED;
        } else {
            sch->orb.ctrl0 |= ORB_CTRL0_MASK_PFCH;
            warn_once_pfch(vcdev, sch, "PFCH flag forced");
        }
    }

    QEMU_BUILD_BUG_ON(sizeof(region->orb_area) != sizeof(ORB));
    QEMU_BUILD_BUG_ON(sizeof(region->scsw_area) != sizeof(SCSW));
    QEMU_BUILD_BUG_ON(sizeof(region->irb_area) != sizeof(IRB));
@@ -430,6 +464,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp)

static Property vfio_ccw_properties[] = {
    DEFINE_PROP_STRING("sysfsdev", VFIOCCWDevice, vdev.sysfsdev),
    DEFINE_PROP_BOOL("force-orb-pfch", VFIOCCWDevice, force_orb_pfch, false),
    DEFINE_PROP_END_OF_LIST(),
};