Commit 4f225f34 authored by Stefan Hajnoczi's avatar Stefan Hajnoczi
Browse files

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



More s390x patches, this time boot related:
- LOADPARM machine property, exposed to the guest via SCLP and
  diagnose 308
- Use LOADPARM in the s390-ccw bios to select a boot entry
- Fix a crash in the ipl device code when a virtio-scsi-pci device
  has been specified

# gpg: Signature made Tue 02 May 2017 02:29:26 PM BST
# gpg:                using RSA key 0xDECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg:                 aka "Cornelia Huck <cohuck@kernel.org>"
# gpg:                 aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg:                 aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0  18CE DECF 6B93 C6F0 2FAF

* cohuck/tags/s390x-20170502:
  hw/s390x/ipl: Fix crash with virtio-scsi-pci device
  pc-bios/s390-ccw.img: update image
  pc-bios/s390-ccw: add boot entry selection to El Torito routine
  pc-bios/s390-ccw: add boot entry selection for ECKD DASD
  pc-bios/s390-ccw: provide entry selection on LOADPARM for SCSI disk
  pc-bios/s390-ccw: provide a function to interpret LOADPARM value
  pc-bios/s390-ccw: get LOADPARM stored in SCP Read Info
  pc-bios/s390-ccw: Make ebcdic/ascii conversion public
  util/qemu-config: Add loadparm to qemu machine_opts
  hw/s390x/sclp: update LOADPARM in SCP Info
  hw/s390x/ipl: enable LOADPARM in IPIB for a boot device
  hw/s390x: provide loadparm property for the machine

Signed-off-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
parents 12a95f32 99efaa26
Loading
Loading
Loading
Loading
+36 −3
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
#include "cpu.h"
#include "elf.h"
#include "hw/loader.h"
#include "hw/boards.h"
#include "hw/s390x/virtio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "ipl.h"
#include "qemu/error-report.h"

@@ -243,12 +245,17 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
            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;
            return true;
        } else 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 = CCW_DEVICE(scsi_ccw);
            CcwDevice *ccw_dev;

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

            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
            ipl->iplb.blk0_len =
@@ -259,13 +266,39 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
            ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
            ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
            ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
            return true;
        } else {
            return false; /* unknown device */
        }

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

    return false;
}

int s390_ipl_set_loadparm(uint8_t *loadparm)
{
    MachineState *machine = MACHINE(qdev_get_machine());
    char *lp = object_property_get_str(OBJECT(machine), "loadparm", NULL);

    if (lp) {
        int i;

        /* lp is an uppercase string without leading/embedded spaces */
        for (i = 0; i < 8 && lp[i]; i++) {
            loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]];
        }

        g_free(lp);
        return 0;
    }

    return -1;
}

static int load_netboot_image(Error **errp)
{
    S390IPLState *ipl = get_ipl_device();
+3 −0
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ struct IplBlockQemuScsi {
} QEMU_PACKED;
typedef struct IplBlockQemuScsi IplBlockQemuScsi;

#define DIAG308_FLAGS_LP_VALID 0x80

union IplParameterBlock {
    struct {
        uint32_t len;
@@ -82,6 +84,7 @@ union IplParameterBlock {
} QEMU_PACKED;
typedef union IplParameterBlock IplParameterBlock;

int s390_ipl_set_loadparm(uint8_t *loadparm);
void s390_ipl_update_diag308(IplParameterBlock *iplb);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
+37 −0
Original line number Diff line number Diff line
@@ -274,6 +274,36 @@ bool cpu_model_allowed(void)
    return true;
}

static char *machine_get_loadparm(Object *obj, Error **errp)
{
    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);

    return g_memdup(ms->loadparm, sizeof(ms->loadparm));
}

static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
{
    S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
    int i;

    for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
        uint8_t c = toupper(val[i]); /* mimic HMC */

        if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
            (c == ' ')) {
            ms->loadparm[i] = c;
        } else {
            error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
                       c, c);
            return;
        }
    }

    for (; i < sizeof(ms->loadparm); i++) {
        ms->loadparm[i] = ' '; /* pad right with spaces */
    }
}

static inline void s390_machine_initfn(Object *obj)
{
    object_property_add_bool(obj, "aes-key-wrap",
@@ -291,6 +321,13 @@ static inline void s390_machine_initfn(Object *obj)
            "enable/disable DEA key wrapping using the CPACF wrapping key",
            NULL);
    object_property_set_bool(obj, true, "dea-key-wrap", NULL);
    object_property_add_str(obj, "loadparm",
            machine_get_loadparm, machine_set_loadparm, NULL);
    object_property_set_description(obj, "loadparm",
            "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
            " to upper case) to pass to machine loader, boot manager,"
            " and guest kernel",
            NULL);
}

static const TypeInfo ccw_machine_info = {
+9 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "hw/s390x/sclp.h"
#include "hw/s390x/event-facility.h"
#include "hw/s390x/s390-pci-bus.h"
#include "hw/s390x/ipl.h"

static inline SCLPDevice *get_sclp_device(void)
{
@@ -57,6 +58,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
    int cpu_count = 0;
    int rnsize, rnmax;
    int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
    IplParameterBlock *ipib = s390_ipl_get_iplb();

    CPU_FOREACH(cpu) {
        cpu_count++;
@@ -129,6 +131,13 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
        read_info->rnmax2 = cpu_to_be64(rnmax);
    }

    if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
        memcpy(&read_info->loadparm, &ipib->loadparm,
               sizeof(read_info->loadparm));
    } else {
        s390_ipl_set_loadparm(read_info->loadparm);
    }

    sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
}

+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ typedef struct S390CcwMachineState {
    /*< public >*/
    bool aes_key_wrap;
    bool dea_key_wrap;
    uint8_t loadparm[8];
} S390CcwMachineState;

typedef struct S390CcwMachineClass {
Loading