cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

ipl.c (23622B)


      1/*
      2 * bootloader support
      3 *
      4 * Copyright IBM, Corp. 2012, 2020
      5 *
      6 * Authors:
      7 *  Christian Borntraeger <borntraeger@de.ibm.com>
      8 *  Janosch Frank <frankja@linux.ibm.com>
      9 *
     10 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
     11 * option) any later version.  See the COPYING file in the top-level directory.
     12 *
     13 */
     14
     15#include "qemu/osdep.h"
     16#include "qemu-common.h"
     17#include "qemu/datadir.h"
     18#include "qapi/error.h"
     19#include "sysemu/reset.h"
     20#include "sysemu/runstate.h"
     21#include "sysemu/tcg.h"
     22#include "elf.h"
     23#include "hw/loader.h"
     24#include "hw/qdev-properties.h"
     25#include "hw/boards.h"
     26#include "hw/s390x/virtio-ccw.h"
     27#include "hw/s390x/vfio-ccw.h"
     28#include "hw/s390x/css.h"
     29#include "hw/s390x/ebcdic.h"
     30#include "hw/s390x/pv.h"
     31#include "ipl.h"
     32#include "qemu/error-report.h"
     33#include "qemu/config-file.h"
     34#include "qemu/cutils.h"
     35#include "qemu/option.h"
     36#include "exec/exec-all.h"
     37
     38#define KERN_IMAGE_START                0x010000UL
     39#define LINUX_MAGIC_ADDR                0x010008UL
     40#define KERN_PARM_AREA                  0x010480UL
     41#define INITRD_START                    0x800000UL
     42#define INITRD_PARM_START               0x010408UL
     43#define PARMFILE_START                  0x001000UL
     44#define ZIPL_IMAGE_START                0x009000UL
     45#define IPL_PSW_MASK                    (PSW_MASK_32 | PSW_MASK_64)
     46
     47static bool iplb_extended_needed(void *opaque)
     48{
     49    S390IPLState *ipl = S390_IPL(object_resolve_path(TYPE_S390_IPL, NULL));
     50
     51    return ipl->iplbext_migration;
     52}
     53
     54static const VMStateDescription vmstate_iplb_extended = {
     55    .name = "ipl/iplb_extended",
     56    .version_id = 0,
     57    .minimum_version_id = 0,
     58    .needed = iplb_extended_needed,
     59    .fields = (VMStateField[]) {
     60        VMSTATE_UINT8_ARRAY(reserved_ext, IplParameterBlock, 4096 - 200),
     61        VMSTATE_END_OF_LIST()
     62    }
     63};
     64
     65static const VMStateDescription vmstate_iplb = {
     66    .name = "ipl/iplb",
     67    .version_id = 0,
     68    .minimum_version_id = 0,
     69    .fields = (VMStateField[]) {
     70        VMSTATE_UINT8_ARRAY(reserved1, IplParameterBlock, 110),
     71        VMSTATE_UINT16(devno, IplParameterBlock),
     72        VMSTATE_UINT8_ARRAY(reserved2, IplParameterBlock, 88),
     73        VMSTATE_END_OF_LIST()
     74    },
     75    .subsections = (const VMStateDescription*[]) {
     76        &vmstate_iplb_extended,
     77        NULL
     78    }
     79};
     80
     81static const VMStateDescription vmstate_ipl = {
     82    .name = "ipl",
     83    .version_id = 0,
     84    .minimum_version_id = 0,
     85    .fields = (VMStateField[]) {
     86        VMSTATE_UINT64(compat_start_addr, S390IPLState),
     87        VMSTATE_UINT64(compat_bios_start_addr, S390IPLState),
     88        VMSTATE_STRUCT(iplb, S390IPLState, 0, vmstate_iplb, IplParameterBlock),
     89        VMSTATE_BOOL(iplb_valid, S390IPLState),
     90        VMSTATE_UINT8(cssid, S390IPLState),
     91        VMSTATE_UINT8(ssid, S390IPLState),
     92        VMSTATE_UINT16(devno, S390IPLState),
     93        VMSTATE_END_OF_LIST()
     94     }
     95};
     96
     97static S390IPLState *get_ipl_device(void)
     98{
     99    return S390_IPL(object_resolve_path_type("", TYPE_S390_IPL, NULL));
    100}
    101
    102static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr)
    103{
    104    uint64_t dstaddr = *(uint64_t *) opaque;
    105    /*
    106     * Assuming that our s390-ccw.img was linked for starting at address 0,
    107     * we can simply add the destination address for the final location
    108     */
    109    return srcaddr + dstaddr;
    110}
    111
    112static void s390_ipl_realize(DeviceState *dev, Error **errp)
    113{
    114    MachineState *ms = MACHINE(qdev_get_machine());
    115    S390IPLState *ipl = S390_IPL(dev);
    116    uint32_t *ipl_psw;
    117    uint64_t pentry;
    118    char *magic;
    119    int kernel_size;
    120
    121    int bios_size;
    122    char *bios_filename;
    123
    124    /*
    125     * Always load the bios if it was enforced,
    126     * even if an external kernel has been defined.
    127     */
    128    if (!ipl->kernel || ipl->enforce_bios) {
    129        uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
    130
    131        bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware);
    132        if (bios_filename == NULL) {
    133            error_setg(errp, "could not find stage1 bootloader");
    134            return;
    135        }
    136
    137        bios_size = load_elf(bios_filename, NULL,
    138                             bios_translate_addr, &fwbase,
    139                             &ipl->bios_start_addr, NULL, NULL, NULL, 1,
    140                             EM_S390, 0, 0);
    141        if (bios_size > 0) {
    142            /* Adjust ELF start address to final location */
    143            ipl->bios_start_addr += fwbase;
    144        } else {
    145            /* Try to load non-ELF file */
    146            bios_size = load_image_targphys(bios_filename, ZIPL_IMAGE_START,
    147                                            4096);
    148            ipl->bios_start_addr = ZIPL_IMAGE_START;
    149        }
    150        g_free(bios_filename);
    151
    152        if (bios_size == -1) {
    153            error_setg(errp, "could not load bootloader '%s'", ipl->firmware);
    154            return;
    155        }
    156
    157        /* default boot target is the bios */
    158        ipl->start_addr = ipl->bios_start_addr;
    159    }
    160
    161    if (ipl->kernel) {
    162        kernel_size = load_elf(ipl->kernel, NULL, NULL, NULL,
    163                               &pentry, NULL,
    164                               NULL, NULL, 1, EM_S390, 0, 0);
    165        if (kernel_size < 0) {
    166            kernel_size = load_image_targphys(ipl->kernel, 0, ms->ram_size);
    167            if (kernel_size < 0) {
    168                error_setg(errp, "could not load kernel '%s'", ipl->kernel);
    169                return;
    170            }
    171            /* if this is Linux use KERN_IMAGE_START */
    172            magic = rom_ptr(LINUX_MAGIC_ADDR, 6);
    173            if (magic && !memcmp(magic, "S390EP", 6)) {
    174                pentry = KERN_IMAGE_START;
    175            } else {
    176                /* if not Linux load the address of the (short) IPL PSW */
    177                ipl_psw = rom_ptr(4, 4);
    178                if (ipl_psw) {
    179                    pentry = be32_to_cpu(*ipl_psw) & PSW_MASK_SHORT_ADDR;
    180                } else {
    181                    error_setg(errp, "Could not get IPL PSW");
    182                    return;
    183                }
    184            }
    185        }
    186        /*
    187         * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the
    188         * kernel parameters here as well. Note: For old kernels (up to 3.2)
    189         * we can not rely on the ELF entry point - it was 0x800 (the SALIPL
    190         * loader) and it won't work. For this case we force it to 0x10000, too.
    191         */
    192        if (pentry == KERN_IMAGE_START || pentry == 0x800) {
    193            char *parm_area = rom_ptr(KERN_PARM_AREA, strlen(ipl->cmdline) + 1);
    194            ipl->start_addr = KERN_IMAGE_START;
    195            /* Overwrite parameters in the kernel image, which are "rom" */
    196            if (parm_area) {
    197                strcpy(parm_area, ipl->cmdline);
    198            }
    199        } else {
    200            ipl->start_addr = pentry;
    201        }
    202
    203        if (ipl->initrd) {
    204            ram_addr_t initrd_offset;
    205            int initrd_size;
    206            uint64_t *romptr;
    207
    208            initrd_offset = INITRD_START;
    209            while (kernel_size + 0x100000 > initrd_offset) {
    210                initrd_offset += 0x100000;
    211            }
    212            initrd_size = load_image_targphys(ipl->initrd, initrd_offset,
    213                                              ms->ram_size - initrd_offset);
    214            if (initrd_size == -1) {
    215                error_setg(errp, "could not load initrd '%s'", ipl->initrd);
    216                return;
    217            }
    218
    219            /*
    220             * we have to overwrite values in the kernel image,
    221             * which are "rom"
    222             */
    223            romptr = rom_ptr(INITRD_PARM_START, 16);
    224            if (romptr) {
    225                stq_p(romptr, initrd_offset);
    226                stq_p(romptr + 1, initrd_size);
    227            }
    228        }
    229    }
    230    /*
    231     * Don't ever use the migrated values, they could come from a different
    232     * BIOS and therefore don't work. But still migrate the values, so
    233     * QEMUs relying on it don't break.
    234     */
    235    ipl->compat_start_addr = ipl->start_addr;
    236    ipl->compat_bios_start_addr = ipl->bios_start_addr;
    237    /*
    238     * Because this Device is not on any bus in the qbus tree (it is
    239     * not a sysbus device and it's not on some other bus like a PCI
    240     * bus) it will not be automatically reset by the 'reset the
    241     * sysbus' hook registered by vl.c like most devices. So we must
    242     * manually register a reset hook for it.
    243     * TODO: there should be a better way to do this.
    244     */
    245    qemu_register_reset(resettable_cold_reset_fn, dev);
    246}
    247
    248static Property s390_ipl_properties[] = {
    249    DEFINE_PROP_STRING("kernel", S390IPLState, kernel),
    250    DEFINE_PROP_STRING("initrd", S390IPLState, initrd),
    251    DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
    252    DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
    253    DEFINE_PROP_STRING("netboot_fw", S390IPLState, netboot_fw),
    254    DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
    255    DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration,
    256                     true),
    257    DEFINE_PROP_END_OF_LIST(),
    258};
    259
    260static void s390_ipl_set_boot_menu(S390IPLState *ipl)
    261{
    262    QemuOptsList *plist = qemu_find_opts("boot-opts");
    263    QemuOpts *opts = QTAILQ_FIRST(&plist->head);
    264    const char *tmp;
    265    unsigned long splash_time = 0;
    266
    267    if (!get_boot_device(0)) {
    268        if (boot_menu) {
    269            error_report("boot menu requires a bootindex to be specified for "
    270                         "the IPL device");
    271        }
    272        return;
    273    }
    274
    275    switch (ipl->iplb.pbt) {
    276    case S390_IPL_TYPE_CCW:
    277        /* In the absence of -boot menu, use zipl parameters */
    278        if (!qemu_opt_get(opts, "menu")) {
    279            ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_ZIPL;
    280            return;
    281        }
    282        break;
    283    case S390_IPL_TYPE_QEMU_SCSI:
    284        break;
    285    default:
    286        if (boot_menu) {
    287            error_report("boot menu is not supported for this device type");
    288        }
    289        return;
    290    }
    291
    292    if (!boot_menu) {
    293        return;
    294    }
    295
    296    ipl->qipl.qipl_flags |= QIPL_FLAG_BM_OPTS_CMD;
    297
    298    tmp = qemu_opt_get(opts, "splash-time");
    299
    300    if (tmp && qemu_strtoul(tmp, NULL, 10, &splash_time)) {
    301        error_report("splash-time is invalid, forcing it to 0");
    302        ipl->qipl.boot_menu_timeout = 0;
    303        return;
    304    }
    305
    306    if (splash_time > 0xffffffff) {
    307        error_report("splash-time is too large, forcing it to max value");
    308        ipl->qipl.boot_menu_timeout = 0xffffffff;
    309        return;
    310    }
    311
    312    ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time);
    313}
    314
    315#define CCW_DEVTYPE_NONE        0x00
    316#define CCW_DEVTYPE_VIRTIO      0x01
    317#define CCW_DEVTYPE_VIRTIO_NET  0x02
    318#define CCW_DEVTYPE_SCSI        0x03
    319#define CCW_DEVTYPE_VFIO        0x04
    320
    321static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
    322{
    323    CcwDevice *ccw_dev = NULL;
    324    int tmp_dt = CCW_DEVTYPE_NONE;
    325
    326    if (dev_st) {
    327        VirtIONet *virtio_net_dev = (VirtIONet *)
    328            object_dynamic_cast(OBJECT(dev_st), TYPE_VIRTIO_NET);
    329        VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
    330            object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
    331                                TYPE_VIRTIO_CCW_DEVICE);
    332        VFIOCCWDevice *vfio_ccw_dev = (VFIOCCWDevice *)
    333            object_dynamic_cast(OBJECT(dev_st), TYPE_VFIO_CCW);
    334
    335        if (virtio_ccw_dev) {
    336            ccw_dev = CCW_DEVICE(virtio_ccw_dev);
    337            if (virtio_net_dev) {
    338                tmp_dt = CCW_DEVTYPE_VIRTIO_NET;
    339            } else {
    340                tmp_dt = CCW_DEVTYPE_VIRTIO;
    341            }
    342        } else if (vfio_ccw_dev) {
    343            ccw_dev = CCW_DEVICE(vfio_ccw_dev);
    344            tmp_dt = CCW_DEVTYPE_VFIO;
    345        } else {
    346            SCSIDevice *sd = (SCSIDevice *)
    347                object_dynamic_cast(OBJECT(dev_st),
    348                                    TYPE_SCSI_DEVICE);
    349            if (sd) {
    350                SCSIBus *bus = scsi_bus_from_device(sd);
    351                VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
    352                VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw,
    353                                                       vdev);
    354
    355                ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
    356                                                           TYPE_CCW_DEVICE);
    357                tmp_dt = CCW_DEVTYPE_SCSI;
    358            }
    359        }
    360    }
    361    if (devtype) {
    362        *devtype = tmp_dt;
    363    }
    364    return ccw_dev;
    365}
    366
    367static bool s390_gen_initial_iplb(S390IPLState *ipl)
    368{
    369    DeviceState *dev_st;
    370    CcwDevice *ccw_dev = NULL;
    371    SCSIDevice *sd;
    372    int devtype;
    373
    374    dev_st = get_boot_device(0);
    375    if (dev_st) {
    376        ccw_dev = s390_get_ccw_device(dev_st, &devtype);
    377    }
    378
    379    /*
    380     * Currently allow IPL only from CCW devices.
    381     */
    382    if (ccw_dev) {
    383        switch (devtype) {
    384        case CCW_DEVTYPE_SCSI:
    385            sd = SCSI_DEVICE(dev_st);
    386            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
    387            ipl->iplb.blk0_len =
    388                cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
    389            ipl->iplb.pbt = S390_IPL_TYPE_QEMU_SCSI;
    390            ipl->iplb.scsi.lun = cpu_to_be32(sd->lun);
    391            ipl->iplb.scsi.target = cpu_to_be16(sd->id);
    392            ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
    393            ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
    394            ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
    395            break;
    396        case CCW_DEVTYPE_VFIO:
    397            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
    398            ipl->iplb.pbt = S390_IPL_TYPE_CCW;
    399            ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
    400            ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
    401            break;
    402        case CCW_DEVTYPE_VIRTIO_NET:
    403            ipl->netboot = true;
    404            /* Fall through to CCW_DEVTYPE_VIRTIO case */
    405        case CCW_DEVTYPE_VIRTIO:
    406            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
    407            ipl->iplb.blk0_len =
    408                cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
    409            ipl->iplb.pbt = S390_IPL_TYPE_CCW;
    410            ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
    411            ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
    412            break;
    413        }
    414
    415        if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
    416            ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
    417        }
    418
    419        return true;
    420    }
    421
    422    return false;
    423}
    424
    425int s390_ipl_set_loadparm(uint8_t *loadparm)
    426{
    427    MachineState *machine = MACHINE(qdev_get_machine());
    428    char *lp = object_property_get_str(OBJECT(machine), "loadparm", NULL);
    429
    430    if (lp) {
    431        int i;
    432
    433        /* lp is an uppercase string without leading/embedded spaces */
    434        for (i = 0; i < 8 && lp[i]; i++) {
    435            loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]];
    436        }
    437
    438        if (i < 8) {
    439            memset(loadparm + i, 0x40, 8 - i); /* fill with EBCDIC spaces */
    440        }
    441
    442        g_free(lp);
    443        return 0;
    444    }
    445
    446    return -1;
    447}
    448
    449static int load_netboot_image(Error **errp)
    450{
    451    MachineState *ms = MACHINE(qdev_get_machine());
    452    S390IPLState *ipl = get_ipl_device();
    453    char *netboot_filename;
    454    MemoryRegion *sysmem =  get_system_memory();
    455    MemoryRegion *mr = NULL;
    456    void *ram_ptr = NULL;
    457    int img_size = -1;
    458
    459    mr = memory_region_find(sysmem, 0, 1).mr;
    460    if (!mr) {
    461        error_setg(errp, "Failed to find memory region at address 0");
    462        return -1;
    463    }
    464
    465    ram_ptr = memory_region_get_ram_ptr(mr);
    466    if (!ram_ptr) {
    467        error_setg(errp, "No RAM found");
    468        goto unref_mr;
    469    }
    470
    471    netboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->netboot_fw);
    472    if (netboot_filename == NULL) {
    473        error_setg(errp, "Could not find network bootloader '%s'",
    474                   ipl->netboot_fw);
    475        goto unref_mr;
    476    }
    477
    478    img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
    479                            &ipl->start_addr,
    480                            NULL, NULL, NULL, 1, EM_S390, 0, 0, NULL,
    481                            false);
    482
    483    if (img_size < 0) {
    484        img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size);
    485        ipl->start_addr = KERN_IMAGE_START;
    486    }
    487
    488    if (img_size < 0) {
    489        error_setg(errp, "Failed to load network bootloader");
    490    }
    491
    492    g_free(netboot_filename);
    493
    494unref_mr:
    495    memory_region_unref(mr);
    496    return img_size;
    497}
    498
    499static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb,
    500                                         int virtio_id)
    501{
    502    uint8_t cssid;
    503    uint8_t ssid;
    504    uint16_t devno;
    505    uint16_t schid;
    506    SubchDev *sch = NULL;
    507
    508    if (iplb->pbt != S390_IPL_TYPE_CCW) {
    509        return false;
    510    }
    511
    512    devno = be16_to_cpu(iplb->ccw.devno);
    513    ssid = iplb->ccw.ssid & 3;
    514
    515    for (schid = 0; schid < MAX_SCHID; schid++) {
    516        for (cssid = 0; cssid < MAX_CSSID; cssid++) {
    517            sch = css_find_subch(1, cssid, ssid, schid);
    518
    519            if (sch && sch->devno == devno) {
    520                return sch->id.cu_model == virtio_id;
    521            }
    522        }
    523    }
    524    return false;
    525}
    526
    527static bool is_virtio_net_device(IplParameterBlock *iplb)
    528{
    529    return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET);
    530}
    531
    532static bool is_virtio_scsi_device(IplParameterBlock *iplb)
    533{
    534    return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI);
    535}
    536
    537static void update_machine_ipl_properties(IplParameterBlock *iplb)
    538{
    539    Object *machine = qdev_get_machine();
    540    Error *err = NULL;
    541
    542    /* Sync loadparm */
    543    if (iplb->flags & DIAG308_FLAGS_LP_VALID) {
    544        uint8_t *ebcdic_loadparm = iplb->loadparm;
    545        char ascii_loadparm[9];
    546        int i;
    547
    548        for (i = 0; i < 8 && ebcdic_loadparm[i]; i++) {
    549            ascii_loadparm[i] = ebcdic2ascii[(uint8_t) ebcdic_loadparm[i]];
    550        }
    551        ascii_loadparm[i] = 0;
    552        object_property_set_str(machine, "loadparm", ascii_loadparm, &err);
    553    } else {
    554        object_property_set_str(machine, "loadparm", "", &err);
    555    }
    556    if (err) {
    557        warn_report_err(err);
    558    }
    559}
    560
    561void s390_ipl_update_diag308(IplParameterBlock *iplb)
    562{
    563    S390IPLState *ipl = get_ipl_device();
    564
    565    /*
    566     * The IPLB set and retrieved by subcodes 8/9 is completely
    567     * separate from the one managed via subcodes 5/6.
    568     */
    569    if (iplb->pbt == S390_IPL_TYPE_PV) {
    570        ipl->iplb_pv = *iplb;
    571        ipl->iplb_valid_pv = true;
    572    } else {
    573        ipl->iplb = *iplb;
    574        ipl->iplb_valid = true;
    575    }
    576    ipl->netboot = is_virtio_net_device(iplb);
    577    update_machine_ipl_properties(iplb);
    578}
    579
    580IplParameterBlock *s390_ipl_get_iplb_pv(void)
    581{
    582    S390IPLState *ipl = get_ipl_device();
    583
    584    if (!ipl->iplb_valid_pv) {
    585        return NULL;
    586    }
    587    return &ipl->iplb_pv;
    588}
    589
    590IplParameterBlock *s390_ipl_get_iplb(void)
    591{
    592    S390IPLState *ipl = get_ipl_device();
    593
    594    if (!ipl->iplb_valid) {
    595        return NULL;
    596    }
    597    return &ipl->iplb;
    598}
    599
    600void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type)
    601{
    602    S390IPLState *ipl = get_ipl_device();
    603
    604    if (reset_type == S390_RESET_EXTERNAL || reset_type == S390_RESET_REIPL) {
    605        /* use CPU 0 for full resets */
    606        ipl->reset_cpu_index = 0;
    607    } else {
    608        ipl->reset_cpu_index = cs->cpu_index;
    609    }
    610    ipl->reset_type = reset_type;
    611
    612    if (reset_type == S390_RESET_REIPL &&
    613        ipl->iplb_valid &&
    614        !ipl->netboot &&
    615        ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
    616        is_virtio_scsi_device(&ipl->iplb)) {
    617        CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0), NULL);
    618
    619        if (ccw_dev &&
    620            cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
    621            (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) {
    622            /*
    623             * this is the original boot device's SCSI
    624             * so restore IPL parameter info from it
    625             */
    626            ipl->iplb_valid = s390_gen_initial_iplb(ipl);
    627        }
    628    }
    629    if (reset_type == S390_RESET_MODIFIED_CLEAR ||
    630        reset_type == S390_RESET_LOAD_NORMAL ||
    631        reset_type == S390_RESET_PV) {
    632        /* ignore -no-reboot, send no event  */
    633        qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET);
    634    } else {
    635        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
    636    }
    637    /* as this is triggered by a CPU, make sure to exit the loop */
    638    if (tcg_enabled()) {
    639        cpu_loop_exit(cs);
    640    }
    641}
    642
    643void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type)
    644{
    645    S390IPLState *ipl = get_ipl_device();
    646
    647    *cs = qemu_get_cpu(ipl->reset_cpu_index);
    648    if (!*cs) {
    649        /* use any CPU */
    650        *cs = first_cpu;
    651    }
    652    *reset_type = ipl->reset_type;
    653}
    654
    655void s390_ipl_clear_reset_request(void)
    656{
    657    S390IPLState *ipl = get_ipl_device();
    658
    659    ipl->reset_type = S390_RESET_EXTERNAL;
    660    /* use CPU 0 for full resets */
    661    ipl->reset_cpu_index = 0;
    662}
    663
    664static void s390_ipl_prepare_qipl(S390CPU *cpu)
    665{
    666    S390IPLState *ipl = get_ipl_device();
    667    uint8_t *addr;
    668    uint64_t len = 4096;
    669
    670    addr = cpu_physical_memory_map(cpu->env.psa, &len, true);
    671    if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) {
    672        error_report("Cannot set QEMU IPL parameters");
    673        return;
    674    }
    675    memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters));
    676    cpu_physical_memory_unmap(addr, len, 1, len);
    677}
    678
    679int s390_ipl_prepare_pv_header(void)
    680{
    681    IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
    682    IPLBlockPV *ipib_pv = &ipib->pv;
    683    void *hdr = g_malloc(ipib_pv->pv_header_len);
    684    int rc;
    685
    686    cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr,
    687                             ipib_pv->pv_header_len);
    688    rc = s390_pv_set_sec_parms((uintptr_t)hdr,
    689                               ipib_pv->pv_header_len);
    690    g_free(hdr);
    691    return rc;
    692}
    693
    694int s390_ipl_pv_unpack(void)
    695{
    696    IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
    697    IPLBlockPV *ipib_pv = &ipib->pv;
    698    int i, rc = 0;
    699
    700    for (i = 0; i < ipib_pv->num_comp; i++) {
    701        rc = s390_pv_unpack(ipib_pv->components[i].addr,
    702                            TARGET_PAGE_ALIGN(ipib_pv->components[i].size),
    703                            ipib_pv->components[i].tweak_pref);
    704        if (rc) {
    705            break;
    706        }
    707    }
    708    return rc;
    709}
    710
    711void s390_ipl_prepare_cpu(S390CPU *cpu)
    712{
    713    S390IPLState *ipl = get_ipl_device();
    714
    715    cpu->env.psw.addr = ipl->start_addr;
    716    cpu->env.psw.mask = IPL_PSW_MASK;
    717
    718    if (!ipl->kernel || ipl->iplb_valid) {
    719        cpu->env.psw.addr = ipl->bios_start_addr;
    720        if (!ipl->iplb_valid) {
    721            ipl->iplb_valid = s390_gen_initial_iplb(ipl);
    722        }
    723    }
    724    if (ipl->netboot) {
    725        load_netboot_image(&error_fatal);
    726        ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
    727    }
    728    s390_ipl_set_boot_menu(ipl);
    729    s390_ipl_prepare_qipl(cpu);
    730}
    731
    732static void s390_ipl_reset(DeviceState *dev)
    733{
    734    S390IPLState *ipl = S390_IPL(dev);
    735
    736    if (ipl->reset_type != S390_RESET_REIPL) {
    737        ipl->iplb_valid = false;
    738        memset(&ipl->iplb, 0, sizeof(IplParameterBlock));
    739    }
    740}
    741
    742static void s390_ipl_class_init(ObjectClass *klass, void *data)
    743{
    744    DeviceClass *dc = DEVICE_CLASS(klass);
    745
    746    dc->realize = s390_ipl_realize;
    747    device_class_set_props(dc, s390_ipl_properties);
    748    dc->reset = s390_ipl_reset;
    749    dc->vmsd = &vmstate_ipl;
    750    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    751    /* Reason: Loads the ROMs and thus can only be used one time - internally */
    752    dc->user_creatable = false;
    753}
    754
    755static const TypeInfo s390_ipl_info = {
    756    .class_init = s390_ipl_class_init,
    757    .parent = TYPE_DEVICE,
    758    .name  = TYPE_S390_IPL,
    759    .instance_size  = sizeof(S390IPLState),
    760};
    761
    762static void s390_ipl_register_types(void)
    763{
    764    type_register_static(&s390_ipl_info);
    765}
    766
    767type_init(s390_ipl_register_types)