xref: /openbmc/qemu/hw/vfio/cpr-legacy.c (revision 54857b08168a0a74711d1f773c16a7122499027b)
1*54857b08SSteve Sistare /*
2*54857b08SSteve Sistare  * Copyright (c) 2021-2025 Oracle and/or its affiliates.
3*54857b08SSteve Sistare  *
4*54857b08SSteve Sistare  * SPDX-License-Identifier: GPL-2.0-or-later
5*54857b08SSteve Sistare  */
6*54857b08SSteve Sistare 
7*54857b08SSteve Sistare #include <sys/ioctl.h>
8*54857b08SSteve Sistare #include <linux/vfio.h>
9*54857b08SSteve Sistare #include "qemu/osdep.h"
10*54857b08SSteve Sistare #include "hw/vfio/vfio-container.h"
11*54857b08SSteve Sistare #include "migration/blocker.h"
12*54857b08SSteve Sistare #include "migration/cpr.h"
13*54857b08SSteve Sistare #include "migration/migration.h"
14*54857b08SSteve Sistare #include "migration/vmstate.h"
15*54857b08SSteve Sistare #include "qapi/error.h"
16*54857b08SSteve Sistare 
17*54857b08SSteve Sistare static bool vfio_cpr_supported(VFIOContainer *container, Error **errp)
18*54857b08SSteve Sistare {
19*54857b08SSteve Sistare     if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UPDATE_VADDR)) {
20*54857b08SSteve Sistare         error_setg(errp, "VFIO container does not support VFIO_UPDATE_VADDR");
21*54857b08SSteve Sistare         return false;
22*54857b08SSteve Sistare 
23*54857b08SSteve Sistare     } else if (!ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UNMAP_ALL)) {
24*54857b08SSteve Sistare         error_setg(errp, "VFIO container does not support VFIO_UNMAP_ALL");
25*54857b08SSteve Sistare         return false;
26*54857b08SSteve Sistare 
27*54857b08SSteve Sistare     } else {
28*54857b08SSteve Sistare         return true;
29*54857b08SSteve Sistare     }
30*54857b08SSteve Sistare }
31*54857b08SSteve Sistare 
32*54857b08SSteve Sistare static const VMStateDescription vfio_container_vmstate = {
33*54857b08SSteve Sistare     .name = "vfio-container",
34*54857b08SSteve Sistare     .version_id = 0,
35*54857b08SSteve Sistare     .minimum_version_id = 0,
36*54857b08SSteve Sistare     .needed = cpr_incoming_needed,
37*54857b08SSteve Sistare     .fields = (VMStateField[]) {
38*54857b08SSteve Sistare         VMSTATE_END_OF_LIST()
39*54857b08SSteve Sistare     }
40*54857b08SSteve Sistare };
41*54857b08SSteve Sistare 
42*54857b08SSteve Sistare bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp)
43*54857b08SSteve Sistare {
44*54857b08SSteve Sistare     VFIOContainerBase *bcontainer = &container->bcontainer;
45*54857b08SSteve Sistare     Error **cpr_blocker = &container->cpr.blocker;
46*54857b08SSteve Sistare 
47*54857b08SSteve Sistare     migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier,
48*54857b08SSteve Sistare                                 vfio_cpr_reboot_notifier,
49*54857b08SSteve Sistare                                 MIG_MODE_CPR_REBOOT);
50*54857b08SSteve Sistare 
51*54857b08SSteve Sistare     if (!vfio_cpr_supported(container, cpr_blocker)) {
52*54857b08SSteve Sistare         return migrate_add_blocker_modes(cpr_blocker, errp,
53*54857b08SSteve Sistare                                          MIG_MODE_CPR_TRANSFER, -1) == 0;
54*54857b08SSteve Sistare     }
55*54857b08SSteve Sistare 
56*54857b08SSteve Sistare     vmstate_register(NULL, -1, &vfio_container_vmstate, container);
57*54857b08SSteve Sistare 
58*54857b08SSteve Sistare     return true;
59*54857b08SSteve Sistare }
60*54857b08SSteve Sistare 
61*54857b08SSteve Sistare void vfio_legacy_cpr_unregister_container(VFIOContainer *container)
62*54857b08SSteve Sistare {
63*54857b08SSteve Sistare     VFIOContainerBase *bcontainer = &container->bcontainer;
64*54857b08SSteve Sistare 
65*54857b08SSteve Sistare     migration_remove_notifier(&bcontainer->cpr_reboot_notifier);
66*54857b08SSteve Sistare     migrate_del_blocker(&container->cpr.blocker);
67*54857b08SSteve Sistare     vmstate_unregister(NULL, &vfio_container_vmstate, container);
68*54857b08SSteve Sistare }
69