A common pattern is that to delete memory subregions during realization error handling and unrealization. pci automatically automatically deletes the IO subregions, but the pattern is manually implemented in other places, which is tedious and error-prone.
Implement the logic to delete subregions in qdev to cover all devices. Signed-off-by: Akihiko Odaki <od...@rsg.ci.i.u-tokyo.ac.jp> --- include/hw/qdev-core.h | 2 ++ hw/core/qdev.c | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 530f3da70218df59da72dc7a975dca8265600e00..c2582a4d59b38152a00d066351492c2e2ae0718f 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -226,6 +226,7 @@ typedef QLIST_HEAD(, BusState) BusStateHead; struct DeviceState { /* private: */ Object parent_obj; + /* public: */ /** @@ -526,6 +527,7 @@ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp); * - unrealize any child buses by calling qbus_unrealize() * (this will recursively unrealize any devices on those buses) * - call the unrealize method of @dev + * - remove @dev from memory * * The device can then be freed by causing its reference count to go * to zero. diff --git a/hw/core/qdev.c b/hw/core/qdev.c index f600226176871361d7ff3875f5d06bd4e614be6e..8fdf6774f87ec8424348e8c9652dc4c99a2faeb5 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -451,6 +451,17 @@ static bool check_only_migratable(Object *obj, Error **errp) return true; } +static int del_memory_region(Object *child, void *opaque) +{ + MemoryRegion *mr = (MemoryRegion *)object_dynamic_cast(child, TYPE_MEMORY_REGION); + + if (mr && mr->container) { + memory_region_del_subregion(mr->container, mr); + } + + return 0; +} + static void device_set_realized(Object *obj, bool value, Error **errp) { DeviceState *dev = DEVICE(obj); @@ -582,6 +593,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) if (dc->unrealize) { dc->unrealize(dev); } + object_child_foreach(OBJECT(dev), del_memory_region, NULL); dev->pending_deleted_event = true; DEVICE_LISTENER_CALL(unrealize, Reverse, dev); } @@ -606,6 +618,8 @@ post_realize_fail: } fail: + object_child_foreach(OBJECT(dev), del_memory_region, NULL); + error_propagate(errp, local_err); if (unattached_parent) { /* -- 2.51.0