2015-11-06 14:32:40 +03:00
|
|
|
/*
|
|
|
|
* css bridge implementation
|
|
|
|
*
|
|
|
|
* Copyright 2012,2016 IBM Corp.
|
|
|
|
* Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
|
|
|
|
* Pierre Morel <pmorel@linux.vnet.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at
|
|
|
|
* your option) any later version. See the COPYING file in the top-level
|
|
|
|
* directory.
|
|
|
|
*/
|
2019-05-23 17:35:07 +03:00
|
|
|
|
2015-11-06 14:32:40 +03:00
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "hw/hotplug.h"
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-properties.h"
|
2015-11-06 14:32:40 +03:00
|
|
|
#include "hw/sysbus.h"
|
|
|
|
#include "qemu/bitops.h"
|
2019-05-23 17:35:07 +03:00
|
|
|
#include "qemu/module.h"
|
2015-11-06 14:32:40 +03:00
|
|
|
#include "hw/s390x/css.h"
|
2016-02-26 08:46:12 +03:00
|
|
|
#include "ccw-device.h"
|
2015-11-06 14:32:40 +03:00
|
|
|
#include "hw/s390x/css-bridge.h"
|
|
|
|
|
2016-02-26 08:46:12 +03:00
|
|
|
/*
|
|
|
|
* Invoke device-specific unplug handler, disable the subchannel
|
|
|
|
* (including sending a channel report to the guest) and remove the
|
|
|
|
* device from the virtual css bus.
|
|
|
|
*/
|
|
|
|
static void ccw_device_unplug(HotplugHandler *hotplug_dev,
|
|
|
|
DeviceState *dev, Error **errp)
|
|
|
|
{
|
|
|
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
|
|
|
CCWDeviceClass *k = CCW_DEVICE_GET_CLASS(ccw_dev);
|
|
|
|
SubchDev *sch = ccw_dev->sch;
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
if (k->unplug) {
|
|
|
|
k->unplug(hotplug_dev, dev, &err);
|
|
|
|
if (err) {
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We should arrive here only for device_del, since we don't support
|
|
|
|
* direct hot(un)plug of channels.
|
|
|
|
*/
|
|
|
|
assert(sch != NULL);
|
|
|
|
/* Subchannel is now disabled and no longer valid. */
|
|
|
|
sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
|
|
|
|
PMCW_FLAGS_MASK_DNV);
|
|
|
|
|
|
|
|
css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);
|
|
|
|
|
2020-06-10 08:31:56 +03:00
|
|
|
qdev_unrealize(dev);
|
2016-02-26 08:46:12 +03:00
|
|
|
}
|
|
|
|
|
2015-11-06 14:32:40 +03:00
|
|
|
static void virtual_css_bus_reset(BusState *qbus)
|
|
|
|
{
|
|
|
|
/* This should actually be modelled via the generic css */
|
|
|
|
css_reset();
|
|
|
|
}
|
|
|
|
|
2016-07-11 13:55:44 +03:00
|
|
|
static char *virtual_css_bus_get_dev_path(DeviceState *dev)
|
|
|
|
{
|
|
|
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
|
|
|
SubchDev *sch = ccw_dev->sch;
|
|
|
|
VirtualCssBridge *bridge =
|
|
|
|
VIRTUAL_CSS_BRIDGE(qdev_get_parent_bus(dev)->parent);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We can't provide a dev path for backward compatibility on
|
|
|
|
* older machines, as it is visible in the migration stream.
|
|
|
|
*/
|
|
|
|
return bridge->css_dev_path ?
|
|
|
|
g_strdup_printf("/%02x.%1x.%04x", sch->cssid, sch->ssid, sch->devno) :
|
|
|
|
NULL;
|
|
|
|
}
|
|
|
|
|
2015-11-06 14:32:40 +03:00
|
|
|
static void virtual_css_bus_class_init(ObjectClass *klass, void *data)
|
|
|
|
{
|
|
|
|
BusClass *k = BUS_CLASS(klass);
|
|
|
|
|
|
|
|
k->reset = virtual_css_bus_reset;
|
2016-07-11 13:55:44 +03:00
|
|
|
k->get_dev_path = virtual_css_bus_get_dev_path;
|
2015-11-06 14:32:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtual_css_bus_info = {
|
|
|
|
.name = TYPE_VIRTUAL_CSS_BUS,
|
|
|
|
.parent = TYPE_BUS,
|
|
|
|
.instance_size = sizeof(VirtualCssBus),
|
|
|
|
.class_init = virtual_css_bus_class_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
VirtualCssBus *virtual_css_bus_init(void)
|
|
|
|
{
|
|
|
|
VirtualCssBus *cbus;
|
|
|
|
BusState *bus;
|
|
|
|
DeviceState *dev;
|
|
|
|
|
|
|
|
/* Create bridge device */
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
dev = qdev_new(TYPE_VIRTUAL_CSS_BRIDGE);
|
2017-11-28 16:08:14 +03:00
|
|
|
object_property_add_child(qdev_get_machine(), TYPE_VIRTUAL_CSS_BRIDGE,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 18:29:22 +03:00
|
|
|
OBJECT(dev));
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2015-11-06 14:32:40 +03:00
|
|
|
|
|
|
|
/* Create bus on bridge device */
|
2021-09-23 15:11:52 +03:00
|
|
|
bus = qbus_new(TYPE_VIRTUAL_CSS_BUS, dev, "virtual-css");
|
2015-11-06 14:32:40 +03:00
|
|
|
cbus = VIRTUAL_CSS_BUS(bus);
|
|
|
|
|
|
|
|
/* Enable hotplugging */
|
qdev: Drop qbus_set_hotplug_handler() parameter @errp
qbus_set_hotplug_handler() is a simple wrapper around
object_property_set_link().
object_property_set_link() fails when the property doesn't exist, is
not settable, or its .check() method fails. These are all programming
errors here, so passing &error_abort to qbus_set_hotplug_handler() is
appropriate.
Most of its callers do. Exceptions:
* pcie_cap_slot_init(), shpc_init(), spapr_phb_realize() pass NULL,
i.e. they ignore errors.
* spapr_machine_init() passes &error_fatal.
* s390_pcihost_realize(), virtio_serial_device_realize(),
s390_pcihost_plug() pass the error to their callers. The latter two
keep going after the error, which looks wrong.
Drop the @errp parameter, and instead pass &error_abort to
object_property_set_link().
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20200630090351.1247703-15-armbru@redhat.com>
2020-06-30 12:03:39 +03:00
|
|
|
qbus_set_hotplug_handler(bus, OBJECT(dev));
|
2015-11-06 14:32:40 +03:00
|
|
|
|
2016-11-24 13:10:39 +03:00
|
|
|
css_register_io_adapters(CSS_IO_ADAPTER_VIRTIO, true, false,
|
2017-03-07 06:07:44 +03:00
|
|
|
0, &error_abort);
|
2016-11-24 13:10:39 +03:00
|
|
|
|
2015-11-06 14:32:40 +03:00
|
|
|
return cbus;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************** Virtual-css Bus Bridge Device ********************/
|
|
|
|
|
2016-07-11 13:55:44 +03:00
|
|
|
static Property virtual_css_bridge_properties[] = {
|
|
|
|
DEFINE_PROP_BOOL("css_dev_path", VirtualCssBridge, css_dev_path,
|
|
|
|
true),
|
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
|
};
|
|
|
|
|
2017-12-06 17:44:37 +03:00
|
|
|
static bool prop_get_true(Object *obj, Error **errp)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-11-06 14:32:40 +03:00
|
|
|
static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
|
|
|
|
{
|
|
|
|
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
|
|
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
|
|
2016-02-26 08:46:12 +03:00
|
|
|
hc->unplug = ccw_device_unplug;
|
2015-11-06 14:32:40 +03:00
|
|
|
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
2020-01-10 18:30:32 +03:00
|
|
|
device_class_set_props(dc, virtual_css_bridge_properties);
|
2017-12-06 17:44:37 +03:00
|
|
|
object_class_property_add_bool(klass, "cssid-unrestricted",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 18:29:22 +03:00
|
|
|
prop_get_true, NULL);
|
2017-12-06 17:44:37 +03:00
|
|
|
object_class_property_set_description(klass, "cssid-unrestricted",
|
|
|
|
"A css device can use any cssid, regardless whether virtual"
|
2020-05-05 18:29:15 +03:00
|
|
|
" or not (read only, always true)");
|
2015-11-06 14:32:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo virtual_css_bridge_info = {
|
|
|
|
.name = TYPE_VIRTUAL_CSS_BRIDGE,
|
|
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
2016-07-11 13:55:44 +03:00
|
|
|
.instance_size = sizeof(VirtualCssBridge),
|
2015-11-06 14:32:40 +03:00
|
|
|
.class_init = virtual_css_bridge_class_init,
|
|
|
|
.interfaces = (InterfaceInfo[]) {
|
|
|
|
{ TYPE_HOTPLUG_HANDLER },
|
|
|
|
{ }
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void virtual_css_register(void)
|
|
|
|
{
|
|
|
|
type_register_static(&virtual_css_bridge_info);
|
|
|
|
type_register_static(&virtual_css_bus_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(virtual_css_register)
|