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

css-bridge.c (4898B)


      1/*
      2 * css bridge implementation
      3 *
      4 * Copyright 2012,2016 IBM Corp.
      5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
      6 *            Pierre Morel <pmorel@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 "hw/hotplug.h"
     16#include "hw/qdev-properties.h"
     17#include "hw/sysbus.h"
     18#include "qemu/bitops.h"
     19#include "qemu/module.h"
     20#include "hw/s390x/css.h"
     21#include "ccw-device.h"
     22#include "hw/s390x/css-bridge.h"
     23
     24/*
     25 * Invoke device-specific unplug handler, disable the subchannel
     26 * (including sending a channel report to the guest) and remove the
     27 * device from the virtual css bus.
     28 */
     29static void ccw_device_unplug(HotplugHandler *hotplug_dev,
     30                              DeviceState *dev, Error **errp)
     31{
     32    CcwDevice *ccw_dev = CCW_DEVICE(dev);
     33    CCWDeviceClass *k = CCW_DEVICE_GET_CLASS(ccw_dev);
     34    SubchDev *sch = ccw_dev->sch;
     35    Error *err = NULL;
     36
     37    if (k->unplug) {
     38        k->unplug(hotplug_dev, dev, &err);
     39        if (err) {
     40            error_propagate(errp, err);
     41            return;
     42        }
     43    }
     44
     45    /*
     46     * We should arrive here only for device_del, since we don't support
     47     * direct hot(un)plug of channels.
     48     */
     49    assert(sch != NULL);
     50    /* Subchannel is now disabled and no longer valid. */
     51    sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
     52                                     PMCW_FLAGS_MASK_DNV);
     53
     54    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
     55
     56    qdev_unrealize(dev);
     57}
     58
     59static void virtual_css_bus_reset(BusState *qbus)
     60{
     61    /* This should actually be modelled via the generic css */
     62    css_reset();
     63}
     64
     65static char *virtual_css_bus_get_dev_path(DeviceState *dev)
     66{
     67    CcwDevice *ccw_dev = CCW_DEVICE(dev);
     68    SubchDev *sch = ccw_dev->sch;
     69    VirtualCssBridge *bridge =
     70        VIRTUAL_CSS_BRIDGE(qdev_get_parent_bus(dev)->parent);
     71
     72    /*
     73     * We can't provide a dev path for backward compatibility on
     74     * older machines, as it is visible in the migration stream.
     75     */
     76    return bridge->css_dev_path ?
     77        g_strdup_printf("/%02x.%1x.%04x", sch->cssid, sch->ssid, sch->devno) :
     78        NULL;
     79}
     80
     81static void virtual_css_bus_class_init(ObjectClass *klass, void *data)
     82{
     83    BusClass *k = BUS_CLASS(klass);
     84
     85    k->reset = virtual_css_bus_reset;
     86    k->get_dev_path = virtual_css_bus_get_dev_path;
     87}
     88
     89static const TypeInfo virtual_css_bus_info = {
     90    .name = TYPE_VIRTUAL_CSS_BUS,
     91    .parent = TYPE_BUS,
     92    .instance_size = sizeof(VirtualCssBus),
     93    .class_init = virtual_css_bus_class_init,
     94};
     95
     96VirtualCssBus *virtual_css_bus_init(void)
     97{
     98    VirtualCssBus *cbus;
     99    BusState *bus;
    100    DeviceState *dev;
    101
    102    /* Create bridge device */
    103    dev = qdev_new(TYPE_VIRTUAL_CSS_BRIDGE);
    104    object_property_add_child(qdev_get_machine(), TYPE_VIRTUAL_CSS_BRIDGE,
    105                              OBJECT(dev));
    106    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    107
    108    /* Create bus on bridge device */
    109    bus = qbus_new(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
    110    cbus = VIRTUAL_CSS_BUS(bus);
    111
    112    /* Enable hotplugging */
    113    qbus_set_hotplug_handler(bus, OBJECT(dev));
    114
    115    css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false,
    116                             0, &error_abort);
    117
    118    return cbus;
    119 }
    120
    121/***************** Virtual-css Bus Bridge Device ********************/
    122
    123static Property virtual_css_bridge_properties[] = {
    124    DEFINE_PROP_BOOL("css_dev_path", VirtualCssBridge, css_dev_path,
    125                     true),
    126    DEFINE_PROP_END_OF_LIST(),
    127};
    128
    129static bool prop_get_true(Object *obj, Error **errp)
    130{
    131    return true;
    132}
    133
    134static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
    135{
    136    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
    137    DeviceClass *dc = DEVICE_CLASS(klass);
    138
    139    hc->unplug = ccw_device_unplug;
    140    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    141    device_class_set_props(dc, virtual_css_bridge_properties);
    142    object_class_property_add_bool(klass, "cssid-unrestricted",
    143                                   prop_get_true, NULL);
    144    object_class_property_set_description(klass, "cssid-unrestricted",
    145            "A css device can use any cssid, regardless whether virtual"
    146            " or not (read only, always true)");
    147}
    148
    149static const TypeInfo virtual_css_bridge_info = {
    150    .name          = TYPE_VIRTUAL_CSS_BRIDGE,
    151    .parent        = TYPE_SYS_BUS_DEVICE,
    152    .instance_size = sizeof(VirtualCssBridge),
    153    .class_init    = virtual_css_bridge_class_init,
    154    .interfaces = (InterfaceInfo[]) {
    155        { TYPE_HOTPLUG_HANDLER },
    156        { }
    157    }
    158};
    159
    160static void virtual_css_register(void)
    161{
    162    type_register_static(&virtual_css_bridge_info);
    163    type_register_static(&virtual_css_bus_info);
    164}
    165
    166type_init(virtual_css_register)