From: "Maciej S. Szmigiero" <[email protected]> A future patch will need an ability to register qdev VM state change handlers below and above the normal priority level for the registering device qdev tree depth, but still properly ordered with respect to handlers registered at other tree depths.
To implement this split the priority argument passed to qemu_add_vm_change_state_handler_prio_full() into two parts: its 15 most significant bits will now carry the actual qdev tree depth while the 16 least significant bits will now carry the caller provided priority adjustment value. Although this will limit the qdev tree to a depth of 32k such high limit shouldn't be a problem in practice. Signed-off-by: Maciej S. Szmigiero <[email protected]> --- hw/core/vm-change-state-handler.c | 22 +++++++++++++++------- hw/vfio/migration.c | 2 +- include/system/runstate.h | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/hw/core/vm-change-state-handler.c b/hw/core/vm-change-state-handler.c index 2c111350298d..3db0819984c6 100644 --- a/hw/core/vm-change-state-handler.c +++ b/hw/core/vm-change-state-handler.c @@ -19,9 +19,9 @@ #include "hw/core/qdev.h" #include "system/runstate.h" -static int qdev_get_dev_tree_depth(DeviceState *dev) +static unsigned int qdev_get_dev_tree_depth(DeviceState *dev) { - int depth; + unsigned int depth; for (depth = 0; dev; depth++) { BusState *bus = dev->parent_bus; @@ -61,20 +61,28 @@ VMChangeStateEntry *qdev_add_vm_change_state_handler(DeviceState *dev, void *opaque) { assert(!cb || !cb_ret); - return qdev_add_vm_change_state_handler_full(dev, cb, NULL, cb_ret, opaque); + return qdev_add_vm_change_state_handler_full(dev, cb, NULL, cb_ret, opaque, 0); } /* * Exactly like qdev_add_vm_change_state_handler() but passes a prepare_cb - * and the cb_ret arguments too. + * and the cb_ret arguments too and allows for adjustment of priority. */ VMChangeStateEntry *qdev_add_vm_change_state_handler_full( DeviceState *dev, VMChangeStateHandler *cb, VMChangeStateHandler *prepare_cb, - VMChangeStateHandlerWithRet *cb_ret, void *opaque) + VMChangeStateHandlerWithRet *cb_ret, void *opaque, int adj) { - int depth = qdev_get_dev_tree_depth(dev); + unsigned int depth = qdev_get_dev_tree_depth(dev); + int prio; + + /* 32k depth should be enough for everyone */ + assert(depth <= INT16_MAX); + + /* encode depth on 15 MSB and adj on 16 LSB */ + assert(adj >= INT16_MIN && adj <= INT16_MAX); + prio = (depth << 16) + (adj - INT16_MIN); assert(!cb || !cb_ret); return qemu_add_vm_change_state_handler_prio_full(cb, prepare_cb, cb_ret, - opaque, depth); + opaque, prio); } diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index dbfd13b83a15..9889b20ad7dd 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -1227,7 +1227,7 @@ static int vfio_migration_init(VFIODevice *vbasedev, Error **errp) vfio_vmstate_change_prepare : NULL; migration->vm_state = qdev_add_vm_change_state_handler_full( - vbasedev->dev, vfio_vmstate_change, prepare_cb, NULL, vbasedev); + vbasedev->dev, vfio_vmstate_change, prepare_cb, NULL, vbasedev, 0); migration_add_notifier(&migration->migration_state, vfio_migration_state_notifier); diff --git a/include/system/runstate.h b/include/system/runstate.h index 929379adae41..306e2684c195 100644 --- a/include/system/runstate.h +++ b/include/system/runstate.h @@ -69,7 +69,7 @@ VMChangeStateEntry *qdev_add_vm_change_state_handler(DeviceState *dev, void *opaque); VMChangeStateEntry *qdev_add_vm_change_state_handler_full( DeviceState *dev, VMChangeStateHandler *cb, VMChangeStateHandler *prepare_cb, - VMChangeStateHandlerWithRet *cb_ret, void *opaque); + VMChangeStateHandlerWithRet *cb_ret, void *opaque, int adj); void qemu_del_vm_change_state_handler(VMChangeStateEntry *e); /** * vm_state_notify: Notify the state of the VM
