Commit 1e7e92e2 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180409' into staging



Fixes for s390x: kvm, vfio-ccw, ipl code, bios. Includes a rebuild
of s390-ccw.img and s390-netboot.img.

# gpg: Signature made Mon 09 Apr 2018 16:08:19 BST
# gpg:                using RSA key DECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>"
# gpg:                 aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* remotes/cohuck/tags/s390x-20180409:
  s390x: load_psw() should only exchange the PSW for KVM
  s390x/mmu: don't overwrite pending exception in mmu translate
  vfio-ccw: fix memory leaks in vfio_ccw_realize()
  pc-bios/s390: update images
  s390: Do not pass inofficial IPL type to the guest
  s390: Ensure IPL from SCSI works as expected
  s390: Refactor IPL parameter block generation
  s390x/kvm: call cpu_synchronize_state() on every kvm_arch_handle_exit()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 915d34c5 b3a184f5
Loading
Loading
Loading
Loading
+80 −32
Original line number Diff line number Diff line
@@ -279,44 +279,52 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
    *timeout = cpu_to_be32(splash_time);
}

static bool s390_gen_initial_iplb(S390IPLState *ipl)
static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
{
    DeviceState *dev_st;
    CcwDevice *ccw_dev = NULL;

    dev_st = get_boot_device(0);
    if (dev_st) {
        VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
            object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
                                TYPE_VIRTIO_CCW_DEVICE);
        SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
                                                            TYPE_SCSI_DEVICE);
        VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
                                                          TYPE_VIRTIO_NET);

        if (vn) {
            ipl->netboot = true;
        }
        if (virtio_ccw_dev) {
            CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev);

            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
            ipl->iplb.blk0_len =
                cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
            ipl->iplb.pbt = S390_IPL_TYPE_CCW;
            ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
            ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
        } else if (sd) {
            ccw_dev = CCW_DEVICE(virtio_ccw_dev);
        } else {
            SCSIDevice *sd = (SCSIDevice *)
                object_dynamic_cast(OBJECT(dev_st),
                                    TYPE_SCSI_DEVICE);
            if (sd) {
                SCSIBus *bus = scsi_bus_from_device(sd);
                VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
            VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
            CcwDevice *ccw_dev;
                VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw,
                                                       vdev);

                ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
                                                           TYPE_CCW_DEVICE);
            if (!ccw_dev) {       /* It might be a PCI device instead */
                return false;
            }
        }
    }
    return ccw_dev;
}

static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
    DeviceState *dev_st;
    CcwDevice *ccw_dev = NULL;

    dev_st = get_boot_device(0);
    if (dev_st) {
        ccw_dev = s390_get_ccw_device(dev_st);
    }

    /*
     * Currently allow IPL only from CCW devices.
     */
    if (ccw_dev) {
        SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
                                                            TYPE_SCSI_DEVICE);

        if (sd) {
            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
            ipl->iplb.blk0_len =
                cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
@@ -327,12 +335,25 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
            ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
            ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
        } else {
            return false; /* unknown device */
            VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
                                                              TYPE_VIRTIO_NET);

            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
            ipl->iplb.blk0_len =
                cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
            ipl->iplb.pbt = S390_IPL_TYPE_CCW;
            ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
            ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;

            if (vn) {
                ipl->netboot = true;
            }
        }

        if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
            ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
        }

        return true;
    }

@@ -406,7 +427,8 @@ unref_mr:
    return img_size;
}

static bool is_virtio_net_device(IplParameterBlock *iplb)
static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb,
                                         int virtio_id)
{
    uint8_t cssid;
    uint8_t ssid;
@@ -426,13 +448,23 @@ static bool is_virtio_net_device(IplParameterBlock *iplb)
            sch = css_find_subch(1, cssid, ssid, schid);

            if (sch && sch->devno == devno) {
                return sch->id.cu_model == VIRTIO_ID_NET;
                return sch->id.cu_model == virtio_id;
            }
        }
    }
    return false;
}

static bool is_virtio_net_device(IplParameterBlock *iplb)
{
    return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET);
}

static bool is_virtio_scsi_device(IplParameterBlock *iplb)
{
    return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI);
}

void s390_ipl_update_diag308(IplParameterBlock *iplb)
{
    S390IPLState *ipl = get_ipl_device();
@@ -457,6 +489,22 @@ void s390_reipl_request(void)
    S390IPLState *ipl = get_ipl_device();

    ipl->reipl_requested = true;
    if (ipl->iplb_valid &&
        !ipl->netboot &&
        ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
        is_virtio_scsi_device(&ipl->iplb)) {
        CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0));

        if (ccw_dev &&
            cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
            (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) {
            /*
             * this is the original boot device's SCSI
             * so restore IPL parameter info from it
             */
            ipl->iplb_valid = s390_gen_initial_iplb(ipl);
        }
    }
    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}

+2 −0
Original line number Diff line number Diff line
@@ -357,11 +357,13 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp)
        if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) {
            error_setg(&err, "vfio: subchannel %s has already been attached",
                       vcdev->vdev.name);
            g_free(vcdev->vdev.name);
            goto out_device_err;
        }
    }

    if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) {
        g_free(vcdev->vdev.name);
        goto out_device_err;
    }

−48 B (29.8 KiB)

File changed.

No diff preview for this file type.

+7 −0
Original line number Diff line number Diff line
@@ -70,6 +70,13 @@ static void jump_to_IPL_code(uint64_t address)
{
    /* store the subsystem information _after_ the bootmap was loaded */
    write_subsystem_identification();

    /* prevent unknown IPL types in the guest */
    if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) {
        iplb.pbt = S390_IPL_TYPE_CCW;
        set_iplb(&iplb);
    }

    /*
     * The IPL PSW is at address 0. We also must not overwrite the
     * content of non-BIOS memory after we loaded the guest, so we
+13 −2
Original line number Diff line number Diff line
@@ -97,16 +97,27 @@ extern QemuIplParameters qipl;
#define S390_IPL_TYPE_CCW 0x02
#define S390_IPL_TYPE_QEMU_SCSI 0xff

static inline bool store_iplb(IplParameterBlock *iplb)
static inline bool manage_iplb(IplParameterBlock *iplb, bool store)
{
    register unsigned long addr asm("0") = (unsigned long) iplb;
    register unsigned long rc asm("1") = 0;

    asm volatile ("diag %0,%2,0x308\n"
                  : "+d" (addr), "+d" (rc)
                  : "d" (6)
                  : "d" (store ? 6 : 5)
                  : "memory", "cc");
    return rc == 0x01;
}


static inline bool store_iplb(IplParameterBlock *iplb)
{
    return manage_iplb(iplb, true);
}

static inline bool set_iplb(IplParameterBlock *iplb)
{
    return manage_iplb(iplb, false);
}

#endif /* IPLB_H */
Loading