Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107127135
D26387.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
29 KB
Referenced Files
None
Subscribers
None
D26387.diff
View Options
diff --git a/usr.sbin/bhyve/atkbdc.h b/usr.sbin/bhyve/atkbdc.h
--- a/usr.sbin/bhyve/atkbdc.h
+++ b/usr.sbin/bhyve/atkbdc.h
@@ -31,13 +31,14 @@
struct atkbdc_softc;
struct vm_snapshot_meta;
+struct vm_snapshot_dev_info;
struct vmctx;
void atkbdc_init(struct vmctx *ctx);
void atkbdc_event(struct atkbdc_softc *sc, int iskbd);
#ifdef BHYVE_SNAPSHOT
-int atkbdc_snapshot(struct vm_snapshot_meta *meta);
+int atkbdc_snapshot(struct vm_snapshot_meta *meta, struct vm_snapshot_dev_info *dev_info);
#endif
#endif /* _ATKBDC_H_ */
diff --git a/usr.sbin/bhyve/atkbdc.c b/usr.sbin/bhyve/atkbdc.c
--- a/usr.sbin/bhyve/atkbdc.c
+++ b/usr.sbin/bhyve/atkbdc.c
@@ -56,6 +56,10 @@
#include "ps2kbd.h"
#include "ps2mouse.h"
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#define KBD_DATA_PORT 0x60
#define KBD_STS_CTL_PORT 0x64
@@ -138,10 +142,6 @@
struct aux_dev aux;
};
-#ifdef BHYVE_SNAPSHOT
-static struct atkbdc_softc *atkbdc_sc = NULL;
-#endif
-
static void
atkbdc_assert_kbd_intr(struct atkbdc_softc *sc)
{
@@ -517,6 +517,9 @@
struct inout_port iop;
struct atkbdc_softc *sc;
int error;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
sc = calloc(1, sizeof(struct atkbdc_softc));
sc->ctx = ctx;
@@ -555,16 +558,31 @@
sc->ps2mouse_sc = ps2mouse_init(sc);
#ifdef BHYVE_SNAPSHOT
- assert(atkbdc_sc == NULL);
- atkbdc_sc = sc;
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (dev_info == NULL) {
+ error = -1;
+ fprintf(stderr, "Error allocating space for dev_info");
+ }
+ assert(error == 0);
+
+ dev_info->dev_name = "atkbdc";
+ dev_info->snapshot_cb = atkbdc_snapshot;
+ dev_info->meta_data = sc;
+
+ insert_registered_devs(dev_info);
#endif
}
#ifdef BHYVE_SNAPSHOT
int
-atkbdc_snapshot(struct vm_snapshot_meta *meta)
+atkbdc_snapshot(struct vm_snapshot_meta *meta, struct vm_snapshot_dev_info *dev_info)
{
int ret;
+ struct atkbdc_softc *atkbdc_sc;
+
+ assert(dev_info->meta_data != NULL);
+ atkbdc_sc = (struct atkbdc_softc*) dev_info->meta_data;
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->status, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->outport, meta, ret, done);
@@ -584,7 +602,6 @@
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq_active, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq, meta, ret, done);
-
ret = ps2kbd_snapshot(atkbdc_sc->ps2kbd_sc, meta);
if (ret != 0)
goto done;
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -928,7 +928,6 @@
static int
vmexit_breakpoint(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
{
-
gdb_cpu_breakpoint(*pvcpu, vmexit);
return (VMEXIT_CONTINUE);
}
@@ -1240,12 +1239,12 @@
set_config_bool("destroy_on_poweroff", true);
break;
case 'p':
- if (pincpu_parse(optarg) != 0) {
- errx(EX_USAGE, "invalid vcpu pinning "
- "configuration '%s'", optarg);
- }
+ if (pincpu_parse(optarg) != 0) {
+ errx(EX_USAGE, "invalid vcpu pinning "
+ "configuration '%s'", optarg);
+ }
break;
- case 'c':
+ case 'c':
if (topology_parse(optarg) != 0) {
errx(EX_USAGE, "invalid cpu topology "
"'%s'", optarg);
@@ -1341,10 +1340,10 @@
argc -= optind;
argv += optind;
- if (argc > 1)
+#ifdef BHYVE_SNAPSHOT
+ if (argc > 1 || (argc == 0 && restore_file == NULL))
usage(1);
-#ifdef BHYVE_SNAPSHOT
if (restore_file != NULL) {
error = load_restore_file(restore_file, &rstate);
if (error) {
@@ -1476,7 +1475,7 @@
}
fprintf(stdout, "Restoring pci devs...\r\n");
- if (vm_restore_user_devs(ctx, &rstate) != 0) {
+ if (walk_and_restore_user_devs(ctx, &rstate) != 0) {
fprintf(stderr, "Failed to restore PCI device state.\n");
exit(1);
}
@@ -1569,7 +1568,6 @@
}
}
#endif
-
/*
* Head off to the main event dispatch loop
*/
diff --git a/usr.sbin/bhyve/gdb.c b/usr.sbin/bhyve/gdb.c
--- a/usr.sbin/bhyve/gdb.c
+++ b/usr.sbin/bhyve/gdb.c
@@ -731,8 +731,6 @@
_gdb_cpu_suspend(int vcpu, bool report_stop)
{
- if (!gdb_active)
- return;
debug("$vCPU %d suspending\n", vcpu);
CPU_SET(vcpu, &vcpus_waiting);
if (report_stop && CPU_CMP(&vcpus_waiting, &vcpus_suspended) == 0)
@@ -807,6 +805,9 @@
gdb_cpu_suspend(int vcpu)
{
+ if (!gdb_active)
+ return;
+
pthread_mutex_lock(&gdb_lock);
_gdb_cpu_suspend(vcpu, true);
gdb_cpu_resume(vcpu);
diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c
--- a/usr.sbin/bhyve/pci_ahci.c
+++ b/usr.sbin/bhyve/pci_ahci.c
@@ -42,6 +42,9 @@
#include <sys/endian.h>
#include <machine/vmm_snapshot.h>
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
#include <errno.h>
#include <fcntl.h>
@@ -2425,6 +2428,10 @@
const char *path, *type, *value;
nvlist_t *ports_nvl, *port_nvl;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
+
ret = 0;
#ifdef AHCI_DEBUG
@@ -2435,8 +2442,6 @@
pi->pi_arg = sc;
sc->asc_pi = pi;
pthread_mutex_init(&sc->mtx, NULL);
- sc->ports = 0;
- sc->pi = 0;
slots = 32;
ports_nvl = find_relative_config_node(nvl, "port");
@@ -2549,6 +2554,23 @@
pci_lintr_request(pi);
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ goto open_fail;
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->meta_data = pi;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->pause_cb = pci_pause;
+ dev_info->resume_cb = pci_resume;
+
+ insert_registered_devs(dev_info);
+#endif
+
open_fail:
if (ret) {
for (p = 0; p < sc->ports; p++) {
diff --git a/usr.sbin/bhyve/pci_e82545.c b/usr.sbin/bhyve/pci_e82545.c
--- a/usr.sbin/bhyve/pci_e82545.c
+++ b/usr.sbin/bhyve/pci_e82545.c
@@ -48,6 +48,10 @@
#endif
#include <machine/vmm_snapshot.h>
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -2284,6 +2288,9 @@
struct e82545_softc *sc;
const char *mac;
int err;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
/* Setup our softc */
sc = calloc(1, sizeof(*sc));
@@ -2342,6 +2349,22 @@
/* H/w initiated reset */
e82545_reset(sc, 0);
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ return (-1);
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
+
return (0);
}
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -47,6 +47,7 @@
struct pci_devinst;
struct memory_region;
struct vm_snapshot_meta;
+struct vm_snapshot_dev_info;
struct pci_devemu {
char *pe_emu; /* Name of device emulation */
@@ -257,9 +258,9 @@
uint64_t pci_ecfg_base(void);
int pci_bus_configured(int bus);
#ifdef BHYVE_SNAPSHOT
-int pci_snapshot(struct vm_snapshot_meta *meta);
-int pci_pause(struct vmctx *ctx, const char *dev_name);
-int pci_resume(struct vmctx *ctx, const char *dev_name);
+int pci_snapshot(struct vm_snapshot_meta *meta, struct vm_snapshot_dev_info *dev_info);
+int pci_pause(struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info);
+int pci_resume(struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info);
#endif
static __inline void
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -64,9 +64,12 @@
#include "pci_irq.h"
#include "pci_lpc.h"
-#define CONF1_ADDR_PORT 0x0cf8
-#define CONF1_DATA_PORT 0x0cfc
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+#define CONF1_ADDR_PORT 0x0cf8
+#define CONF1_DATA_PORT 0x0cfc
#define CONF1_ENABLE 0x80000000ul
#define MAXBUSES (PCI_BUSMAX + 1)
@@ -282,6 +285,7 @@
error = pde->pe_legacy_config(nvl, config);
else
error = pci_parse_legacy_config(nvl, config);
+
done:
free(str);
return (error);
@@ -2104,58 +2108,19 @@
return (ret);
}
-static int
-pci_find_slotted_dev(const char *dev_name, struct pci_devemu **pde,
- struct pci_devinst **pdi)
-{
- struct businfo *bi;
- struct slotinfo *si;
- struct funcinfo *fi;
- int bus, slot, func;
-
- assert(dev_name != NULL);
- assert(pde != NULL);
- assert(pdi != NULL);
-
- for (bus = 0; bus < MAXBUSES; bus++) {
- if ((bi = pci_businfo[bus]) == NULL)
- continue;
-
- for (slot = 0; slot < MAXSLOTS; slot++) {
- si = &bi->slotinfo[slot];
- for (func = 0; func < MAXFUNCS; func++) {
- fi = &si->si_funcs[func];
- if (fi->fi_pde == NULL)
- continue;
- if (strcmp(dev_name, fi->fi_pde->pe_emu) != 0)
- continue;
-
- *pde = fi->fi_pde;
- *pdi = fi->fi_devi;
- return (0);
- }
- }
- }
-
- return (EINVAL);
-}
-
int
-pci_snapshot(struct vm_snapshot_meta *meta)
+pci_snapshot(struct vm_snapshot_meta *meta, struct vm_snapshot_dev_info *dev_info)
{
struct pci_devemu *pde;
struct pci_devinst *pdi;
int ret;
- assert(meta->dev_name != NULL);
-
- ret = pci_find_slotted_dev(meta->dev_name, &pde, &pdi);
- if (ret != 0) {
- fprintf(stderr, "%s: no such name: %s\r\n",
- __func__, meta->dev_name);
- memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
- return (0);
+ if (dev_info->meta_data == NULL) {
+ fprintf(stderr, "%s: device meta data is NULL", __func__);
+ return (-1);
}
+ pdi = (struct pci_devinst *) dev_info->meta_data;
+ pde = pdi->pi_d;
meta->dev_data = pdi;
@@ -2178,28 +2143,20 @@
}
int
-pci_pause(struct vmctx *ctx, const char *dev_name)
+pci_pause(struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info)
{
struct pci_devemu *pde;
struct pci_devinst *pdi;
- int ret;
-
- assert(dev_name != NULL);
-
- ret = pci_find_slotted_dev(dev_name, &pde, &pdi);
- if (ret != 0) {
- /*
- * It is possible to call this function without
- * checking that the device is inserted first.
- */
- fprintf(stderr, "%s: no such name: %s\n", __func__, dev_name);
- return (0);
- }
+
+ assert(dev_info->meta_data != NULL);
+
+ pdi = (struct pci_devinst *) dev_info->meta_data;
+ pde = pdi->pi_d;
if (pde->pe_pause == NULL) {
/* The pause/resume functionality is optional. */
fprintf(stderr, "%s: not implemented for: %s\n",
- __func__, dev_name);
+ __func__, dev_info->dev_name);
return (0);
}
@@ -2207,28 +2164,22 @@
}
int
-pci_resume(struct vmctx *ctx, const char *dev_name)
+pci_resume(struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info)
{
struct pci_devemu *pde;
struct pci_devinst *pdi;
- int ret;
- assert(dev_name != NULL);
-
- ret = pci_find_slotted_dev(dev_name, &pde, &pdi);
- if (ret != 0) {
- /*
- * It is possible to call this function without
- * checking that the device is inserted first.
- */
- fprintf(stderr, "%s: no such name: %s\n", __func__, dev_name);
- return (0);
+ if (dev_info->meta_data == NULL) {
+ fprintf(stderr, "%s: device meta data is NULL", __func__);
+ return (-1);
}
+ pdi = (struct pci_devinst *) dev_info->meta_data;
+ pde = pdi->pi_d;
if (pde->pe_resume == NULL) {
/* The pause/resume functionality is optional. */
fprintf(stderr, "%s: not implemented for: %s\n",
- __func__, dev_name);
+ __func__, dev_info->dev_name);
return (0);
}
diff --git a/usr.sbin/bhyve/pci_fbuf.c b/usr.sbin/bhyve/pci_fbuf.c
--- a/usr.sbin/bhyve/pci_fbuf.c
+++ b/usr.sbin/bhyve/pci_fbuf.c
@@ -55,6 +55,10 @@
#include "rfb.h"
#include "vga.h"
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
/*
* bhyve Framebuffer device emulation.
* BAR0 points to the current mode information.
@@ -377,6 +381,9 @@
{
int error, prot;
struct pci_fbuf_softc *sc;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
if (fbuf_sc != NULL) {
EPRINTLN("Only one frame buffer device is allowed.");
@@ -456,6 +463,23 @@
memset((void *)sc->fb_base, 0, FB_SIZE);
error = rfb_init(sc->rfb_host, sc->rfb_port, sc->rfb_wait, sc->rfb_password);
+
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ error = -1;
+ goto done;
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
done:
if (error)
free(sc);
diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c
--- a/usr.sbin/bhyve/pci_lpc.c
+++ b/usr.sbin/bhyve/pci_lpc.c
@@ -53,6 +53,10 @@
#include "pctestdev.h"
#include "uart_emul.h"
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#define IO_ICU1 0x20
#define IO_ICU2 0xA0
@@ -424,6 +428,9 @@
static int
pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
{
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
/*
* Do not allow more than one LPC bridge to be configured.
@@ -454,6 +461,22 @@
lpc_bridge = pi;
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ return (-1);
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
+
return (0);
}
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -63,6 +63,10 @@
#define VTBLK_BSIZE 512
#define VTBLK_RINGSZ 128
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
_Static_assert(VTBLK_RINGSZ <= BLOCKIF_RING_MAX, "Each ring entry must be able to queue a request");
#define VTBLK_S_OK 0
@@ -446,6 +450,9 @@
struct pci_vtblk_softc *sc;
off_t size;
int i, sectsz, sts, sto;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
/*
* The supplied backing file has to exist
@@ -540,6 +547,23 @@
return (1);
}
vi_set_io_bar(&sc->vbsc_vs, 0);
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ free(sc);
+ return (1);
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
+
return (0);
}
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -39,6 +39,14 @@
#include <machine/vmm_snapshot.h>
#include <net/ethernet.h>
#include <net/if.h> /* IFNAMSIZ */
+#ifndef NETMAP_WITH_LIBS
+#define NETMAP_WITH_LIBS
+#endif
+#include <net/netmap_user.h>
+
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
#include <err.h>
#include <errno.h>
@@ -566,6 +574,9 @@
char tname[MAXCOMLEN + 1];
unsigned long mtu = ETHERMTU;
int err;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
/*
* Allocate data structures for further virtio initializations.
@@ -672,7 +683,22 @@
snprintf(tname, sizeof(tname), "vtnet-%d:%d tx", pi->pi_slot,
pi->pi_func);
pthread_set_name_np(sc->tx_tid, tname);
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ free(sc);
+ return (1);
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
return (0);
}
@@ -802,7 +828,7 @@
}
#endif
-static struct pci_devemu pci_de_vnet = {
+struct pci_devemu pci_de_vnet = {
.pe_emu = "virtio-net",
.pe_init = pci_vtnet_init,
.pe_legacy_config = netbe_legacy_config,
diff --git a/usr.sbin/bhyve/pci_xhci.c b/usr.sbin/bhyve/pci_xhci.c
--- a/usr.sbin/bhyve/pci_xhci.c
+++ b/usr.sbin/bhyve/pci_xhci.c
@@ -50,6 +50,10 @@
#include <machine/vmm_snapshot.h>
+#ifdef BHYVE_SNAPSHOT
+#include "snapshot.h"
+#endif
+
#include <dev/usb/usbdi.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_freebsd.h>
@@ -2837,6 +2841,9 @@
{
struct pci_xhci_softc *sc;
int error;
+#ifdef BHYVE_SNAPSHOT
+ struct vm_snapshot_dev_info *dev_info;
+#endif
if (xhci_in_use) {
WPRINTF(("pci_xhci controller already defined"));
@@ -2918,6 +2925,23 @@
pthread_mutex_init(&sc->mtx, NULL);
+#ifdef BHYVE_SNAPSHOT
+ dev_info = calloc(1, sizeof(*dev_info));
+
+ if (!dev_info) {
+ fprintf(stderr, "Error allocating space for snapshot struct");
+ error = -1;
+ goto done;
+ }
+
+ dev_info->dev_name = pi->pi_d->pe_emu;
+ dev_info->was_restored = 0;
+ dev_info->snapshot_cb = pci_snapshot;
+ dev_info->meta_data = pi;
+
+ insert_registered_devs(dev_info);
+#endif
+
done:
if (error) {
free(sc);
diff --git a/usr.sbin/bhyve/snapshot.h b/usr.sbin/bhyve/snapshot.h
--- a/usr.sbin/bhyve/snapshot.h
+++ b/usr.sbin/bhyve/snapshot.h
@@ -46,6 +46,7 @@
#define MAX_SNAPSHOT_FILENAME PATH_MAX
struct vmctx;
+struct vm_snapshot_dev_info;
struct restore_state {
int kdata_fd;
@@ -75,12 +76,14 @@
int socket_fd;
};
-typedef int (*vm_snapshot_dev_cb)(struct vm_snapshot_meta *);
-typedef int (*vm_pause_dev_cb) (struct vmctx *, const char *);
-typedef int (*vm_resume_dev_cb) (struct vmctx *, const char *);
+typedef int (*vm_snapshot_dev_cb)(struct vm_snapshot_meta *meta, struct vm_snapshot_dev_info *dev_info);
+typedef int (*vm_pause_dev_cb) (struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info);
+typedef int (*vm_resume_dev_cb) (struct vmctx *ctx, struct vm_snapshot_dev_info *dev_info);
struct vm_snapshot_dev_info {
const char *dev_name; /* device name */
+ int was_restored; /* flag to check if the device was previously restored*/
+ void *meta_data; /* specific meta data for specific devices*/
vm_snapshot_dev_cb snapshot_cb; /* callback for device snapshot */
vm_pause_dev_cb pause_cb; /* callback for device pause */
vm_resume_dev_cb resume_cb; /* callback for device resume */
@@ -91,6 +94,14 @@
enum snapshot_req req; /* request type */
};
+struct vm_snapshot_registered_devs {
+ struct vm_snapshot_dev_info *dev_info;
+ // for each device type, the meta should be specific
+ struct vm_snapshot_registered_devs *next_dev;
+};
+
+void insert_registered_devs(struct vm_snapshot_dev_info *dev_info);
+
void destroy_restore_state(struct restore_state *rstate);
const char *lookup_vmname(struct restore_state *rstate);
@@ -104,8 +115,9 @@
int restore_vm_mem(struct vmctx *ctx, struct restore_state *rstate);
int vm_restore_kern_structs(struct vmctx *ctx, struct restore_state *rstate);
-
-int vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate);
+int vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate, void *dev_ptr,
+ size_t dev_size, struct vm_snapshot_dev_info *dev_info);
+int walk_and_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate);
int vm_pause_user_devs(struct vmctx *ctx);
int vm_resume_user_devs(struct vmctx *ctx);
diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c
--- a/usr.sbin/bhyve/snapshot.c
+++ b/usr.sbin/bhyve/snapshot.c
@@ -109,6 +109,10 @@
static struct winsize winsize;
static sig_t old_winch_handler;
+#ifdef BHYVE_SNAPSHOT
+static struct vm_snapshot_registered_devs *head_registered_devs = NULL;
+#endif
+
#define KB (1024UL)
#define MB (1024UL * KB)
#define GB (1024UL * MB)
@@ -139,20 +143,6 @@
_a < _b ? _a : _b; \
})
-const struct vm_snapshot_dev_info snapshot_devs[] = {
- { "atkbdc", atkbdc_snapshot, NULL, NULL },
- { "virtio-net", pci_snapshot, pci_pause, pci_resume },
- { "virtio-blk", pci_snapshot, pci_pause, pci_resume },
- { "virtio-rnd", pci_snapshot, NULL, NULL },
- { "lpc", pci_snapshot, NULL, NULL },
- { "fbuf", pci_snapshot, NULL, NULL },
- { "xhci", pci_snapshot, NULL, NULL },
- { "e1000", pci_snapshot, NULL, NULL },
- { "ahci", pci_snapshot, pci_pause, pci_resume },
- { "ahci-hd", pci_snapshot, pci_pause, pci_resume },
- { "ahci-cd", pci_snapshot, pci_pause, pci_resume },
-};
-
const struct vm_snapshot_kern_info snapshot_kern_structs[] = {
{ "vhpet", STRUCT_VHPET },
{ "vm", STRUCT_VM },
@@ -171,6 +161,18 @@
static pthread_cond_t vcpus_idle, vcpus_can_run;
static bool checkpoint_active;
+void
+insert_registered_devs(struct vm_snapshot_dev_info *dev_info)
+{
+ struct vm_snapshot_registered_devs *new_node;
+ new_node = malloc(sizeof(*new_node));
+
+ new_node->dev_info = dev_info;
+ new_node->next_dev = head_registered_devs;
+
+ head_registered_devs = new_node;
+}
+
/*
* TODO: Harden this function and all of its callers since 'base_str' is a user
* provided string.
@@ -461,58 +463,42 @@
}
static void *
-lookup_check_dev(const char *dev_name, struct restore_state *rstate,
- const ucl_object_t *obj, size_t *data_size)
+lookup_check_dev(struct restore_state *rstate, const ucl_object_t *obj,
+ size_t *data_size, struct vm_snapshot_dev_info **dev_info)
{
const char *snapshot_req;
+ struct vm_snapshot_registered_devs *ptr_registered_devs;
int64_t size, file_offset;
snapshot_req = NULL;
JSON_GET_STRING_OR_RETURN(JSON_SNAPSHOT_REQ_KEY, obj,
&snapshot_req, NULL);
assert(snapshot_req != NULL);
- if (!strcmp(snapshot_req, dev_name)) {
- JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
- &size, NULL);
- assert(size >= 0);
-
- JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
- &file_offset, NULL);
- assert(file_offset >= 0);
- assert(file_offset + size <= rstate->kdata_len);
- *data_size = (size_t)size;
- return (rstate->kdata_map + file_offset);
- }
-
- return (NULL);
-}
-
-static void*
-lookup_dev(const char *dev_name, struct restore_state *rstate,
- size_t *data_size)
-{
- const ucl_object_t *devs = NULL, *obj = NULL;
- ucl_object_iter_t it = NULL;
- void *ret;
-
- devs = ucl_object_lookup(rstate->meta_root_obj, JSON_DEV_ARR_KEY);
- if (devs == NULL) {
- fprintf(stderr, "Failed to find '%s' object.\n",
- JSON_DEV_ARR_KEY);
- return (NULL);
- }
+ ptr_registered_devs = head_registered_devs;
+
+ while (ptr_registered_devs != NULL) {
+ if (!strcmp(snapshot_req, ptr_registered_devs->dev_info->dev_name)
+ && !ptr_registered_devs->dev_info->was_restored) {
+ *dev_info = ptr_registered_devs->dev_info;
+
+ #ifdef DEBUG
+ fprintf(stderr, "Found the following device: %s \n", (*dev_info)->dev_name);
+ #endif
+
+ JSON_GET_INT_OR_RETURN(JSON_SIZE_KEY, obj,
+ &size, NULL);
+ assert(size >= 0);
- if (ucl_object_type((ucl_object_t *)devs) != UCL_ARRAY) {
- fprintf(stderr, "Object '%s' is not an array.\n",
- JSON_DEV_ARR_KEY);
- return (NULL);
- }
+ JSON_GET_INT_OR_RETURN(JSON_FILE_OFFSET_KEY, obj,
+ &file_offset, NULL);
+ assert(file_offset >= 0);
+ assert(file_offset + size <= rstate->kdata_len);
+ *data_size = (size_t)size;
- while ((obj = ucl_object_iterate(devs, &it, true)) != NULL) {
- ret = lookup_check_dev(dev_name, rstate, obj, data_size);
- if (ret != NULL)
- return (ret);
+ return (rstate->kdata_map + file_offset);
+ }
+ ptr_registered_devs = ptr_registered_devs->next_dev;
}
return (NULL);
@@ -927,31 +913,15 @@
}
int
-vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate,
- const struct vm_snapshot_dev_info *info)
+vm_restore_user_dev(struct vmctx *ctx, struct restore_state *rstate, void *dev_ptr,
+ size_t dev_size, struct vm_snapshot_dev_info *dev_info)
{
- void *dev_ptr;
- size_t dev_size;
int ret;
struct vm_snapshot_meta *meta;
- dev_ptr = lookup_dev(info->dev_name, rstate, &dev_size);
- if (dev_ptr == NULL) {
- fprintf(stderr, "Failed to lookup dev: %s\r\n", info->dev_name);
- fprintf(stderr, "Continuing the restore/migration process\r\n");
- return (0);
- }
-
- if (dev_size == 0) {
- fprintf(stderr, "%s: Device size is 0. "
- "Assuming %s is not used\r\n",
- __func__, info->dev_name);
- return (0);
- }
-
meta = &(struct vm_snapshot_meta) {
.ctx = ctx,
- .dev_name = info->dev_name,
+ .dev_name = dev_info->dev_name,
.buffer.buf_start = dev_ptr,
.buffer.buf_size = dev_size,
@@ -962,30 +932,52 @@
.op = VM_SNAPSHOT_RESTORE,
};
- ret = (*info->snapshot_cb)(meta);
+ ret = (*dev_info->snapshot_cb)(meta, dev_info);
if (ret != 0) {
fprintf(stderr, "Failed to restore dev: %s\r\n",
- info->dev_name);
+ dev_info->dev_name);
return (-1);
}
+ dev_info->was_restored = 1;
+
return (0);
}
-
int
-vm_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
+walk_and_restore_user_devs(struct vmctx *ctx, struct restore_state *rstate)
{
- int ret;
- int i;
+ const ucl_object_t *devs = NULL, *obj = NULL;
+ ucl_object_iter_t it = NULL;
+ void *dev_ptr;
+ size_t dev_size;
+ struct vm_snapshot_dev_info *dev_info;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- ret = vm_restore_user_dev(ctx, rstate, &snapshot_devs[i]);
- if (ret != 0)
- return (ret);
+ devs = ucl_object_lookup(rstate->meta_root_obj, JSON_DEV_ARR_KEY);
+ if (devs == NULL) {
+ fprintf(stderr, "Failed to find '%s' object.\n",
+ JSON_DEV_ARR_KEY);
+ return (-1);
+ }
+
+ if (ucl_object_type((ucl_object_t *)devs) != UCL_ARRAY) {
+ fprintf(stderr, "Object '%s' is not an array.\n",
+ JSON_DEV_ARR_KEY);
+ return (-1);
}
- return 0;
+ while ((obj = ucl_object_iterate(devs, &it, true)) != NULL) {
+ dev_ptr = lookup_check_dev(rstate, obj, &dev_size, &dev_info);
+
+ if (dev_ptr != NULL) {
+ int ret_val;
+ ret_val = vm_restore_user_dev(ctx, rstate, dev_ptr, dev_size, dev_info);
+ if (ret_val != 0)
+ return ret_val;
+ }
+ }
+
+ return (0);
}
int
@@ -993,16 +985,21 @@
{
const struct vm_snapshot_dev_info *info;
int ret;
- int i;
+ struct vm_snapshot_registered_devs *ptr_registered_devs;
+
+ ptr_registered_devs = head_registered_devs;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->pause_cb == NULL)
+ while (ptr_registered_devs != NULL) {
+ info = ptr_registered_devs->dev_info;
+ if (info->pause_cb == NULL) {
+ ptr_registered_devs = ptr_registered_devs->next_dev;
continue;
+ }
- ret = info->pause_cb(ctx, info->dev_name);
+ ret = info->pause_cb(ctx, ptr_registered_devs->dev_info);
if (ret != 0)
return (ret);
+ ptr_registered_devs = ptr_registered_devs->next_dev;
}
return (0);
@@ -1013,16 +1010,20 @@
{
const struct vm_snapshot_dev_info *info;
int ret;
- int i;
+ struct vm_snapshot_registered_devs *ptr_registered_devs;
- for (i = 0; i < nitems(snapshot_devs); i++) {
- info = &snapshot_devs[i];
- if (info->resume_cb == NULL)
- continue;
+ ptr_registered_devs = head_registered_devs;
- ret = info->resume_cb(ctx, info->dev_name);
+ while (ptr_registered_devs != NULL) {
+ info = ptr_registered_devs->dev_info;
+ if (info->resume_cb == NULL) {
+ ptr_registered_devs = ptr_registered_devs->next_dev;
+ continue;
+ }
+ ret = info->resume_cb(ctx, ptr_registered_devs->dev_info);
if (ret != 0)
return (ret);
+ ptr_registered_devs = ptr_registered_devs->next_dev;
}
return (0);
@@ -1175,13 +1176,13 @@
}
static int
-vm_snapshot_user_dev(const struct vm_snapshot_dev_info *info,
+vm_snapshot_user_dev(struct vm_snapshot_dev_info *info,
int data_fd, xo_handle_t *xop,
struct vm_snapshot_meta *meta, off_t *offset)
{
int ret;
- ret = (*info->snapshot_cb)(meta);
+ ret = (*info->snapshot_cb)(meta, info);
if (ret != 0) {
fprintf(stderr, "Failed to snapshot %s; ret=%d\r\n",
meta->dev_name, ret);
@@ -1199,11 +1200,15 @@
static int
vm_snapshot_user_devs(struct vmctx *ctx, int data_fd, xo_handle_t *xop)
{
- int ret, i;
+ int ret;
off_t offset;
void *buffer;
size_t buf_size;
struct vm_snapshot_meta *meta;
+ struct vm_snapshot_dev_info *info;
+ struct vm_snapshot_registered_devs *ptr_registered_devs;
+
+ ptr_registered_devs = head_registered_devs;
buf_size = SNAPSHOT_BUFFER_SIZE;
@@ -1232,17 +1237,24 @@
xo_open_list_h(xop, JSON_DEV_ARR_KEY);
/* Restore other devices that support this feature */
- for (i = 0; i < nitems(snapshot_devs); i++) {
- meta->dev_name = snapshot_devs[i].dev_name;
+ while (ptr_registered_devs != NULL) {
+ info = ptr_registered_devs->dev_info;
+
+ meta->dev_name = info->dev_name;
memset(meta->buffer.buf_start, 0, meta->buffer.buf_size);
meta->buffer.buf = meta->buffer.buf_start;
meta->buffer.buf_rem = meta->buffer.buf_size;
- ret = vm_snapshot_user_dev(&snapshot_devs[i], data_fd, xop,
+ #ifdef DEBUG
+ fprintf(stderr, "Doing the snapshot for: %s \n", info->dev_name);
+ #endif
+ ret = vm_snapshot_user_dev(info, data_fd, xop,
meta, &offset);
if (ret != 0)
goto snapshot_err;
+
+ ptr_registered_devs = ptr_registered_devs->next_dev;
}
xo_close_list_h(xop, JSON_DEV_ARR_KEY);
@@ -1324,6 +1336,18 @@
pthread_cond_broadcast(&vcpus_can_run);
}
+void
+free_snapshot_array() {
+ struct vm_snapshot_registered_devs *ptr_registered_devs;
+
+ while(head_registered_devs != NULL) {
+ ptr_registered_devs = head_registered_devs;
+ head_registered_devs = head_registered_devs->next_dev;
+ free(ptr_registered_devs->dev_info);
+ free(ptr_registered_devs);
+ }
+}
+
static int
vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, bool stop_vm)
{
@@ -1389,7 +1413,7 @@
perror("Could not write guest memory to file");
error = -1;
goto done;
- }
+ }
ret = vm_snapshot_basic_metadata(ctx, xop, memsz);
if (ret != 0) {
@@ -1398,7 +1422,6 @@
goto done;
}
-
ret = vm_snapshot_kern_structs(ctx, kdata_fd, xop);
if (ret != 0) {
fprintf(stderr, "Failed to snapshot vm kernel data.\n");
@@ -1416,6 +1439,7 @@
xo_finish_h(xop);
if (stop_vm) {
+ free_snapshot_array();
vm_destroy(ctx);
exit(0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 11, 1:12 PM (20 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15754082
Default Alt Text
D26387.diff (29 KB)
Attached To
Mode
D26387: bhyve - Snapshot Save and Restore multiple devices
Attached
Detach File
Event Timeline
Log In to Comment