[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [qemu-s390x] [PATCH v1 2/8] qdev: introduce ResourceHandler as a fir
From: |
David Hildenbrand |
Subject: |
Re: [qemu-s390x] [PATCH v1 2/8] qdev: introduce ResourceHandler as a first-stage hotplug handler |
Date: |
Fri, 4 May 2018 16:22:39 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0 |
On 03.05.2018 17:49, David Hildenbrand wrote:
> Hotplug handlers usually do 3 things:
> 1. Allocate some resources for a new device
> 2. Make the new device visible for the guest
> 3. Notify the guest about the new device
>
> While 2. and 3. are only ever performed once for a device, there
> might be various resources to allocate. E.g. a MemoryDevice could be
> exposed via Virtio. The proxy device hotplug handler (e.g. virtio-pci,
> virtio-ccw) takes care of exposing the device to the guest. However,
> we also have to allocate system resources, like a portion in guest
> physical address space, which is to be handled by the machine.
>
> One key difference between a hotplug handler and a resource handler is
> that resource handlers have no "unplug_request". There is no
> communication with the guest (this is done by a "hotplug" handler). So
> conceptually, they are different.
>
> For now we live with the assumption, that - in additon to the existing
> hotplug handler which can do some resource asignment - at most one
> resource handler is necessary.
>
> We might even later decide to have multiple resource handlers for a
> specific device (e.g. one for each interface they implement). For now,
> this design is sufficient.
>
> Resource handlers have to run before the hotplug handler runs (esp
> before exposing the device to the guest).
>
> Signed-off-by: David Hildenbrand <address@hidden>
> ---
> hw/core/Makefile.objs | 1 +
> hw/core/qdev.c | 41 ++++++++++++++++++++++++++++++-
> hw/core/resource-handler.c | 57
> +++++++++++++++++++++++++++++++++++++++++++
> include/hw/boards.h | 9 +++++++
> include/hw/resource-handler.h | 46 ++++++++++++++++++++++++++++++++++
> 5 files changed, 153 insertions(+), 1 deletion(-)
> create mode 100644 hw/core/resource-handler.c
> create mode 100644 include/hw/resource-handler.h
>
> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
> index eb88ca979e..7474387fcd 100644
> --- a/hw/core/Makefile.objs
> +++ b/hw/core/Makefile.objs
> @@ -6,6 +6,7 @@ common-obj-$(CONFIG_SOFTMMU) += fw-path-provider.o
> # irq.o needed for qdev GPIO handling:
> common-obj-y += irq.o
> common-obj-y += hotplug.o
> +common-obj-y += resource-handler.o
> common-obj-$(CONFIG_SOFTMMU) += nmi.o
>
> common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index f6f92473b8..042e275884 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -35,6 +35,7 @@
> #include "qemu/error-report.h"
> #include "qemu/option.h"
> #include "hw/hotplug.h"
> +#include "hw/resource-handler.h"
> #include "hw/boards.h"
> #include "hw/sysbus.h"
>
> @@ -271,6 +272,17 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState
> *dev)
> return hotplug_ctrl;
> }
>
> +static ResourceHandler *qdev_get_resource_handler(DeviceState *dev)
> +{
> + MachineState *ms = MACHINE(qdev_get_machine());
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> +
> + if (mc->get_resource_handler) {
> + return mc->get_resource_handler(ms, dev);
> + }
> + return NULL;
> +}
> +
> static int qdev_reset_one(DeviceState *dev, void *opaque)
> {
> device_reset(dev);
> @@ -814,6 +826,7 @@ static void device_set_realized(Object *obj, bool value,
> Error **errp)
> {
> DeviceState *dev = DEVICE(obj);
> DeviceClass *dc = DEVICE_GET_CLASS(dev);
> + ResourceHandler *resource_ctrl;
> HotplugHandler *hotplug_ctrl;
> BusState *bus;
> Error *local_err = NULL;
> @@ -825,6 +838,8 @@ static void device_set_realized(Object *obj, bool value,
> Error **errp)
> return;
> }
>
> + resource_ctrl = qdev_get_resource_handler(dev);
> +
> if (value && !dev->realized) {
> if (!check_only_migratable(obj, &local_err)) {
> goto fail;
> @@ -840,6 +855,13 @@ static void device_set_realized(Object *obj, bool value,
> Error **errp)
> g_free(name);
> }
>
> + if (resource_ctrl) {
> + resource_handler_pre_assign(resource_ctrl, dev, &local_err);
> + if (local_err != NULL) {
> + goto fail;
> + }
> + }
> +
> hotplug_ctrl = qdev_get_hotplug_handler(dev);
> if (hotplug_ctrl) {
> hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);
> @@ -858,12 +880,19 @@ static void device_set_realized(Object *obj, bool
> value, Error **errp)
>
> DEVICE_LISTENER_CALL(realize, Forward, dev);
>
> + if (resource_ctrl) {
> + resource_handler_assign(resource_ctrl, dev, &local_err);
> + if (local_err != NULL) {
> + goto post_realize_fail;
> + }
> + }
> +
> if (hotplug_ctrl) {
> hotplug_handler_plug(hotplug_ctrl, dev, &local_err);
> }
>
> if (local_err != NULL) {
> - goto post_realize_fail;
> + goto post_assign_fail;
> }
>
> /*
> @@ -903,6 +932,11 @@ static void device_set_realized(Object *obj, bool value,
> Error **errp)
> if (qdev_get_vmsd(dev)) {
> vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> }
> +
> + if (resource_ctrl) {
> + resource_handler_unassign(resource_ctrl, dev);
> + }
> +
> if (dc->unrealize) {
> local_errp = local_err ? NULL : &local_err;
> dc->unrealize(dev, local_errp);
> @@ -928,6 +962,11 @@ child_realize_fail:
> vmstate_unregister(dev, qdev_get_vmsd(dev), dev);
> }
>
> +post_assign_fail:
> + if (resource_ctrl) {
> + resource_handler_unassign(resource_ctrl, dev);
> + }
> +
> post_realize_fail:
> g_free(dev->canonical_path);
> dev->canonical_path = NULL;
> diff --git a/hw/core/resource-handler.c b/hw/core/resource-handler.c
> new file mode 100644
> index 0000000000..0a1ff0e66a
> --- /dev/null
> +++ b/hw/core/resource-handler.c
> @@ -0,0 +1,57 @@
> +/*
> + * Resource handler interface.
> + *
> + * Copyright (c) 2018 Red Hat Inc.
> + *
> + * Authors:
> + * David Hildenbrand <address@hidden>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/resource-handler.h"
> +#include "qemu/module.h"
> +
> +void resource_handler_pre_assign(ResourceHandler *rh,
> + const DeviceState *dev, Error **errp)
> +{
> + ResourceHandlerClass *rhc = RESOURCE_HANDLER_GET_CLASS(rh);
> +
> + if (rhc->pre_assign) {
> + rhc->pre_assign(rh, dev, errp);
> + }
> +}
> +
> +void resource_handler_assign(ResourceHandler *rh, DeviceState *dev,
> + Error **errp)
> +{
> + ResourceHandlerClass *rhc = RESOURCE_HANDLER_GET_CLASS(rh);
> +
> + if (rhc->assign) {
> + rhc->assign(rh, dev, errp);
> + }
> +}
> +
> +void resource_handler_unassign(ResourceHandler *rh, DeviceState *dev)
> +{
> + ResourceHandlerClass *rhc = RESOURCE_HANDLER_GET_CLASS(rh);
> +
> + if (rhc->unassign) {
> + rhc->unassign(rh, dev);
> + }
> +}
> +
> +static const TypeInfo resource_handler_info = {
> + .name = TYPE_RESOURCE_HANDLER,
> + .parent = TYPE_INTERFACE,
> + .class_size = sizeof(ResourceHandlerClass),
> +};
> +
> +static void resource_handler_register_types(void)
> +{
> + type_register_static(&resource_handler_info);
> +}
> +
> +type_init(resource_handler_register_types)
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index 8748964e6f..ff5142d7c2 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -8,6 +8,7 @@
> #include "hw/qdev.h"
> #include "qom/object.h"
> #include "qom/cpu.h"
> +#include "hw/resource-handler.h"
>
> /**
> * memory_region_allocate_system_memory - Allocate a board's main memory
> @@ -115,6 +116,12 @@ typedef struct {
> * of HotplugHandler object, which handles hotplug operation
> * for a given @dev. It may return NULL if @dev doesn't require
> * any actions to be performed by hotplug handler.
> + * @get_resource_handler: this function is called when a new device is
> + * about to be hotplugged. If defined, it returns
> pointer
> + * to an instance of ResourceHandler object, which
> + * handles resource asignment for a given @dev. It
> + * may return NULL if @dev doesn't require any actions
> + * to be performed by a resource handler.
> * @cpu_index_to_instance_props:
> * used to provide @cpu_index to socket/core/thread number mapping,
> allowing
> * legacy code to perform maping from cpu_index to topology properties
> @@ -208,6 +215,8 @@ struct MachineClass {
>
> HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
> DeviceState *dev);
> + ResourceHandler *(*get_resource_handler)(MachineState *machine,
> + const DeviceState *dev);
> CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState
> *machine,
> unsigned cpu_index);
> const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine);
> diff --git a/include/hw/resource-handler.h b/include/hw/resource-handler.h
> new file mode 100644
> index 0000000000..3eda1bec5c
> --- /dev/null
> +++ b/include/hw/resource-handler.h
> @@ -0,0 +1,46 @@
> +/*
> + * Resource handler interface.
> + *
> + * Copyright (c) 2018 Red Hat Inc.
> + *
> + * Authors:
> + * David Hildenbrand <address@hidden>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#ifndef RESOURCE_HANDLER_H
> +#define RESOURCE_HANDLER_H
> +
> +#include "qom/object.h"
> +
> +#define TYPE_RESOURCE_HANDLER "resource-handler"
> +
> +#define RESOURCE_HANDLER_CLASS(klass) \
> + OBJECT_CLASS_CHECK(ResourceHandlerClass, (klass), TYPE_RESOURCE_HANDLER)
> +#define RESOURCE_HANDLER_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(ResourceHandlerClass, (obj), TYPE_RESOURCE_HANDLER)
> +#define RESOURCE_HANDLER(obj) \
> + INTERFACE_CHECK(ResourceHandler, (obj), TYPE_RESOURCE_HANDLER)
> +
> +typedef struct ResourceHandler {
> + Object Parent;
> +} ResourceHandler;
> +
> +typedef struct ResourceHandlerClass {
> + InterfaceClass parent;
> +
> + void (*pre_assign)(ResourceHandler *rh, const DeviceState *dev,
> + Error **errp);
> + void (*assign)(ResourceHandler *rh, DeviceState *dev, Error **errp);
> + void (*unassign)(ResourceHandler *rh, DeviceState *dev);
> +} ResourceHandlerClass;
> +
> +void resource_handler_pre_assign(ResourceHandler *rh, const DeviceState *dev,
> + Error **errp);
> +void resource_handler_assign(ResourceHandler *rh, DeviceState *dev,
> + Error **errp);
> +void resource_handler_unassign(ResourceHandler *rh, DeviceState *dev);
> +
> +#endif /* RESOURCE_HANDLER_H */
>
I did the following changes to make it pass "make check".
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 042e275884..efa59b9d1e 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -274,12 +274,18 @@ HotplugHandler
*qdev_get_hotplug_handler(DeviceState *dev)
static ResourceHandler *qdev_get_resource_handler(DeviceState *dev)
{
- MachineState *ms = MACHINE(qdev_get_machine());
- MachineClass *mc = MACHINE_GET_CLASS(ms);
+ MachineState *ms;
+ MachineClass *mc;
+ Object *m_obj = qdev_get_machine();
- if (mc->get_resource_handler) {
- return mc->get_resource_handler(ms, dev);
+ if (object_dynamic_cast(m_obj, TYPE_MACHINE)) {
+ ms = MACHINE(m_obj);
+ mc = MACHINE_GET_CLASS(ms);
+ if (mc->get_resource_handler) {
+ return mc->get_resource_handler(ms, dev);
+ }
}
+
return NULL;
}
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 3b9a5e31a2..45c64bee64 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -645,6 +645,7 @@ tests/atomic_add-bench$(EXESUF):
tests/atomic_add-bench.o $(test-util-obj-y)
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
+ hw/core/resource-handler.o \
hw/core/bus.o \
hw/core/irq.o \
hw/core/fw-path-provider.o \
--
Thanks,
David / dhildenb
- [qemu-s390x] [PATCH v1 0/8] MemoryDevice: introduce and use ResourceHandler, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 1/8] memory-device: always compile support for memory devices for SOFTMMU, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 2/8] qdev: introduce ResourceHandler as a first-stage hotplug handler, David Hildenbrand, 2018/05/03
- Re: [qemu-s390x] [PATCH v1 2/8] qdev: introduce ResourceHandler as a first-stage hotplug handler,
David Hildenbrand <=
- [qemu-s390x] [PATCH v1 3/8] machine: provide default resource handler, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 4/8] memory-device: new functions to handle resource assignment, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 5/8] pc-dimm: implement new memory device functions, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 6/8] machine: introduce enforce_memory_device_align() and add it for pc, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 7/8] memory-device: factor out pre-assign into default resource handler, David Hildenbrand, 2018/05/03
- [qemu-s390x] [PATCH v1 8/8] memory-device: factor out (un)assign into default resource handler, David Hildenbrand, 2018/05/03
- Re: [qemu-s390x] [Qemu-devel] [PATCH v1 0/8] MemoryDevice: introduce and use ResourceHandler, Igor Mammedov, 2018/05/04