vfio/container: register container for cpr

Register a legacy container for cpr-transfer, replacing the generic CPR
register call with a more specific legacy container register call.  Add a
blocker if the kernel does not support VFIO_UPDATE_VADDR or VFIO_UNMAP_ALL.

This is mostly boiler plate.  The fields to to saved and restored are added
in subsequent patches.

Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link: https://lore.kernel.org/qemu-devel/1749569991-25171-4-git-send-email-steven.sistare@oracle.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
Steve Sistare 2025-06-10 08:39:16 -07:00 committed by Cédric Le Goater
parent 081c09dc52
commit 54857b0816
6 changed files with 91 additions and 7 deletions

View file

@ -33,7 +33,6 @@
#include "qapi/error.h"
#include "pci.h"
#include "hw/vfio/vfio-container.h"
#include "hw/vfio/vfio-cpr.h"
#include "vfio-helpers.h"
#include "vfio-listener.h"
@ -643,7 +642,7 @@ static bool vfio_container_connect(VFIOGroup *group, AddressSpace *as,
new_container = true;
bcontainer = &container->bcontainer;
if (!vfio_cpr_register_container(bcontainer, errp)) {
if (!vfio_legacy_cpr_register_container(container, errp)) {
goto fail;
}
@ -679,7 +678,7 @@ fail:
vioc->release(bcontainer);
}
if (new_container) {
vfio_cpr_unregister_container(bcontainer);
vfio_legacy_cpr_unregister_container(container);
object_unref(container);
}
if (fd >= 0) {
@ -720,7 +719,7 @@ static void vfio_container_disconnect(VFIOGroup *group)
VFIOAddressSpace *space = bcontainer->space;
trace_vfio_container_disconnect(container->fd);
vfio_cpr_unregister_container(bcontainer);
vfio_legacy_cpr_unregister_container(container);
close(container->fd);
object_unref(container);

68
hw/vfio/cpr-legacy.c Normal file
View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2021-2025 Oracle and/or its affiliates.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <sys/ioctl.h>
#include <linux/vfio.h>
#include "qemu/osdep.h"
#include "hw/vfio/vfio-container.h"
#include "migration/blocker.h"
#include "migration/cpr.h"
#include "migration/migration.h"
#include "migration/vmstate.h"
#include "qapi/error.h"
static bool vfio_cpr_supported(VFIOContainer *container, Error **errp)
{
if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UPDATE_VADDR)) {
error_setg(errp, "VFIO container does not support VFIO_UPDATE_VADDR");
return false;
} else if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UNMAP_ALL)) {
error_setg(errp, "VFIO container does not support VFIO_UNMAP_ALL");
return false;
} else {
return true;
}
}
static const VMStateDescription vfio_container_vmstate = {
.name = "vfio-container",
.version_id = 0,
.minimum_version_id = 0,
.needed = cpr_incoming_needed,
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
}
};
bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp)
{
VFIOContainerBase *bcontainer = &container->bcontainer;
Error **cpr_blocker = &container->cpr.blocker;
migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier,
vfio_cpr_reboot_notifier,
MIG_MODE_CPR_REBOOT);
if (!vfio_cpr_supported(container, cpr_blocker)) {
return migrate_add_blocker_modes(cpr_blocker, errp,
MIG_MODE_CPR_TRANSFER, -1) == 0;
}
vmstate_register(NULL, -1, &vfio_container_vmstate, container);
return true;
}
void vfio_legacy_cpr_unregister_container(VFIOContainer *container)
{
VFIOContainerBase *bcontainer = &container->bcontainer;
migration_remove_notifier(&bcontainer->cpr_reboot_notifier);
migrate_del_blocker(&container->cpr.blocker);
vmstate_unregister(NULL, &vfio_container_vmstate, container);
}

View file

@ -7,13 +7,12 @@
#include "qemu/osdep.h"
#include "hw/vfio/vfio-device.h"
#include "migration/misc.h"
#include "hw/vfio/vfio-cpr.h"
#include "qapi/error.h"
#include "system/runstate.h"
static int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier,
MigrationEvent *e, Error **errp)
int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier,
MigrationEvent *e, Error **errp)
{
if (e->type == MIG_EVENT_PRECOPY_SETUP &&
!runstate_check(RUN_STATE_SUSPENDED) && !vm_get_suspended()) {

View file

@ -21,6 +21,7 @@ system_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c'))
system_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c'))
system_ss.add(when: 'CONFIG_VFIO', if_true: files(
'cpr.c',
'cpr-legacy.c',
'device.c',
'migration.c',
'migration-multifd.c',

View file

@ -10,6 +10,7 @@
#define HW_VFIO_CONTAINER_H
#include "hw/vfio/vfio-container-base.h"
#include "hw/vfio/vfio-cpr.h"
typedef struct VFIOContainer VFIOContainer;
typedef struct VFIODevice VFIODevice;
@ -29,6 +30,7 @@ typedef struct VFIOContainer {
int fd; /* /dev/vfio/vfio, empowered by the attached groups */
unsigned iommu_type;
QLIST_HEAD(, VFIOGroup) group_list;
VFIOContainerCPR cpr;
} VFIOContainer;
OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY);

View file

@ -9,8 +9,23 @@
#ifndef HW_VFIO_VFIO_CPR_H
#define HW_VFIO_VFIO_CPR_H
#include "migration/misc.h"
struct VFIOContainer;
struct VFIOContainerBase;
typedef struct VFIOContainerCPR {
Error *blocker;
} VFIOContainerCPR;
bool vfio_legacy_cpr_register_container(struct VFIOContainer *container,
Error **errp);
void vfio_legacy_cpr_unregister_container(struct VFIOContainer *container);
int vfio_cpr_reboot_notifier(NotifierWithReturn *notifier, MigrationEvent *e,
Error **errp);
bool vfio_cpr_register_container(struct VFIOContainerBase *bcontainer,
Error **errp);
void vfio_cpr_unregister_container(struct VFIOContainerBase *bcontainer);