qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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  */
     29 static 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 
     59 static void virtual_css_bus_reset(BusState *qbus)
     60 {
     61     /* This should actually be modelled via the generic css */
     62     css_reset();
     63 }
     64 
     65 static 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 
     81 static 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 
     89 static 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 
     96 VirtualCssBus *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 
    123 static 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 
    129 static bool prop_get_true(Object *obj, Error **errp)
    130 {
    131     return true;
    132 }
    133 
    134 static 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 
    149 static 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 
    160 static void virtual_css_register(void)
    161 {
    162     type_register_static(&virtual_css_bridge_info);
    163     type_register_static(&virtual_css_bus_info);
    164 }
    165 
    166 type_init(virtual_css_register)