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

ioinst.c (22669B)


      1/*
      2 * I/O instructions for S/390
      3 *
      4 * Copyright 2012, 2015 IBM Corp.
      5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
      6 *
      7 * This work is licensed under the terms of the GNU GPL, version 2 or (at
      8 * your option) any later version. See the COPYING file in the top-level
      9 * directory.
     10 */
     11
     12#include "qemu/osdep.h"
     13
     14#include "cpu.h"
     15#include "s390x-internal.h"
     16#include "hw/s390x/ioinst.h"
     17#include "trace.h"
     18#include "hw/s390x/s390-pci-bus.h"
     19#include "hw/s390x/pv.h"
     20
     21/* All I/O instructions but chsc use the s format */
     22static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb,
     23                                      uint8_t *ar)
     24{
     25    /*
     26     * Addresses for protected guests are all offsets into the
     27     * satellite block which holds the IO control structures. Those
     28     * control structures are always starting at offset 0 and are
     29     * always aligned and accessible. So we can return 0 here which
     30     * will pass the following address checks.
     31     */
     32    if (s390_is_pv()) {
     33        *ar = 0;
     34        return 0;
     35    }
     36    return decode_basedisp_s(env, ipb, ar);
     37}
     38
     39int ioinst_disassemble_sch_ident(uint32_t value, int *m, int *cssid, int *ssid,
     40                                 int *schid)
     41{
     42    if (!IOINST_SCHID_ONE(value)) {
     43        return -EINVAL;
     44    }
     45    if (!IOINST_SCHID_M(value)) {
     46        if (IOINST_SCHID_CSSID(value)) {
     47            return -EINVAL;
     48        }
     49        *cssid = 0;
     50        *m = 0;
     51    } else {
     52        *cssid = IOINST_SCHID_CSSID(value);
     53        *m = 1;
     54    }
     55    *ssid = IOINST_SCHID_SSID(value);
     56    *schid = IOINST_SCHID_NR(value);
     57    return 0;
     58}
     59
     60void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
     61{
     62    int cssid, ssid, schid, m;
     63    SubchDev *sch;
     64
     65    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
     66        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
     67        return;
     68    }
     69    trace_ioinst_sch_id("xsch", cssid, ssid, schid);
     70    sch = css_find_subch(m, cssid, ssid, schid);
     71    if (!sch || !css_subch_visible(sch)) {
     72        setcc(cpu, 3);
     73        return;
     74    }
     75    setcc(cpu, css_do_xsch(sch));
     76}
     77
     78void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
     79{
     80    int cssid, ssid, schid, m;
     81    SubchDev *sch;
     82
     83    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
     84        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
     85        return;
     86    }
     87    trace_ioinst_sch_id("csch", cssid, ssid, schid);
     88    sch = css_find_subch(m, cssid, ssid, schid);
     89    if (!sch || !css_subch_visible(sch)) {
     90        setcc(cpu, 3);
     91        return;
     92    }
     93    setcc(cpu, css_do_csch(sch));
     94}
     95
     96void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
     97{
     98    int cssid, ssid, schid, m;
     99    SubchDev *sch;
    100
    101    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
    102        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
    103        return;
    104    }
    105    trace_ioinst_sch_id("hsch", cssid, ssid, schid);
    106    sch = css_find_subch(m, cssid, ssid, schid);
    107    if (!sch || !css_subch_visible(sch)) {
    108        setcc(cpu, 3);
    109        return;
    110    }
    111    setcc(cpu, css_do_hsch(sch));
    112}
    113
    114static int ioinst_schib_valid(SCHIB *schib)
    115{
    116    if ((be16_to_cpu(schib->pmcw.flags) & PMCW_FLAGS_MASK_INVALID) ||
    117        (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_INVALID)) {
    118        return 0;
    119    }
    120    /* Disallow extended measurements for now. */
    121    if (be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_XMWME) {
    122        return 0;
    123    }
    124    /* for MB format 1 bits 26-31 of word 11 must be 0 */
    125    /* MBA uses words 10 and 11, it means align on 2**6 */
    126    if ((be32_to_cpu(schib->pmcw.chars) & PMCW_CHARS_MASK_MBFC) &&
    127        (be64_to_cpu(schib->mba) & 0x03fUL)) {
    128        return 0;
    129    }
    130    return 1;
    131}
    132
    133void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
    134{
    135    int cssid, ssid, schid, m;
    136    SubchDev *sch;
    137    SCHIB schib;
    138    uint64_t addr;
    139    CPUS390XState *env = &cpu->env;
    140    uint8_t ar;
    141
    142    addr = get_address_from_regs(env, ipb, &ar);
    143    if (addr & 3) {
    144        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    145        return;
    146    }
    147    if (s390_is_pv()) {
    148        s390_cpu_pv_mem_read(cpu, addr, &schib, sizeof(schib));
    149    } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
    150        s390_cpu_virt_mem_handle_exc(cpu, ra);
    151        return;
    152    }
    153    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
    154        !ioinst_schib_valid(&schib)) {
    155        s390_program_interrupt(env, PGM_OPERAND, ra);
    156        return;
    157    }
    158    trace_ioinst_sch_id("msch", cssid, ssid, schid);
    159    sch = css_find_subch(m, cssid, ssid, schid);
    160    if (!sch || !css_subch_visible(sch)) {
    161        setcc(cpu, 3);
    162        return;
    163    }
    164    setcc(cpu, css_do_msch(sch, &schib));
    165}
    166
    167static void copy_orb_from_guest(ORB *dest, const ORB *src)
    168{
    169    dest->intparm = be32_to_cpu(src->intparm);
    170    dest->ctrl0 = be16_to_cpu(src->ctrl0);
    171    dest->lpm = src->lpm;
    172    dest->ctrl1 = src->ctrl1;
    173    dest->cpa = be32_to_cpu(src->cpa);
    174}
    175
    176static int ioinst_orb_valid(ORB *orb)
    177{
    178    if ((orb->ctrl0 & ORB_CTRL0_MASK_INVALID) ||
    179        (orb->ctrl1 & ORB_CTRL1_MASK_INVALID)) {
    180        return 0;
    181    }
    182    /* We don't support MIDA. */
    183    if (orb->ctrl1 & ORB_CTRL1_MASK_MIDAW) {
    184        return 0;
    185    }
    186    if ((orb->cpa & HIGH_ORDER_BIT) != 0) {
    187        return 0;
    188    }
    189    return 1;
    190}
    191
    192void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
    193{
    194    int cssid, ssid, schid, m;
    195    SubchDev *sch;
    196    ORB orig_orb, orb;
    197    uint64_t addr;
    198    CPUS390XState *env = &cpu->env;
    199    uint8_t ar;
    200
    201    addr = get_address_from_regs(env, ipb, &ar);
    202    if (addr & 3) {
    203        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    204        return;
    205    }
    206    if (s390_is_pv()) {
    207        s390_cpu_pv_mem_read(cpu, addr, &orig_orb, sizeof(orb));
    208    } else if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
    209        s390_cpu_virt_mem_handle_exc(cpu, ra);
    210        return;
    211    }
    212    copy_orb_from_guest(&orb, &orig_orb);
    213    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid) ||
    214        !ioinst_orb_valid(&orb)) {
    215        s390_program_interrupt(env, PGM_OPERAND, ra);
    216        return;
    217    }
    218    trace_ioinst_sch_id("ssch", cssid, ssid, schid);
    219    sch = css_find_subch(m, cssid, ssid, schid);
    220    if (!sch || !css_subch_visible(sch)) {
    221        setcc(cpu, 3);
    222        return;
    223    }
    224    setcc(cpu, css_do_ssch(sch, &orb));
    225}
    226
    227void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
    228{
    229    CRW crw;
    230    uint64_t addr;
    231    int cc;
    232    CPUS390XState *env = &cpu->env;
    233    uint8_t ar;
    234
    235    addr = get_address_from_regs(env, ipb, &ar);
    236    if (addr & 3) {
    237        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    238        return;
    239    }
    240
    241    cc = css_do_stcrw(&crw);
    242    /* 0 - crw stored, 1 - zeroes stored */
    243
    244    if (s390_is_pv()) {
    245        s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw));
    246        setcc(cpu, cc);
    247    } else {
    248        if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
    249            setcc(cpu, cc);
    250        } else {
    251            if (cc == 0) {
    252                /* Write failed: requeue CRW since STCRW is suppressing */
    253                css_undo_stcrw(&crw);
    254            }
    255            s390_cpu_virt_mem_handle_exc(cpu, ra);
    256        }
    257    }
    258}
    259
    260void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
    261                         uintptr_t ra)
    262{
    263    int cssid, ssid, schid, m;
    264    SubchDev *sch;
    265    uint64_t addr;
    266    int cc;
    267    SCHIB schib;
    268    CPUS390XState *env = &cpu->env;
    269    uint8_t ar;
    270
    271    addr = get_address_from_regs(env, ipb, &ar);
    272    if (addr & 3) {
    273        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    274        return;
    275    }
    276
    277    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
    278        /*
    279         * The Ultravisor checks schid bit 16 to be one and bits 0-12
    280         * to be 0 and injects a operand exception itself.
    281         *
    282         * Hence we should never end up here.
    283         */
    284        g_assert(!s390_is_pv());
    285        /*
    286         * As operand exceptions have a lower priority than access exceptions,
    287         * we check whether the memory area is writeable (injecting the
    288         * access execption if it is not) first.
    289         */
    290        if (!s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib))) {
    291            s390_program_interrupt(env, PGM_OPERAND, ra);
    292        } else {
    293            s390_cpu_virt_mem_handle_exc(cpu, ra);
    294        }
    295        return;
    296    }
    297    trace_ioinst_sch_id("stsch", cssid, ssid, schid);
    298    sch = css_find_subch(m, cssid, ssid, schid);
    299    if (sch) {
    300        if (css_subch_visible(sch)) {
    301            cc = css_do_stsch(sch, &schib);
    302        } else {
    303            /* Indicate no more subchannels in this css/ss */
    304            cc = 3;
    305        }
    306    } else {
    307        if (css_schid_final(m, cssid, ssid, schid)) {
    308            cc = 3; /* No more subchannels in this css/ss */
    309        } else {
    310            /* Store an empty schib. */
    311            memset(&schib, 0, sizeof(schib));
    312            cc = 0;
    313        }
    314    }
    315    if (cc != 3) {
    316        if (s390_is_pv()) {
    317            s390_cpu_pv_mem_write(cpu, addr, &schib, sizeof(schib));
    318        } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
    319                                           sizeof(schib)) != 0) {
    320            s390_cpu_virt_mem_handle_exc(cpu, ra);
    321            return;
    322        }
    323    } else {
    324        /* Access exceptions have a higher priority than cc3 */
    325        if (!s390_is_pv() &&
    326            s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
    327            s390_cpu_virt_mem_handle_exc(cpu, ra);
    328            return;
    329        }
    330    }
    331    setcc(cpu, cc);
    332}
    333
    334int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
    335{
    336    CPUS390XState *env = &cpu->env;
    337    int cssid, ssid, schid, m;
    338    SubchDev *sch;
    339    IRB irb;
    340    uint64_t addr;
    341    int cc, irb_len;
    342    uint8_t ar;
    343
    344    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
    345        s390_program_interrupt(env, PGM_OPERAND, ra);
    346        return -EIO;
    347    }
    348    trace_ioinst_sch_id("tsch", cssid, ssid, schid);
    349    addr = get_address_from_regs(env, ipb, &ar);
    350    if (addr & 3) {
    351        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    352        return -EIO;
    353    }
    354
    355    sch = css_find_subch(m, cssid, ssid, schid);
    356    if (sch && css_subch_visible(sch)) {
    357        cc = css_do_tsch_get_irb(sch, &irb, &irb_len);
    358    } else {
    359        cc = 3;
    360    }
    361    /* 0 - status pending, 1 - not status pending, 3 - not operational */
    362    if (cc != 3) {
    363        if (s390_is_pv()) {
    364            s390_cpu_pv_mem_write(cpu, addr, &irb, irb_len);
    365        } else if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
    366            s390_cpu_virt_mem_handle_exc(cpu, ra);
    367            return -EFAULT;
    368        }
    369        css_do_tsch_update_subch(sch);
    370    } else {
    371        irb_len = sizeof(irb) - sizeof(irb.emw);
    372        /* Access exceptions have a higher priority than cc3 */
    373        if (!s390_is_pv() &&
    374            s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
    375            s390_cpu_virt_mem_handle_exc(cpu, ra);
    376            return -EFAULT;
    377        }
    378    }
    379
    380    setcc(cpu, cc);
    381    return 0;
    382}
    383
    384typedef struct ChscReq {
    385    uint16_t len;
    386    uint16_t command;
    387    uint32_t param0;
    388    uint32_t param1;
    389    uint32_t param2;
    390} QEMU_PACKED ChscReq;
    391
    392typedef struct ChscResp {
    393    uint16_t len;
    394    uint16_t code;
    395    uint32_t param;
    396    char data[];
    397} QEMU_PACKED ChscResp;
    398
    399#define CHSC_MIN_RESP_LEN 0x0008
    400
    401#define CHSC_SCPD 0x0002
    402#define CHSC_SCSC 0x0010
    403#define CHSC_SDA  0x0031
    404#define CHSC_SEI  0x000e
    405
    406#define CHSC_SCPD_0_M 0x20000000
    407#define CHSC_SCPD_0_C 0x10000000
    408#define CHSC_SCPD_0_FMT 0x0f000000
    409#define CHSC_SCPD_0_CSSID 0x00ff0000
    410#define CHSC_SCPD_0_RFMT 0x00000f00
    411#define CHSC_SCPD_0_RES 0xc000f000
    412#define CHSC_SCPD_1_RES 0xffffff00
    413#define CHSC_SCPD_01_CHPID 0x000000ff
    414static void ioinst_handle_chsc_scpd(ChscReq *req, ChscResp *res)
    415{
    416    uint16_t len = be16_to_cpu(req->len);
    417    uint32_t param0 = be32_to_cpu(req->param0);
    418    uint32_t param1 = be32_to_cpu(req->param1);
    419    uint16_t resp_code;
    420    int rfmt;
    421    uint16_t cssid;
    422    uint8_t f_chpid, l_chpid;
    423    int desc_size;
    424    int m;
    425
    426    rfmt = (param0 & CHSC_SCPD_0_RFMT) >> 8;
    427    if ((rfmt == 0) ||  (rfmt == 1)) {
    428        rfmt = !!(param0 & CHSC_SCPD_0_C);
    429    }
    430    if ((len != 0x0010) || (param0 & CHSC_SCPD_0_RES) ||
    431        (param1 & CHSC_SCPD_1_RES) || req->param2) {
    432        resp_code = 0x0003;
    433        goto out_err;
    434    }
    435    if (param0 & CHSC_SCPD_0_FMT) {
    436        resp_code = 0x0007;
    437        goto out_err;
    438    }
    439    cssid = (param0 & CHSC_SCPD_0_CSSID) >> 16;
    440    m = param0 & CHSC_SCPD_0_M;
    441    if (cssid != 0) {
    442        if (!m || !css_present(cssid)) {
    443            resp_code = 0x0008;
    444            goto out_err;
    445        }
    446    }
    447    f_chpid = param0 & CHSC_SCPD_01_CHPID;
    448    l_chpid = param1 & CHSC_SCPD_01_CHPID;
    449    if (l_chpid < f_chpid) {
    450        resp_code = 0x0003;
    451        goto out_err;
    452    }
    453    /* css_collect_chp_desc() is endian-aware */
    454    desc_size = css_collect_chp_desc(m, cssid, f_chpid, l_chpid, rfmt,
    455                                     &res->data);
    456    res->code = cpu_to_be16(0x0001);
    457    res->len = cpu_to_be16(8 + desc_size);
    458    res->param = cpu_to_be32(rfmt);
    459    return;
    460
    461  out_err:
    462    res->code = cpu_to_be16(resp_code);
    463    res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
    464    res->param = cpu_to_be32(rfmt);
    465}
    466
    467#define CHSC_SCSC_0_M 0x20000000
    468#define CHSC_SCSC_0_FMT 0x000f0000
    469#define CHSC_SCSC_0_CSSID 0x0000ff00
    470#define CHSC_SCSC_0_RES 0xdff000ff
    471static void ioinst_handle_chsc_scsc(ChscReq *req, ChscResp *res)
    472{
    473    uint16_t len = be16_to_cpu(req->len);
    474    uint32_t param0 = be32_to_cpu(req->param0);
    475    uint8_t cssid;
    476    uint16_t resp_code;
    477    uint32_t general_chars[510];
    478    uint32_t chsc_chars[508];
    479
    480    if (len != 0x0010) {
    481        resp_code = 0x0003;
    482        goto out_err;
    483    }
    484
    485    if (param0 & CHSC_SCSC_0_FMT) {
    486        resp_code = 0x0007;
    487        goto out_err;
    488    }
    489    cssid = (param0 & CHSC_SCSC_0_CSSID) >> 8;
    490    if (cssid != 0) {
    491        if (!(param0 & CHSC_SCSC_0_M) || !css_present(cssid)) {
    492            resp_code = 0x0008;
    493            goto out_err;
    494        }
    495    }
    496    if ((param0 & CHSC_SCSC_0_RES) || req->param1 || req->param2) {
    497        resp_code = 0x0003;
    498        goto out_err;
    499    }
    500    res->code = cpu_to_be16(0x0001);
    501    res->len = cpu_to_be16(4080);
    502    res->param = 0;
    503
    504    memset(general_chars, 0, sizeof(general_chars));
    505    memset(chsc_chars, 0, sizeof(chsc_chars));
    506
    507    general_chars[0] = cpu_to_be32(0x03000000);
    508    general_chars[1] = cpu_to_be32(0x00079000);
    509    general_chars[3] = cpu_to_be32(0x00080000);
    510
    511    chsc_chars[0] = cpu_to_be32(0x40000000);
    512    chsc_chars[3] = cpu_to_be32(0x00040000);
    513
    514    memcpy(res->data, general_chars, sizeof(general_chars));
    515    memcpy(res->data + sizeof(general_chars), chsc_chars, sizeof(chsc_chars));
    516    return;
    517
    518  out_err:
    519    res->code = cpu_to_be16(resp_code);
    520    res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
    521    res->param = 0;
    522}
    523
    524#define CHSC_SDA_0_FMT 0x0f000000
    525#define CHSC_SDA_0_OC 0x0000ffff
    526#define CHSC_SDA_0_RES 0xf0ff0000
    527#define CHSC_SDA_OC_MCSSE 0x0
    528#define CHSC_SDA_OC_MSS 0x2
    529static void ioinst_handle_chsc_sda(ChscReq *req, ChscResp *res)
    530{
    531    uint16_t resp_code = 0x0001;
    532    uint16_t len = be16_to_cpu(req->len);
    533    uint32_t param0 = be32_to_cpu(req->param0);
    534    uint16_t oc;
    535    int ret;
    536
    537    if ((len != 0x0400) || (param0 & CHSC_SDA_0_RES)) {
    538        resp_code = 0x0003;
    539        goto out;
    540    }
    541
    542    if (param0 & CHSC_SDA_0_FMT) {
    543        resp_code = 0x0007;
    544        goto out;
    545    }
    546
    547    oc = param0 & CHSC_SDA_0_OC;
    548    switch (oc) {
    549    case CHSC_SDA_OC_MCSSE:
    550        ret = css_enable_mcsse();
    551        if (ret == -EINVAL) {
    552            resp_code = 0x0101;
    553            goto out;
    554        }
    555        break;
    556    case CHSC_SDA_OC_MSS:
    557        ret = css_enable_mss();
    558        if (ret == -EINVAL) {
    559            resp_code = 0x0101;
    560            goto out;
    561        }
    562        break;
    563    default:
    564        resp_code = 0x0003;
    565        goto out;
    566    }
    567
    568out:
    569    res->code = cpu_to_be16(resp_code);
    570    res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
    571    res->param = 0;
    572}
    573
    574static int chsc_sei_nt0_get_event(void *res)
    575{
    576    /* no events yet */
    577    return 1;
    578}
    579
    580static int chsc_sei_nt0_have_event(void)
    581{
    582    /* no events yet */
    583    return 0;
    584}
    585
    586static int chsc_sei_nt2_get_event(void *res)
    587{
    588    if (s390_has_feat(S390_FEAT_ZPCI)) {
    589        return pci_chsc_sei_nt2_get_event(res);
    590    }
    591    return 1;
    592}
    593
    594static int chsc_sei_nt2_have_event(void)
    595{
    596    if (s390_has_feat(S390_FEAT_ZPCI)) {
    597        return pci_chsc_sei_nt2_have_event();
    598    }
    599    return 0;
    600}
    601
    602#define CHSC_SEI_NT0    (1ULL << 63)
    603#define CHSC_SEI_NT2    (1ULL << 61)
    604static void ioinst_handle_chsc_sei(ChscReq *req, ChscResp *res)
    605{
    606    uint64_t selection_mask = ldq_p(&req->param1);
    607    uint8_t *res_flags = (uint8_t *)res->data;
    608    int have_event = 0;
    609    int have_more = 0;
    610
    611    /* regarding architecture nt0 can not be masked */
    612    have_event = !chsc_sei_nt0_get_event(res);
    613    have_more = chsc_sei_nt0_have_event();
    614
    615    if (selection_mask & CHSC_SEI_NT2) {
    616        if (!have_event) {
    617            have_event = !chsc_sei_nt2_get_event(res);
    618        }
    619
    620        if (!have_more) {
    621            have_more = chsc_sei_nt2_have_event();
    622        }
    623    }
    624
    625    if (have_event) {
    626        res->code = cpu_to_be16(0x0001);
    627        if (have_more) {
    628            (*res_flags) |= 0x80;
    629        } else {
    630            (*res_flags) &= ~0x80;
    631            css_clear_sei_pending();
    632        }
    633    } else {
    634        res->code = cpu_to_be16(0x0005);
    635        res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
    636    }
    637}
    638
    639static void ioinst_handle_chsc_unimplemented(ChscResp *res)
    640{
    641    res->len = cpu_to_be16(CHSC_MIN_RESP_LEN);
    642    res->code = cpu_to_be16(0x0004);
    643    res->param = 0;
    644}
    645
    646void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
    647{
    648    ChscReq *req;
    649    ChscResp *res;
    650    uint64_t addr = 0;
    651    int reg;
    652    uint16_t len;
    653    uint16_t command;
    654    CPUS390XState *env = &cpu->env;
    655    uint8_t buf[TARGET_PAGE_SIZE];
    656
    657    trace_ioinst("chsc");
    658    reg = (ipb >> 20) & 0x00f;
    659    if (!s390_is_pv()) {
    660        addr = env->regs[reg];
    661    }
    662    /* Page boundary? */
    663    if (addr & 0xfff) {
    664        s390_program_interrupt(env, PGM_SPECIFICATION, ra);
    665        return;
    666    }
    667    /*
    668     * Reading sizeof(ChscReq) bytes is currently enough for all of our
    669     * present CHSC sub-handlers ... if we ever need more, we should take
    670     * care of req->len here first.
    671     */
    672    if (s390_is_pv()) {
    673        s390_cpu_pv_mem_read(cpu, addr, buf, sizeof(ChscReq));
    674    } else if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
    675        s390_cpu_virt_mem_handle_exc(cpu, ra);
    676        return;
    677    }
    678    req = (ChscReq *)buf;
    679    len = be16_to_cpu(req->len);
    680    /* Length field valid? */
    681    if ((len < 16) || (len > 4088) || (len & 7)) {
    682        s390_program_interrupt(env, PGM_OPERAND, ra);
    683        return;
    684    }
    685    memset((char *)req + len, 0, TARGET_PAGE_SIZE - len);
    686    res = (void *)((char *)req + len);
    687    command = be16_to_cpu(req->command);
    688    trace_ioinst_chsc_cmd(command, len);
    689    switch (command) {
    690    case CHSC_SCSC:
    691        ioinst_handle_chsc_scsc(req, res);
    692        break;
    693    case CHSC_SCPD:
    694        ioinst_handle_chsc_scpd(req, res);
    695        break;
    696    case CHSC_SDA:
    697        ioinst_handle_chsc_sda(req, res);
    698        break;
    699    case CHSC_SEI:
    700        ioinst_handle_chsc_sei(req, res);
    701        break;
    702    default:
    703        ioinst_handle_chsc_unimplemented(res);
    704        break;
    705    }
    706
    707    if (s390_is_pv()) {
    708        s390_cpu_pv_mem_write(cpu, addr + len, res, be16_to_cpu(res->len));
    709        setcc(cpu, 0);    /* Command execution complete */
    710    } else {
    711        if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
    712                                     be16_to_cpu(res->len))) {
    713            setcc(cpu, 0);    /* Command execution complete */
    714        } else {
    715            s390_cpu_virt_mem_handle_exc(cpu, ra);
    716        }
    717    }
    718}
    719
    720#define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc)
    721#define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28)
    722#define SCHM_REG1_UPD(_reg) ((_reg & 0x0000000000000002) >> 1)
    723#define SCHM_REG1_DCT(_reg) (_reg & 0x0000000000000001)
    724
    725void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
    726                        uint32_t ipb, uintptr_t ra)
    727{
    728    uint8_t mbk;
    729    int update;
    730    int dct;
    731    CPUS390XState *env = &cpu->env;
    732
    733    trace_ioinst("schm");
    734
    735    if (SCHM_REG1_RES(reg1)) {
    736        s390_program_interrupt(env, PGM_OPERAND, ra);
    737        return;
    738    }
    739
    740    mbk = SCHM_REG1_MBK(reg1);
    741    update = SCHM_REG1_UPD(reg1);
    742    dct = SCHM_REG1_DCT(reg1);
    743
    744    if (update && (reg2 & 0x000000000000001f)) {
    745        s390_program_interrupt(env, PGM_OPERAND, ra);
    746        return;
    747    }
    748
    749    css_do_schm(mbk, update, dct, update ? reg2 : 0);
    750}
    751
    752void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
    753{
    754    int cssid, ssid, schid, m;
    755    SubchDev *sch;
    756
    757    if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
    758        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
    759        return;
    760    }
    761    trace_ioinst_sch_id("rsch", cssid, ssid, schid);
    762    sch = css_find_subch(m, cssid, ssid, schid);
    763    if (!sch || !css_subch_visible(sch)) {
    764        setcc(cpu, 3);
    765        return;
    766    }
    767    setcc(cpu, css_do_rsch(sch));
    768}
    769
    770#define RCHP_REG1_RES(_reg) (_reg & 0x00000000ff00ff00)
    771#define RCHP_REG1_CSSID(_reg) ((_reg & 0x0000000000ff0000) >> 16)
    772#define RCHP_REG1_CHPID(_reg) (_reg & 0x00000000000000ff)
    773void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
    774{
    775    int cc;
    776    uint8_t cssid;
    777    uint8_t chpid;
    778    int ret;
    779    CPUS390XState *env = &cpu->env;
    780
    781    if (RCHP_REG1_RES(reg1)) {
    782        s390_program_interrupt(env, PGM_OPERAND, ra);
    783        return;
    784    }
    785
    786    cssid = RCHP_REG1_CSSID(reg1);
    787    chpid = RCHP_REG1_CHPID(reg1);
    788
    789    trace_ioinst_chp_id("rchp", cssid, chpid);
    790
    791    ret = css_do_rchp(cssid, chpid);
    792
    793    switch (ret) {
    794    case -ENODEV:
    795        cc = 3;
    796        break;
    797    case -EBUSY:
    798        cc = 2;
    799        break;
    800    case 0:
    801        cc = 0;
    802        break;
    803    default:
    804        /* Invalid channel subsystem. */
    805        s390_program_interrupt(env, PGM_OPERAND, ra);
    806        return;
    807    }
    808    setcc(cpu, cc);
    809}
    810
    811#define SAL_REG1_INVALID(_reg) (_reg & 0x0000000080000000)
    812void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra)
    813{
    814    /* We do not provide address limit checking, so let's suppress it. */
    815    if (SAL_REG1_INVALID(reg1) || reg1 & 0x000000000000ffff) {
    816        s390_program_interrupt(&cpu->env, PGM_OPERAND, ra);
    817    }
    818}