vfio/migration: Emit VFIO migration QAPI event

Emit VFIO migration QAPI event when a VFIO device changes its migration
state. This can be used by management applications to get updates on the
current state of the VFIO device for their own purposes.

A new per VFIO device capability, "migration-events", is added so events
can be enabled only for the required devices. It is disabled by default.

Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Avihai Horon 2024-05-15 16:21:36 +03:00 committed by Cédric Le Goater
parent a0359b56ec
commit 5e1f8905ca
3 changed files with 59 additions and 3 deletions

View File

@ -24,6 +24,7 @@
#include "migration/register.h"
#include "migration/blocker.h"
#include "qapi/error.h"
#include "qapi/qapi-events-vfio.h"
#include "exec/ramlist.h"
#include "exec/ram_addr.h"
#include "pci.h"
@ -80,6 +81,58 @@ static const char *mig_state_to_str(enum vfio_device_mig_state state)
}
}
static VfioMigrationState
mig_state_to_qapi_state(enum vfio_device_mig_state state)
{
switch (state) {
case VFIO_DEVICE_STATE_STOP:
return QAPI_VFIO_MIGRATION_STATE_STOP;
case VFIO_DEVICE_STATE_RUNNING:
return QAPI_VFIO_MIGRATION_STATE_RUNNING;
case VFIO_DEVICE_STATE_STOP_COPY:
return QAPI_VFIO_MIGRATION_STATE_STOP_COPY;
case VFIO_DEVICE_STATE_RESUMING:
return QAPI_VFIO_MIGRATION_STATE_RESUMING;
case VFIO_DEVICE_STATE_RUNNING_P2P:
return QAPI_VFIO_MIGRATION_STATE_RUNNING_P2P;
case VFIO_DEVICE_STATE_PRE_COPY:
return QAPI_VFIO_MIGRATION_STATE_PRE_COPY;
case VFIO_DEVICE_STATE_PRE_COPY_P2P:
return QAPI_VFIO_MIGRATION_STATE_PRE_COPY_P2P;
default:
g_assert_not_reached();
}
}
static void vfio_migration_send_event(VFIODevice *vbasedev)
{
VFIOMigration *migration = vbasedev->migration;
DeviceState *dev = vbasedev->dev;
g_autofree char *qom_path = NULL;
Object *obj;
if (!vbasedev->migration_events) {
return;
}
g_assert(vbasedev->ops->vfio_get_object);
obj = vbasedev->ops->vfio_get_object(vbasedev);
g_assert(obj);
qom_path = object_get_canonical_path(obj);
qapi_event_send_vfio_migration(
dev->id, qom_path, mig_state_to_qapi_state(migration->device_state));
}
static void vfio_migration_set_device_state(VFIODevice *vbasedev,
enum vfio_device_mig_state state)
{
VFIOMigration *migration = vbasedev->migration;
migration->device_state = state;
vfio_migration_send_event(vbasedev);
}
static int vfio_migration_set_state(VFIODevice *vbasedev,
enum vfio_device_mig_state new_state,
enum vfio_device_mig_state recover_state,
@ -131,12 +184,12 @@ static int vfio_migration_set_state(VFIODevice *vbasedev,
goto reset_device;
}
migration->device_state = recover_state;
vfio_migration_set_device_state(vbasedev, recover_state);
return ret;
}
migration->device_state = new_state;
vfio_migration_set_device_state(vbasedev, new_state);
if (mig_state->data_fd != -1) {
if (migration->data_fd != -1) {
/*
@ -162,7 +215,7 @@ reset_device:
strerror(errno));
}
migration->device_state = VFIO_DEVICE_STATE_RUNNING;
vfio_migration_set_device_state(vbasedev, VFIO_DEVICE_STATE_RUNNING);
return ret;
}

View File

@ -3388,6 +3388,8 @@ static Property vfio_pci_dev_properties[] = {
VFIO_FEATURE_ENABLE_IGD_OPREGION_BIT, false),
DEFINE_PROP_ON_OFF_AUTO("enable-migration", VFIOPCIDevice,
vbasedev.enable_migration, ON_OFF_AUTO_AUTO),
DEFINE_PROP_BOOL("migration-events", VFIOPCIDevice,
vbasedev.migration_events, false),
DEFINE_PROP_BOOL("x-no-mmap", VFIOPCIDevice, vbasedev.no_mmap, false),
DEFINE_PROP_BOOL("x-balloon-allowed", VFIOPCIDevice,
vbasedev.ram_block_discard_allowed, false),

View File

@ -115,6 +115,7 @@ typedef struct VFIODevice {
bool no_mmap;
bool ram_block_discard_allowed;
OnOffAuto enable_migration;
bool migration_events;
VFIODeviceOps *ops;
unsigned int num_irqs;
unsigned int num_regions;