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

3270-ccw.c (4638B)


      1/*
      2 * Emulated ccw-attached 3270 implementation
      3 *
      4 * Copyright 2017 IBM Corp.
      5 * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
      6 *            Jing Liu <liujbjl@linux.vnet.ibm.com>
      7 *
      8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
      9 * your option) any later version. See the COPYING file in the top-level
     10 * directory.
     11 */
     12
     13#include "qemu/osdep.h"
     14#include "qapi/error.h"
     15#include "qemu/module.h"
     16#include "hw/s390x/css.h"
     17#include "hw/s390x/css-bridge.h"
     18#include "hw/qdev-properties.h"
     19#include "hw/s390x/3270-ccw.h"
     20
     21/* Handle READ ccw commands from guest */
     22static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
     23{
     24    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
     25    CcwDevice *ccw_dev = CCW_DEVICE(dev);
     26    int len;
     27
     28    if (!ccw->cda) {
     29        return -EFAULT;
     30    }
     31
     32    len = ck->read_payload_3270(dev);
     33    if (len < 0) {
     34        return len;
     35    }
     36    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
     37
     38    return 0;
     39}
     40
     41/* Handle WRITE ccw commands to write data to client */
     42static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
     43{
     44    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
     45    CcwDevice *ccw_dev = CCW_DEVICE(dev);
     46    int len;
     47
     48    if (!ccw->cda) {
     49        return -EFAULT;
     50    }
     51
     52    len = ck->write_payload_3270(dev, ccw->cmd_code);
     53
     54    if (len <= 0) {
     55        return len ? len : -EIO;
     56    }
     57
     58    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
     59    return 0;
     60}
     61
     62static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
     63{
     64    int rc = 0;
     65    EmulatedCcw3270Device *dev = sch->driver_data;
     66
     67    switch (ccw.cmd_code) {
     68    case TC_WRITESF:
     69    case TC_WRITE:
     70    case TC_EWRITE:
     71    case TC_EWRITEA:
     72        rc = handle_payload_3270_write(dev, &ccw);
     73        break;
     74    case TC_RDBUF:
     75    case TC_READMOD:
     76        rc = handle_payload_3270_read(dev, &ccw);
     77        break;
     78    default:
     79        rc = -ENOSYS;
     80        break;
     81    }
     82
     83    if (rc == -EIO) {
     84        /* I/O error, specific devices generate specific conditions */
     85        SCHIB *schib = &sch->curr_status;
     86
     87        sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
     88        sch->sense_data[0] = 0x40;    /* intervention-req */
     89        schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
     90        schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
     91        schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
     92                   SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
     93    }
     94
     95    return rc;
     96}
     97
     98static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
     99{
    100    uint16_t chpid;
    101    EmulatedCcw3270Device *dev = EMULATED_CCW_3270(ds);
    102    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
    103    CcwDevice *cdev = CCW_DEVICE(ds);
    104    CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
    105    SubchDev *sch;
    106    Error *err = NULL;
    107
    108    sch = css_create_sch(cdev->devno, errp);
    109    if (!sch) {
    110        return;
    111    }
    112
    113    if (!ck->init) {
    114        goto out_err;
    115    }
    116
    117    sch->driver_data = dev;
    118    cdev->sch = sch;
    119    chpid = css_find_free_chpid(sch->cssid);
    120
    121    if (chpid > MAX_CHPID) {
    122        error_setg(&err, "No available chpid to use.");
    123        goto out_err;
    124    }
    125
    126    sch->id.reserved = 0xff;
    127    sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
    128    css_sch_build_virtual_schib(sch, (uint8_t)chpid,
    129                                EMULATED_CCW_3270_CHPID_TYPE);
    130    sch->do_subchannel_work = do_subchannel_work_virtual;
    131    sch->ccw_cb = emulated_ccw_3270_cb;
    132    sch->irb_cb = build_irb_virtual;
    133
    134    ck->init(dev, &err);
    135    if (err) {
    136        goto out_err;
    137    }
    138
    139    cdk->realize(cdev, &err);
    140    if (err) {
    141        goto out_err;
    142    }
    143
    144    return;
    145
    146out_err:
    147    error_propagate(errp, err);
    148    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
    149    cdev->sch = NULL;
    150    g_free(sch);
    151}
    152
    153static Property emulated_ccw_3270_properties[] = {
    154    DEFINE_PROP_END_OF_LIST(),
    155};
    156
    157static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data)
    158{
    159    DeviceClass *dc = DEVICE_CLASS(klass);
    160
    161    device_class_set_props(dc, emulated_ccw_3270_properties);
    162    dc->realize = emulated_ccw_3270_realize;
    163    dc->hotpluggable = false;
    164    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
    165}
    166
    167static const TypeInfo emulated_ccw_3270_info = {
    168    .name = TYPE_EMULATED_CCW_3270,
    169    .parent = TYPE_CCW_DEVICE,
    170    .instance_size = sizeof(EmulatedCcw3270Device),
    171    .class_init = emulated_ccw_3270_class_init,
    172    .class_size = sizeof(EmulatedCcw3270Class),
    173    .abstract = true,
    174};
    175
    176static void emulated_ccw_register(void)
    177{
    178    type_register_static(&emulated_ccw_3270_info);
    179}
    180
    181type_init(emulated_ccw_register)