The purpose of this option is to allow features under development to be committed to the mainline
to more easily track changes and provide access to multiple developers
+config CHECKPOINT
+ bool "Enable Checkpointing"
+ default n
+ help
+ Temporary option to enable experimental checkpoint code
+
+
+
endmenu
LDFLAGS += --script=$(PWD)/ld.symmod.cmd
endif
+ifdef V3_CONFIG_CHECKPOINT
+LDFLAGS += --script=$(PWD)/ld.chkpt.cmd
+endif
+
EXTRA_CFLAGS += -I$(PWD)/../palacios/include/ -include autoconf.h -DMODULE=1 -D__KERNEL__=1
} else if (mode & FILE_OPEN_MODE_WRITE) {
pfile->mode = O_WRONLY;
}
+
+ if (mode & FILE_OPEN_MODE_CREATE) {
+ pfile->mode |= O_CREAT;
+ }
+
pfile->filp = filp_open(path, pfile->mode, 0);
--- /dev/null
+SECTIONS
+{
+ _v3_chkpt_stores :
+ {
+ __start__v3_chkpt_stores = .;
+ *(_v3_chkpt_stores);
+ __stop__v3_chkpt_stores = .;
+ }
+}
+
/* Global Control IOCTLs */
#define V3_START_GUEST 10
#define V3_STOP_GUEST 11
+#define V3_CREATE_GUEST 12
+#define V3_FREE_GUEST 13
+
#define V3_ADD_MEMORY 50
/* VM Specific IOCTLs */
#define V3_VM_PAUSE 23
#define V3_VM_CONTINUE 24
+#define V3_VM_LAUNCH 25
+#define V3_VM_STOP 26
+#define V3_VM_LOAD 27
+#define V3_VM_SAVE 28
+
#define V3_VM_INSPECT 30
#define V3_VM_MOVE_CORE 33
unsigned long long size;
void * guest_data;
char name[128];
-};
+} __attribute__((packed));
struct v3_mem_region {
unsigned long long base_addr;
unsigned long long num_pages;
-};
+} __attribute__((packed));
struct v3_core_move_cmd{
- uint16_t vcore_id;
- uint16_t pcore_id;
-};
+ unsigned short vcore_id;
+ unsigned short pcore_id;
+} __attribute__((packed));
+
+struct v3_chkpt_info {
+ char store[128];
+ char url[256]; /* This might need to be bigger... */
+} __attribute__((packed));
+
void * trace_malloc(size_t size, gfp_t flags);
v3_continue_vm(guest->v3_ctx);
break;
}
+#ifdef V3_CONFIG_CHECKPOINT
+ case V3_VM_SAVE: {
+ struct v3_chkpt_info chkpt;
+ void __user * argp = (void __user *)arg;
+
+ memset(&chkpt, 0, sizeof(struct v3_chkpt_info));
+
+ if (copy_from_user(&chkpt, argp, sizeof(struct v3_chkpt_info))) {
+ printk("Copy from user error getting checkpoint info\n");
+ return -EFAULT;
+ }
+
+ printk("Saving Guest to %s:%s\n", chkpt.store, chkpt.url);
+
+ if (v3_save_vm(guest->v3_ctx, chkpt.store, chkpt.url) == -1) {
+ printk("Error checkpointing VM state\n");
+ return -EFAULT;
+ }
+
+ break;
+ }
+ case V3_VM_LOAD: {
+ struct v3_chkpt_info chkpt;
+ void __user * argp = (void __user *)arg;
+
+ memset(&chkpt, 0, sizeof(struct v3_chkpt_info));
+
+ if (copy_from_user(&chkpt, argp, sizeof(struct v3_chkpt_info))) {
+ printk("Copy from user error getting checkpoint info\n");
+ return -EFAULT;
+ }
+
+ printk("Loading Guest to %s:%s\n", chkpt.store, chkpt.url);
+
+ if (v3_load_vm(guest->v3_ctx, chkpt.store, chkpt.url) == -1) {
+ printk("Error Loading VM state\n");
+ return -EFAULT;
+ }
+
+ break;
+ }
+#endif
case V3_VM_MOVE_CORE: {
struct v3_core_move_cmd cmd;
void __user * argp = (void __user *)arg;
printk("moving guest %s vcore %d to CPU %d\n", guest->name, cmd.vcore_id, cmd.pcore_id);
v3_move_vm_core(guest->v3_ctx, cmd.vcore_id, cmd.pcore_id);
- }
- break;
+ break;
+ }
default: {
struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
-all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file v3_core_move
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_example v3_os_debug v3_user_keyed_stream_example v3_user_keyed_stream_file v3_core_move v3_save v3_load
v3_stop : v3_stop.c v3_ctrl.h
gcc -static v3_stop.c -o v3_stop
+v3_save : v3_save.c v3_ctrl.h
+ gcc -static v3_save.c -o v3_save
+v3_load : v3_load.c v3_ctrl.h
+ gcc -static v3_load.c -o v3_load
+
v3_mem : v3_mem.c v3_ctrl.h
gcc -static v3_mem.c -o v3_mem
#include "v3_ctrl.h"
-struct v3_core_move_cmd {
- unsigned short vcore_id;
- unsigned short pcore_id;
-};
-
int main(int argc, char* argv[]) {
int vm_fd;
#define V3_START_GUEST 10
#define V3_STOP_GUEST 11
+#define V3_CREATE_GUEST 12
+#define V3_FREE_GUEST 13
+
+
+#define V3_VM_PAUSE 23
+#define V3_VM_CONTINUE 24
+
+#define V3_VM_LAUNCH 25
+#define V3_VM_STOP 26
+#define V3_VM_LOAD 27
+#define V3_VM_SAVE 28
+
#define V3_ADD_MEMORY 50
-#define V3_START_NETWORK 60
#define V3_VM_CONSOLE_CONNECT 20
#define V3_VM_SERIAL_CONNECT 21
unsigned long long size;
void * guest_data;
char name[128];
-};
+} __attribute__((packed));
struct v3_mem_region {
unsigned long long base_addr;
unsigned long long num_pages;
-};
+} __attribute__((packed));
+
+
+struct v3_core_move_cmd{
+ unsigned short vcore_id;
+ unsigned short pcore_id;
+} __attribute__((packed));
+
+
+struct v3_chkpt_info {
+ char store[128];
+ char url[256]; /* This might need to be bigger... */
+} __attribute__((packed));
#endif
--- /dev/null
+/*
+ * V3 checkpoint save utility
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include<linux/unistd.h>
+#include <curses.h>
+
+
+#include "v3_ctrl.h"
+
+
+#define MAX_STORE_LEN 128
+#define MAX_URL_LEN 256
+
+
+struct v3_chkpt_info chkpt;
+
+int main(int argc, char* argv[]) {
+ int vm_fd;
+ char * vm_dev = NULL;
+
+ if (argc < 4) {
+ printf("Usage: ./v3_load <vm_device> <store> <url>\n");
+ return -1;
+ }
+
+ vm_dev = argv[1];
+
+ if (strlen(argv[2]) >= MAX_STORE_LEN) {
+ printf("ERROR: Checkpoint store name longer than maximum size (%d)\n", MAX_STORE_LEN);
+ return -1;
+ }
+
+ strncpy(chkpt.store, argv[2], MAX_STORE_LEN);
+
+
+ if (strlen(argv[3]) >= MAX_URL_LEN) {
+ printf("ERROR: Checkpoint URL longer than maximum size (%d)\n", MAX_URL_LEN);
+ return -1;
+ }
+
+ strncpy(chkpt.url, argv[3], MAX_URL_LEN);
+
+ vm_fd = open(vm_dev, O_RDONLY);
+ if (vm_fd == -1) {
+ printf("Error opening VM device: %s\n", vm_dev);
+ return -1;
+ }
+
+ ioctl(vm_fd, V3_VM_LOAD, &chkpt);
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * V3 checkpoint save utility
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include<linux/unistd.h>
+#include <curses.h>
+
+
+#include "v3_ctrl.h"
+
+
+#define MAX_STORE_LEN 128
+#define MAX_URL_LEN 256
+
+
+struct v3_chkpt_info chkpt;
+
+int main(int argc, char* argv[]) {
+ int vm_fd;
+ char * vm_dev = NULL;
+
+ if (argc < 4) {
+ printf("Usage: ./v3_save <vm_device> <store> <url>\n");
+ return -1;
+ }
+
+ vm_dev = argv[1];
+
+ if (strlen(argv[2]) >= MAX_STORE_LEN) {
+ printf("ERROR: Checkpoint store name longer than maximum size (%d)\n", MAX_STORE_LEN);
+ return -1;
+ }
+
+ strncpy(chkpt.store, argv[2], MAX_STORE_LEN);
+
+
+ if (strlen(argv[3]) >= MAX_URL_LEN) {
+ printf("ERROR: Checkpoint URL longer than maximum size (%d)\n", MAX_URL_LEN);
+ return -1;
+ }
+
+ strncpy(chkpt.url, argv[3], MAX_URL_LEN);
+
+ vm_fd = open(vm_dev, O_RDONLY);
+ if (vm_fd == -1) {
+ printf("Error opening VM device: %s\n", vm_dev);
+ return -1;
+ }
+
+ ioctl(vm_fd, V3_VM_SAVE, &chkpt);
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+ return 0;
+}
+
+
#define FILE_OPEN_MODE_READ (1 << 0)
#define FILE_OPEN_MODE_WRITE (1 << 1)
+#define FILE_OPEN_MODE_CREATE (1 << 2)
struct v3_file_hooks {
int v3_start_svm_guest(struct guest_info *info);
int v3_reset_svm_vm_core(struct guest_info * core, addr_t rip);
-
+int v3_svm_load_core(struct guest_info * core, void * ctx);
+int v3_svm_save_core(struct guest_info * core, void * ctx);
#endif
int v3_pause_vm(struct v3_vm_info * vm);
int v3_continue_vm(struct v3_vm_info * vm);
+int v3_save_vm(struct v3_vm_info * vm, char * store, char * url);
+int v3_load_vm(struct v3_vm_info * vm, char * store, char * url);
+
int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu);
int v3_free_vm(struct v3_vm_info * vm);
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Madhav Suresh <madhav@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Authors: Madhav Suresh <madhav@u.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_CHECKPOINT_H__
+#define __VMM_CHECKPOINT_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm.h>
+
+
+struct v3_chkpt;
+
+
+struct v3_chkpt_ctx {
+ struct v3_chkpt * chkpt;
+ struct v3_chkpt_ctx * parent;
+ void * store_ctx;
+};
+
+/* Temporary */
+#define V3_CHKPT_STD_SAVE(ctx,x) v3_chkpt_save(ctx,#x,sizeof(x),&(x))
+#define V3_CHKPT_STD_LOAD(ctx,x) v3_chkpt_load(ctx,#x,sizeof(x),&(x))
+
+
+int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
+int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf);
+
+int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx);
+struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name);
+
+int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url);
+int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url);
+
+int V3_init_checkpoint();
+int V3_deinit_checkpoint();
+
+#endif
+
+#endif
#include <palacios/vmm_config.h>
#include <palacios/vmm_ethernet.h>
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+#endif
+
struct v3_vm_info;
struct v3_device_ops;
int v3_free_vm_devices(struct v3_vm_info * vm);
-
-
-
+#ifdef V3_CONFIG_CHECKPOINT
+int v3_save_vm_devices(struct v3_vm_info * vm, struct v3_chkpt * chkpt);
+int v3_load_vm_devices(struct v3_vm_info * vm, struct v3_chkpt * chkpt);
+#endif
int V3_deinit_devices();
-#ifdef V3_CONFIG_KEYED_STREAMS
-#include <interfaces/vmm_keyed_stream.h>
-#endif
-
struct v3_device_ops {
int (*free)(void * private_data);
-#ifdef V3_CONFIG_KEYED_STREAMS
- int (*checkpoint)(struct vm_device *dev, v3_keyed_stream_t stream);
- int (*restore)(struct vm_device *dev, v3_keyed_stream_t stream);
+#ifdef V3_CONFIG_CHECKPOINT
+ int (*save)(struct v3_chkpt_ctx * ctx, void * private_data);
+ int (*load)(struct v3_chkpt_ctx * ctx, void * privata_data);
#endif
};
void v3_init_vmx_cpu(int cpu_id);
void v3_deinit_vmx_cpu(int cpu_id);
+int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class);
+int v3_deinit_vmx_vmcs(struct guest_info * core);
+
int v3_start_vmx_guest(struct guest_info* info);
int v3_reset_vmx_vm_core(struct guest_info * core, addr_t rip);
int v3_vmx_enter(struct guest_info * info);
-int v3_init_vmx_vmcs(struct guest_info * info, v3_vm_class_t vm_class);
-int v3_deinit_vmx_vmcs(struct guest_info * core);
+int v3_vmx_load_core(struct guest_info * core, void * ctx);
+int v3_vmx_save_core(struct guest_info * core, void * ctx);
+
+
+
+
#endif // ! __V3VEE__
return 0;
}
-#ifdef V3_CONFIG_KEYED_STREAMS
-static int pit_checkpoint(struct vm_device *dev, v3_keyed_stream_t stream)
-{
- struct pit *p = (struct pit *) (dev->private_data);
-
- v3_keyed_stream_key_t ks;
-
- ks = v3_keyed_stream_open_key(stream,dev->name);
-
- if (!ks) {
- return -1;
- }
-
- STD_SAVE(stream,ks,p->pit_counter);
- STD_SAVE(stream,ks,p->pit_reload);
- STD_SAVE(stream,ks,p->ch_0);
- STD_SAVE(stream,ks,p->ch_1);
- STD_SAVE(stream,ks,p->ch_2);
- STD_SAVE(stream,ks,p->speaker);
-
- v3_keyed_stream_close_key(stream,ks);
+#ifdef V3_CONFIG_CHECKPOINT
+static int pit_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pit * pit_state = (struct pit *)private_data;
+
+ V3_CHKPT_STD_SAVE(ctx, pit_state->pit_counter);
+ V3_CHKPT_STD_SAVE(ctx, pit_state->pit_reload);
+ V3_CHKPT_STD_SAVE(ctx, pit_state->ch_0);
+ V3_CHKPT_STD_SAVE(ctx, pit_state->ch_1);
+ V3_CHKPT_STD_SAVE(ctx, pit_state->ch_2);
+ V3_CHKPT_STD_SAVE(ctx, pit_state->speaker);
return 0;
-
-
}
-static int pit_restore(struct vm_device *dev, v3_keyed_stream_t stream)
-{
- struct pit *p = (struct pit *) (dev->private_data);
+static int pit_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pit * pit_state = (struct pit *)private_data;
- v3_keyed_stream_key_t ks;
+ V3_CHKPT_STD_LOAD(ctx, pit_state->pit_counter);
+ V3_CHKPT_STD_LOAD(ctx, pit_state->pit_reload);
+ V3_CHKPT_STD_LOAD(ctx, pit_state->ch_0);
+ V3_CHKPT_STD_LOAD(ctx, pit_state->ch_1);
+ V3_CHKPT_STD_LOAD(ctx, pit_state->ch_2);
+ V3_CHKPT_STD_LOAD(ctx, pit_state->speaker);
- ks = v3_keyed_stream_open_key(stream,dev->name);
-
- if (!ks) {
- return -1;
- }
-
- STD_LOAD(stream,ks,p->pit_counter);
- STD_LOAD(stream,ks,p->pit_reload);
- STD_LOAD(stream,ks,p->ch_0);
- STD_LOAD(stream,ks,p->ch_1);
- STD_LOAD(stream,ks,p->ch_2);
- STD_LOAD(stream,ks,p->speaker);
-
- v3_keyed_stream_close_key(stream,ks);
-
return 0;
-
-
}
#endif
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))pit_free,
-#ifdef V3_CONFIG_KEYED_STREAMS
- .checkpoint = pit_checkpoint,
- .restore = pit_restore,
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = pit_save,
+ .load = pit_load,
#endif
};
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+static int pic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pic_internal * pic = (struct pic_internal *)private_data;
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_irr);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_irr);
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_isr);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_isr);
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_elcr);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_elcr);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_elcr_mask);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_elcr_mask);
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_icw1);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_icw2);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_icw3);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_icw4);
+
+
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_icw1);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_icw2);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_icw3);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_icw4);
+
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_imr);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_imr);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_ocw2);
+ V3_CHKPT_STD_SAVE(ctx, pic->master_ocw3);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_ocw2);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_ocw3);
+
+ V3_CHKPT_STD_SAVE(ctx, pic->master_state);
+ V3_CHKPT_STD_SAVE(ctx, pic->slave_state);
+
+
+ return 0;
+
+}
+
+static int pic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pic_internal * pic = (struct pic_internal *)private_data;
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_irr);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_irr);
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_isr);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_isr);
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_elcr);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_elcr);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_elcr_mask);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_elcr_mask);
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_icw1);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_icw2);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_icw3);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_icw4);
+
+
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_icw1);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_icw2);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_icw3);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_icw4);
+
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_imr);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_imr);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_ocw2);
+ V3_CHKPT_STD_LOAD(ctx, pic->master_ocw3);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_ocw2);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_ocw3);
+
+ V3_CHKPT_STD_LOAD(ctx, pic->master_state);
+ V3_CHKPT_STD_LOAD(ctx, pic->slave_state);
+
+ return 0;
+}
+
+#endif
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))pic_free,
-
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = pic_save,
+ .load = pic_load
+#endif
};
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+static int apic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct apic_dev_state * apic_state = (struct apic_dev_state *)private_data;
+ int i = 0;
+
+ V3_CHKPT_STD_SAVE(ctx, apic_state->num_apics);
+
+ //V3_CHKPT_STD_SAVE(ctx,apic_state->state_lock);
+ for (i = 0; i < apic_state->num_apics; i++) {
+
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].base_addr);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].base_addr_msr);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].lapic_id);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].apic_ver);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].ext_apic_ctrl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].local_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].tmr_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].tmr_div_cfg);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].lint0_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].lint1_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].perf_ctr_loc_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].therm_loc_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].err_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].err_status);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].spurious_int);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].int_cmd);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].log_dst);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].dst_fmt);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].arb_prio);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].task_prio);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].proc_prio);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].ext_apic_feature);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].spec_eoi);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].tmr_cur_cnt);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].tmr_init_cnt);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].ext_intr_vec_tbl);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].rem_rd_data);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].ipi_state);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].int_req_reg);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].int_svc_reg);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].int_en_reg);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].trig_mode_reg);
+ V3_CHKPT_STD_SAVE(ctx, apic_state->apics[i].eoi);
+
+ }
+
+ return 0;
+}
+
+static int apic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct apic_dev_state *apic_state = (struct apic_dev_state *)private_data;
+ int i = 0;
+
+ V3_CHKPT_STD_LOAD(ctx,apic_state->num_apics);
+
+ for (i = 0; i < apic_state->num_apics; i++) {
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].base_addr);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].base_addr_msr);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].lapic_id);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].apic_ver);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].ext_apic_ctrl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].local_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].tmr_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].tmr_div_cfg);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].lint0_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].lint1_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].perf_ctr_loc_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].therm_loc_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].err_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].err_status);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].spurious_int);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].int_cmd);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].log_dst);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].dst_fmt);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].arb_prio);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].task_prio);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].proc_prio);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].ext_apic_feature);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].spec_eoi);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].tmr_cur_cnt);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].tmr_init_cnt);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].ext_intr_vec_tbl);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].rem_rd_data);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].ipi_state);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].int_req_reg);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].int_svc_reg);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].int_en_reg);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].trig_mode_reg);
+ V3_CHKPT_STD_LOAD(ctx, apic_state->apics[i].eoi);
+ }
+
+
+ return 0;
+}
+
+#endif
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))apic_free,
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = apic_save,
+ .load = apic_load
+#endif
};
}
}
-static int free_cga(struct video_internal * video_state) {
+static int cga_free(struct video_internal * video_state) {
if (video_state->framebuf_pa) {
PrintError("Freeing framebuffer PA %p\n", (void *)(video_state->framebuf_pa));
}
+#ifdef V3_CONFIG_CHECKPOINT
+static int cga_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct video_internal * cga = (struct video_internal *)private_data;
+
+ V3_CHKPT_STD_SAVE(ctx, cga->misc_outp_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->seq_index_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->seq_data_regs[SEQ_REG_COUNT]);
+ V3_CHKPT_STD_SAVE(ctx, cga->crtc_index_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->crtc_data_regs[CRTC_REG_COUNT]);
+ V3_CHKPT_STD_SAVE(ctx, cga->graphc_index_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->graphc_data_regs[GRAPHC_REG_COUNT]);
+ V3_CHKPT_STD_SAVE(ctx, cga->attrc_index_flipflop);
+ V3_CHKPT_STD_SAVE(ctx, cga->attrc_index_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->attrc_data_regs[ATTRC_REG_COUNT]);
+ V3_CHKPT_STD_SAVE(ctx, cga->dac_indexr_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->dac_indexr_color);
+ V3_CHKPT_STD_SAVE(ctx, cga->dac_indexw_reg);
+ V3_CHKPT_STD_SAVE(ctx, cga->dac_indexw_color);
+ V3_CHKPT_STD_SAVE(ctx, cga->dac_data_regs[DAC_REG_COUNT]);
+
+ V3_CHKPT_STD_SAVE(ctx, cga->activefb_addr);
+ V3_CHKPT_STD_SAVE(ctx, cga->activefb_len);
+ V3_CHKPT_STD_SAVE(ctx, cga->iorange);
+ V3_CHKPT_STD_SAVE(ctx, cga->vres);
+ V3_CHKPT_STD_SAVE(ctx, cga->hres);
+ V3_CHKPT_STD_SAVE(ctx, cga->vchars);
+ V3_CHKPT_STD_SAVE(ctx, cga->hchars);
+ V3_CHKPT_STD_SAVE(ctx, cga->graphmode);
+
+ V3_CHKPT_STD_SAVE(ctx, cga->dirty);
+ V3_CHKPT_STD_SAVE(ctx, cga->reschanged);
+
+ V3_CHKPT_STD_SAVE(ctx, cga->passthrough);
+
+ return 0;
+}
+
+static int cga_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct video_internal * cga = (struct video_internal *)private_data;
+
+ V3_CHKPT_STD_LOAD(ctx, cga->misc_outp_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->seq_index_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->seq_data_regs[SEQ_REG_COUNT]);
+ V3_CHKPT_STD_LOAD(ctx, cga->crtc_index_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->crtc_data_regs[CRTC_REG_COUNT]);
+ V3_CHKPT_STD_LOAD(ctx, cga->graphc_index_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->graphc_data_regs[GRAPHC_REG_COUNT]);
+ V3_CHKPT_STD_LOAD(ctx, cga->attrc_index_flipflop);
+ V3_CHKPT_STD_LOAD(ctx, cga->attrc_index_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->attrc_data_regs[ATTRC_REG_COUNT]);
+ V3_CHKPT_STD_LOAD(ctx, cga->dac_indexr_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->dac_indexr_color);
+ V3_CHKPT_STD_LOAD(ctx, cga->dac_indexw_reg);
+ V3_CHKPT_STD_LOAD(ctx, cga->dac_indexw_color);
+ V3_CHKPT_STD_LOAD(ctx, cga->dac_data_regs[DAC_REG_COUNT]);
+
+ V3_CHKPT_STD_LOAD(ctx, cga->activefb_addr);
+ V3_CHKPT_STD_LOAD(ctx, cga->activefb_len);
+ V3_CHKPT_STD_LOAD(ctx, cga->iorange);
+ V3_CHKPT_STD_LOAD(ctx, cga->vres);
+ V3_CHKPT_STD_LOAD(ctx, cga->hres);
+ V3_CHKPT_STD_LOAD(ctx, cga->vchars);
+ V3_CHKPT_STD_LOAD(ctx, cga->hchars);
+ V3_CHKPT_STD_LOAD(ctx, cga->graphmode);
+
+ V3_CHKPT_STD_LOAD(ctx, cga->dirty);
+ V3_CHKPT_STD_LOAD(ctx, cga->reschanged);
+
+ V3_CHKPT_STD_LOAD(ctx, cga->passthrough);
+
+ return 0;
+}
+
+#endif
+
+
static struct v3_device_ops dev_ops = {
- .free = (int (*)(void *))free_cga,
+ .free = (int (*)(void *))cga_free,
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = cga_save,
+ .load = cga_load
+#endif
+
};
static int cga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+static int io_apic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct io_apic_state * io_apic = (struct io_apic_state *)private_data;
+
+ V3_CHKPT_STD_SAVE(ctx, io_apic->base_addr);
+ V3_CHKPT_STD_SAVE(ctx, io_apic->index_reg);
+ V3_CHKPT_STD_SAVE(ctx, io_apic->ioapic_id);
+ V3_CHKPT_STD_SAVE(ctx, io_apic->ioapic_ver);
+ V3_CHKPT_STD_SAVE(ctx, io_apic->ioapic_arb_id);
+ V3_CHKPT_STD_SAVE(ctx, io_apic->redir_tbl);
+
+ return 0;
+}
+
+static int io_apic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct io_apic_state * io_apic = (struct io_apic_state *)private_data;
+
+ V3_CHKPT_STD_LOAD(ctx, io_apic->base_addr);
+ V3_CHKPT_STD_LOAD(ctx, io_apic->index_reg);
+ V3_CHKPT_STD_LOAD(ctx, io_apic->ioapic_id);
+ V3_CHKPT_STD_LOAD(ctx, io_apic->ioapic_ver);
+ V3_CHKPT_STD_LOAD(ctx, io_apic->ioapic_arb_id);
+ V3_CHKPT_STD_LOAD(ctx, io_apic->redir_tbl);
+
+ return 0;
+}
+#endif
+
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))io_apic_free,
-
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = io_apic_save,
+ .load = io_apic_load
+#endif
};
}
+#ifdef V3_CONFIG_CHECKPOINT
+static int keyboard_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ return 0;
+}
+
+
+static int keyboard_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct keyboard_internal * kbd = (struct keyboard_internal *)private_data;
+ keyboard_reset_device(kbd);
+ return 0;
+}
+
+#endif
+
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))keyboard_free,
-
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = keyboard_save,
+ .load = keyboard_load
+#endif
};
return 0;
};
+#ifdef V3_CONFIG_CHECKPOINT
+static int debug_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct debug_state * dbg = (struct debug_state *)private_data;
+
+ V3_CHKPT_STD_SAVE(ctx, dbg->debug_buf);
+ V3_CHKPT_STD_SAVE(ctx, dbg->debug_offset);
+
+ return 0;
+}
+
+
+static int debug_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct debug_state * dbg = (struct debug_state *)private_data;
+
+ V3_CHKPT_STD_LOAD(ctx, dbg->debug_buf);
+ V3_CHKPT_STD_LOAD(ctx, dbg->debug_offset);
+
+ return 0;
+}
+
+#endif
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))debug_free,
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = debug_save,
+ .load = debug_load
+#endif
};
+obj-$(V3_CONFIG_CHECKPOINT) += vmm_checkpoint.o
obj-$(V3_CONFIG_TELEMETRY) += vmm_telemetry.o
#include <palacios/vmm_rbtree.h>
#include <palacios/vmm_barrier.h>
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+#endif
#include <palacios/vmm_direct_paging.h>
}
+#ifdef V3_CONFIG_CHECKPOINT
+int v3_svm_save_core(struct guest_info * core, void * ctx){
+
+ v3_chkpt_save(ctx, "vmcb_data", PAGE_SIZE, core->vmm_data);
+
+ return 0;
+}
+
+int v3_svm_load_core(struct guest_info * core, void * chkpt_ctx){
+ struct cr0_32 * shadow_cr0;
+ vmcb_saved_state_t * guest_state;
+ vmcb_ctrl_t * guest_ctrl;
+
+
+
+ if (v3_chkpt_load(chkpt_ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1){
+ return -1;
+ }
+
+ guest_state = GET_VMCB_SAVE_STATE_AREA((vmcb_t *)(core->vmm_data));
+ guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t *)(core->vmm_data));
+
+
+ core->rip = guest_state->rip;
+ core->vm_regs.rsp = guest_state->rsp;
+ core->vm_regs.rax = guest_state->rax;
+
+ core->cpl = guest_state->cpl;
+
+ core->ctrl_regs.cr0 = guest_state->cr0;
+ core->ctrl_regs.cr2 = guest_state->cr2;
+ core->ctrl_regs.cr4 = guest_state->cr4;
+ core->dbg_regs.dr6 = guest_state->dr6;
+ core->dbg_regs.dr7 = guest_state->dr7;
+ core->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
+ core->ctrl_regs.rflags = guest_state->rflags;
+ core->ctrl_regs.efer = guest_state->efer;
+
+
+ shadow_cr0 = (struct cr0_32 *)&(core->ctrl_regs.cr0);
+
+
+ if (core->shdw_pg_mode == SHADOW_PAGING) {
+ if (shadow_cr0->pg){
+ if (v3_activate_passthrough_pt(core) == -1) {
+ PrintError("Failed to activate passthrough page tables\n");
+ return -1;
+ }
+ }
+ }
+
+
+ v3_get_vmcb_segments((vmcb_t*)(core->vmm_data), &(core->segments));
+ return 0;
+}
+#endif
+
static int update_irq_exit_state(struct guest_info * info) {
vmcb_ctrl_t * guest_ctrl = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
#include <palacios/vmx.h>
#endif
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+#endif
+
v3_cpu_arch_t v3_cpu_types[V3_CONFIG_MAX_CPUS];
struct v3_os_hooks * os_hooks = NULL;
V3_init_symmod();
#endif
+#ifdef V3_CONFIG_CHECKPOINT
+ V3_init_checkpoint();
+#endif
+
#ifdef V3_CONFIG_MULTITHREAD_OS
V3_deinit_symmod();
#endif
+#ifdef V3_CONFIG_CHECKPOINT
+ V3_deinit_checkpoint();
+#endif
+
#ifdef V3_CONFIG_MULTITHREAD_OS
if ((os_hooks) && (os_hooks->call_on_cpu)) {
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+
+int v3_save_vm(struct v3_vm_info * vm, char * store, char * url) {
+ return v3_chkpt_save_vm(vm, store, url);
+}
+
+
+int v3_load_vm(struct v3_vm_info * vm, char * store, char * url) {
+ return v3_chkpt_load_vm(vm, store, url);
+}
+#endif
+
int v3_free_vm(struct v3_vm_info * vm) {
int i = 0;
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Madhav Suresh <madhav@u.northwestern.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Madhav Suresh <madhav@u.northwestern.edu>
+ * Arefin Huq <fig@arefin.net>
+ *
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <palacios/vmm_sprintf.h>
+#include <palacios/vm_guest.h>
+#include <palacios/svm.h>
+#include <palacios/vmx.h>
+#include <palacios/vmm_checkpoint.h>
+#include <palacios/vmm_hashtable.h>
+
+#include <palacios/vmm_dev_mgr.h>
+
+
+static struct hashtable * store_table = NULL;
+
+struct v3_chkpt;
+
+typedef enum {SAVE, LOAD} chkpt_mode_t;
+
+struct chkpt_interface {
+ char name[128];
+ void * (*open_chkpt)(char * url, chkpt_mode_t mode);
+ int (*close_chkpt)(void * store_data);
+
+ void * (*open_ctx)(void * store_data, void * parent_ctx, char * name);
+ int (*close_ctx)(void * store_data, void * ctx);
+
+ int (*save)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
+ int (*load)(void * store_data, void * ctx, char * tag, uint64_t len, void * buf);
+};
+
+
+struct v3_chkpt {
+ struct v3_vm_info * vm;
+
+ struct chkpt_interface * interface;
+
+ void * store_data;
+};
+
+
+
+
+static uint_t store_hash_fn(addr_t key) {
+ char * name = (char *)key;
+ return v3_hash_buffer((uint8_t *)name, strlen(name));
+}
+
+static int store_eq_fn(addr_t key1, addr_t key2) {
+ char * name1 = (char *)key1;
+ char * name2 = (char *)key2;
+
+ return (strcmp(name1, name2) == 0);
+}
+
+
+
+#include "vmm_chkpt_stores.h"
+
+
+int V3_init_checkpoint() {
+ extern struct chkpt_interface * __start__v3_chkpt_stores[];
+ extern struct chkpt_interface * __stop__v3_chkpt_stores[];
+ struct chkpt_interface ** tmp_store = __start__v3_chkpt_stores;
+ int i = 0;
+
+ store_table = v3_create_htable(0, store_hash_fn, store_eq_fn);
+
+ while (tmp_store != __stop__v3_chkpt_stores) {
+ V3_Print("Registering Checkpoint Backing Store (%s)\n", (*tmp_store)->name);
+
+ if (v3_htable_search(store_table, (addr_t)((*tmp_store)->name))) {
+ PrintError("Multiple instances of Checkpoint backing Store (%s)\n", (*tmp_store)->name);
+ return -1;
+ }
+
+ if (v3_htable_insert(store_table, (addr_t)((*tmp_store)->name), (addr_t)(*tmp_store)) == 0) {
+ PrintError("Could not register Checkpoint backing store (%s)\n", (*tmp_store)->name);
+ return -1;
+ }
+
+ tmp_store = &(__start__v3_chkpt_stores[++i]);
+ }
+
+ return 0;
+}
+
+int V3_deinit_checkpoint() {
+ v3_free_htable(store_table, 0, 0);
+ return 0;
+}
+
+
+static char svm_chkpt_header[] = "v3vee palacios checkpoint version: x.x, SVM x.x";
+static char vmx_chkpt_header[] = "v3vee palacios checkpoint version: x.x, VMX x.x";
+
+static int chkpt_close(struct v3_chkpt * chkpt) {
+ chkpt->interface->close_chkpt(chkpt->store_data);
+
+ V3_Free(chkpt);
+
+ return 0;
+}
+
+
+static struct v3_chkpt * chkpt_open(struct v3_vm_info * vm, char * store, char * url, chkpt_mode_t mode) {
+ struct chkpt_interface * iface = NULL;
+ struct v3_chkpt * chkpt = NULL;
+ void * store_data = NULL;
+
+ iface = (void *)v3_htable_search(store_table, (addr_t)store);
+
+ if (iface == NULL) {
+ V3_Print("Error: Could not locate Checkpoint interface for store (%s)\n", store);
+ return NULL;
+ }
+
+ store_data = iface->open_chkpt(url, mode);
+
+ if (store_data == NULL) {
+ PrintError("Could not open url (%s) for backing store (%s)\n", url, store);
+ return NULL;
+ }
+
+
+ chkpt = V3_Malloc(sizeof(struct v3_chkpt));
+
+ if (!chkpt) {
+ PrintError("Could not allocate checkpoint state\n");
+ return NULL;
+ }
+
+ chkpt->interface = iface;
+ chkpt->vm = vm;
+ chkpt->store_data = store_data;
+
+ return chkpt;
+}
+
+struct v3_chkpt_ctx * v3_chkpt_open_ctx(struct v3_chkpt * chkpt, struct v3_chkpt_ctx * parent, char * name) {
+ struct v3_chkpt_ctx * ctx = V3_Malloc(sizeof(struct v3_chkpt_ctx));
+ void * parent_store_ctx = NULL;
+
+ memset(ctx, 0, sizeof(struct v3_chkpt_ctx));
+
+ ctx->chkpt = chkpt;
+ ctx->parent = parent;
+
+ if (parent) {
+ parent_store_ctx = parent->store_ctx;
+ }
+
+ ctx->store_ctx = chkpt->interface->open_ctx(chkpt->store_data, parent_store_ctx, name);
+
+ return ctx;
+}
+
+int v3_chkpt_close_ctx(struct v3_chkpt_ctx * ctx) {
+ struct v3_chkpt * chkpt = ctx->chkpt;
+ int ret = 0;
+
+ ret = chkpt->interface->close_ctx(chkpt->store_data, ctx->store_ctx);
+
+ V3_Free(ctx);
+
+ return ret;
+}
+
+
+
+
+
+int v3_chkpt_save(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
+ struct v3_chkpt * chkpt = ctx->chkpt;
+ return chkpt->interface->save(chkpt->store_data, ctx->store_ctx, tag, len, buf);
+}
+
+
+int v3_chkpt_load(struct v3_chkpt_ctx * ctx, char * tag, uint64_t len, void * buf) {
+ struct v3_chkpt * chkpt = ctx->chkpt;
+ return chkpt->interface->load(chkpt->store_data, ctx->store_ctx, tag, len, buf);
+}
+
+
+
+static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+
+ void * guest_mem_base = NULL;
+ void * ctx = NULL;
+ uint64_t ret = 0;
+
+ guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, "memory_img");
+
+ ret = v3_chkpt_load(ctx, "memory_img", vm->mem_size, guest_mem_base);
+ v3_chkpt_close_ctx(ctx);
+
+ return ret;
+}
+
+
+static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+ void * guest_mem_base = NULL;
+ void * ctx = NULL;
+ uint64_t ret = 0;
+
+ guest_mem_base = V3_VAddr((void *)vm->mem_map.base_region.host_addr);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL,"memory_img");
+
+
+ ret = v3_chkpt_save(ctx, "memory_img", vm->mem_size, guest_mem_base);
+ v3_chkpt_close_ctx(ctx);
+
+ return ret;
+}
+
+int save_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+ void * ctx = NULL;
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
+
+ switch (cpu_type) {
+ case V3_SVM_CPU:
+ case V3_SVM_REV3_CPU: {
+ v3_chkpt_save(ctx, "header", strlen(svm_chkpt_header), svm_chkpt_header);
+ break;
+ }
+ case V3_VMX_CPU:
+ case V3_VMX_EPT_CPU:
+ case V3_VMX_EPT_UG_CPU: {
+ v3_chkpt_save(ctx, "header", strlen(vmx_chkpt_header), vmx_chkpt_header);
+ break;
+ }
+ default:
+ PrintError("checkpoint not supported on this architecture\n");
+ v3_chkpt_close_ctx(ctx);
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+
+ return 0;
+}
+
+static int load_header(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+ void * ctx = NULL;
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, "header");
+
+ switch (cpu_type) {
+ case V3_SVM_CPU:
+ case V3_SVM_REV3_CPU: {
+ char header[strlen(svm_chkpt_header) + 1];
+
+ v3_chkpt_load(ctx, "header", strlen(svm_chkpt_header), header);
+
+ break;
+ }
+ case V3_VMX_CPU:
+ case V3_VMX_EPT_CPU:
+ case V3_VMX_EPT_UG_CPU: {
+ char header[strlen(vmx_chkpt_header) + 1];
+
+ v3_chkpt_load(ctx, "header", strlen(vmx_chkpt_header), header);
+
+ break;
+ }
+ default:
+ PrintError("checkpoint not supported on this architecture\n");
+ v3_chkpt_close_ctx(ctx);
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+
+ return 0;
+}
+
+
+static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) {
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+ void * ctx = NULL;
+ char key_name[16];
+ memset(key_name, 0, 16);
+
+ snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
+
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr2);
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr4);
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr8);
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.rflags);
+ V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.efer);
+
+ V3_CHKPT_STD_LOAD(ctx, info->dbg_regs);
+ V3_CHKPT_STD_LOAD(ctx, info->segments);
+ V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr3);
+ V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_cr0);
+ V3_CHKPT_STD_LOAD(ctx, info->shdw_pg_state.guest_efer);
+ v3_chkpt_close_ctx(ctx);
+
+ PrintDebug("Finished reading guest_info information\n");
+
+ info->cpu_mode = v3_get_vm_cpu_mode(info);
+ info->mem_mode = v3_get_vm_mem_mode(info);
+
+
+ switch (cpu_type) {
+ case V3_SVM_CPU:
+ case V3_SVM_REV3_CPU: {
+ char key_name[16];
+
+ snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ if (v3_svm_load_core(info, ctx) == -1) {
+ PrintError("Failed to patch core %d\n", info->vcpu_id);
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+
+ break;
+ }
+ case V3_VMX_CPU:
+ case V3_VMX_EPT_CPU:
+ case V3_VMX_EPT_UG_CPU: {
+ char key_name[16];
+
+ snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ if (v3_vmx_load_core(info, ctx) < 0) {
+ PrintError("VMX checkpoint failed\n");
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+
+ break;
+ }
+ default:
+ PrintError("Invalid CPU Type (%d)\n", cpu_type);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) {
+ v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
+ void * ctx = NULL;
+ char key_name[16];
+
+ memset(key_name, 0, 16);
+
+
+ snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
+
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr2);
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr4);
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr8);
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.rflags);
+ V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.efer);
+
+ V3_CHKPT_STD_SAVE(ctx, info->dbg_regs);
+ V3_CHKPT_STD_SAVE(ctx, info->segments);
+ V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr3);
+ V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_cr0);
+ V3_CHKPT_STD_SAVE(ctx, info->shdw_pg_state.guest_efer);
+
+ v3_chkpt_close_ctx(ctx);
+
+ //Architechture specific code
+ switch (cpu_type) {
+ case V3_SVM_CPU:
+ case V3_SVM_REV3_CPU: {
+ char key_name[16];
+ void * ctx = NULL;
+
+ snprintf(key_name, 16, "vmcb_data%d", info->vcpu_id);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ if (v3_svm_save_core(info, ctx) == -1) {
+ PrintError("VMCB Unable to be written\n");
+ v3_chkpt_close_ctx(ctx);
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+ break;
+ }
+ case V3_VMX_CPU:
+ case V3_VMX_EPT_CPU:
+ case V3_VMX_EPT_UG_CPU: {
+ char key_name[16];
+ void * ctx = NULL;
+
+ snprintf(key_name, 16, "vmcs_data%d", info->vcpu_id);
+
+ ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+
+ if (v3_vmx_save_core(info, ctx) == -1) {
+ PrintError("VMX checkpoint failed\n");
+ v3_chkpt_close_ctx(ctx);
+ return -1;
+ }
+
+ v3_chkpt_close_ctx(ctx);
+
+ break;
+ }
+ default:
+ PrintError("Invalid CPU Type (%d)\n", cpu_type);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int v3_chkpt_save_vm(struct v3_vm_info * vm, char * store, char * url) {
+ struct v3_chkpt * chkpt = NULL;
+ int ret = 0;;
+ int i = 0;
+
+ chkpt = chkpt_open(vm, store, url, SAVE);
+
+ if (chkpt == NULL) {
+ PrintError("Error creating checkpoint store\n");
+ return -1;
+ }
+
+ /* If this guest is running we need to block it while the checkpoint occurs */
+ if (vm->run_state == VM_RUNNING) {
+ while (v3_raise_barrier(vm, NULL) == -1);
+ }
+
+ if ((ret = save_memory(vm, chkpt)) == -1) {
+ PrintError("Unable to save memory\n");
+ goto out;
+ }
+
+
+ if ((ret = v3_save_vm_devices(vm, chkpt)) == -1) {
+ PrintError("Unable to save devices\n");
+ goto out;
+ }
+
+
+ if ((ret = save_header(vm, chkpt)) == -1) {
+ PrintError("Unable to save header\n");
+ goto out;
+ }
+
+ for (i = 0; i < vm->num_cores; i++){
+ if ((ret = save_core(&(vm->cores[i]), chkpt)) == -1) {
+ PrintError("chkpt of core %d failed\n", i);
+ goto out;
+ }
+ }
+
+ out:
+
+ /* Resume the guest if it was running */
+ if (vm->run_state == VM_RUNNING) {
+ v3_lower_barrier(vm);
+ }
+
+ chkpt_close(chkpt);
+
+ return ret;
+
+}
+
+int v3_chkpt_load_vm(struct v3_vm_info * vm, char * store, char * url) {
+ struct v3_chkpt * chkpt = NULL;
+ int i = 0;
+ int ret = 0;
+
+ chkpt = chkpt_open(vm, store, url, LOAD);
+
+ if (chkpt == NULL) {
+ PrintError("Error creating checkpoint store\n");
+ return -1;
+ }
+
+ /* If this guest is running we need to block it while the checkpoint occurs */
+ if (vm->run_state == VM_RUNNING) {
+ while (v3_raise_barrier(vm, NULL) == -1);
+ }
+
+ if ((ret = load_memory(vm, chkpt)) == -1) {
+ PrintError("Unable to save memory\n");
+ goto out;
+ }
+
+
+ if ((ret = v3_load_vm_devices(vm, chkpt)) == -1) {
+ PrintError("Unable to load devies\n");
+ goto out;
+ }
+
+
+ if ((ret = load_header(vm, chkpt)) == -1) {
+ PrintError("Unable to load header\n");
+ goto out;
+ }
+
+ //per core cloning
+ for (i = 0; i < vm->num_cores; i++) {
+ if ((ret = load_core(&(vm->cores[i]), chkpt)) == -1) {
+ PrintError("Error loading core state (core=%d)\n", i);
+ goto out;
+ }
+ }
+
+ out:
+
+ /* Resume the guest if it was running and we didn't just trash the state*/
+ if (vm->run_state == VM_RUNNING) {
+
+ if (ret == -1) {
+ vm->run_state = VM_STOPPED;
+ }
+
+ /* We check the run state of the VM after every barrier
+ So this will immediately halt the VM
+ */
+ v3_lower_barrier(vm);
+ }
+
+ chkpt_close(chkpt);
+
+ return ret;
+}
+
+
+
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2011, Jack Lange <jacklange@cs.pitt.edu>
+ * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jacklange@cs.pitt.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __VMM_CHKPT_STORES_H__
+#define __VMM_CHKPT_STORES_H__
+
+//#include <palacios/vmm_types.h>
+
+/*
+ * This is a place holder to ensure that the _v3_extensions section gets created by gcc
+ */
+static struct {} null_store __attribute__((__used__)) \
+ __attribute__((unused, __section__ ("_v3_chkpt_stores"), \
+ aligned(sizeof(addr_t))));
+
+
+#define register_chkpt_store(store) \
+ static struct chkpt_interface * _v3_store_##store \
+ __attribute__((used)) \
+ __attribute__((unused, __section__("_v3_chkpt_stores"), \
+ aligned(sizeof(addr_t)))) \
+ = &store;
+
+
+
+
+
+#include <palacios/vmm_util.h>
+
+
+static void * debug_open_chkpt(char * url, chkpt_mode_t mode) {
+
+ if (mode == LOAD) {
+ V3_Print("Cannot load from debug store\n");
+ return NULL;
+ }
+
+ V3_Print("Opening Checkpoint: %s\n", url);
+
+ return (void *)1;
+}
+
+
+
+static int debug_close_chkpt(void * store_data) {
+ V3_Print("Closing Checkpoint\n");
+ return 0;
+}
+
+static void * debug_open_ctx(void * store_data,
+ void * parent_ctx,
+ char * name) {
+ V3_Print("[%s]\n", name);
+ return (void *)1;
+}
+
+static int debug_close_ctx(void * store_data, void * ctx) {
+ V3_Print("[CLOSE]\n");
+ return 0;
+}
+
+static int debug_save(void * store_data, void * ctx,
+ char * tag, uint64_t len, void * buf) {
+ V3_Print("%s:\n", tag);
+
+ if (len > 100) {
+ len = 100;
+ }
+
+ v3_dump_mem(buf, len);
+
+ return 0;
+}
+
+static int debug_load(void * store_data, void * ctx,
+ char * tag, uint64_t len, void * buf) {
+ V3_Print("Loading not supported !!!\n");
+ return 0;
+}
+
+
+static struct chkpt_interface debug_store = {
+ .name = "DEBUG",
+ .open_chkpt = debug_open_chkpt,
+ .close_chkpt = debug_close_chkpt,
+ .open_ctx = debug_open_ctx,
+ .close_ctx = debug_close_ctx,
+ .save = debug_save,
+ .load = debug_load
+};
+
+register_chkpt_store(debug_store);
+
+
+
+
+#ifdef V3_CONFIG_KEYED_STREAMS
+#include <interfaces/vmm_keyed_stream.h>
+
+static void * keyed_stream_open_chkpt(char * url, chkpt_mode_t mode) {
+ if (mode == SAVE) {
+ return v3_keyed_stream_open(url, V3_KS_WR_ONLY_CREATE);
+ } else if (mode == LOAD) {
+ return v3_keyed_stream_open(url, V3_KS_RD_ONLY);
+ }
+
+ // Shouldn't get here
+ return NULL;
+}
+
+
+
+static int keyed_stream_close_chkpt(void * store_data) {
+ v3_keyed_stream_t stream = store_data;
+
+ v3_keyed_stream_close(stream);
+
+ return 0;
+}
+
+static void * keyed_stream_open_ctx(void * store_data,
+ void * parent_ctx,
+ char * name) {
+ v3_keyed_stream_t stream = store_data;
+
+ return v3_keyed_stream_open_key(stream, name);
+}
+
+static int keyed_stream_close_ctx(void * store_data, void * ctx) {
+ v3_keyed_stream_t stream = store_data;
+
+ v3_keyed_stream_close_key(stream, ctx);
+
+ return 0;
+}
+
+static int keyed_stream_save(void * store_data, void * ctx,
+ char * tag, uint64_t len, void * buf) {
+ return v3_keyed_stream_write_key(store_data, ctx, buf, len);
+}
+
+static int keyed_stream_load(void * store_data, void * ctx,
+ char * tag, uint64_t len, void * buf) {
+ return v3_keyed_stream_read_key(store_data, ctx, buf, len);
+}
+
+
+static struct chkpt_interface keyed_stream_store = {
+ .name = "KEYED_STREAM",
+ .open_chkpt = keyed_stream_open_chkpt,
+ .close_chkpt = keyed_stream_close_chkpt,
+ .open_ctx = keyed_stream_open_ctx,
+ .close_ctx = keyed_stream_close_ctx,
+ .save = keyed_stream_save,
+ .load = keyed_stream_load
+};
+
+register_chkpt_store(keyed_stream_store);
+
+
+
+#endif
+
+
+
+
+
+
+
+#endif
#include <palacios/vmm.h>
#include <palacios/vmm_decoder.h>
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+#endif
+
#ifndef V3_CONFIG_DEBUG_DEV_MGR
#undef PrintDebug
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+
+int v3_save_vm_devices(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+ struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
+ struct vm_device * dev;
+ struct v3_chkpt_ctx * dev_mgr_ctx = NULL;
+
+ uint32_t num_saved_devs = 0;
+ uint32_t table_len = mgr->num_devs * 32;
+ char * name_table = NULL;
+ uint32_t tbl_offset = 0;
+
+ name_table = V3_Malloc(table_len);
+
+ memset(name_table, 0, table_len);
+
+
+ dev_mgr_ctx = v3_chkpt_open_ctx(chkpt, NULL, "devices");
+
+ list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
+
+ if (dev->ops->save) {
+ struct v3_chkpt_ctx * dev_ctx = NULL;
+
+
+ dev_ctx = v3_chkpt_open_ctx(chkpt, dev_mgr_ctx, dev->name);
+
+ dev->ops->save(dev_ctx, dev->private_data);
+
+ v3_chkpt_close_ctx(dev_ctx);
+
+ // Error checking??
+
+ strncpy(name_table + tbl_offset, dev->name, 32);
+ tbl_offset += 32;
+ num_saved_devs++;
+ } else {
+ PrintError("Error: %s save() not implemented\n", dev->name);
+ }
+ }
+
+
+ // Specify which devices were saved
+ v3_chkpt_save(dev_mgr_ctx, "num_devs", 4, &num_saved_devs);
+ v3_chkpt_save(dev_mgr_ctx, "names", table_len, name_table);
+ V3_Free(name_table);
+
+ v3_chkpt_close_ctx(dev_mgr_ctx);
+
+ return 0;
+}
+
+
+int v3_load_vm_devices(struct v3_vm_info * vm, struct v3_chkpt * chkpt) {
+ struct vm_device * dev;
+ struct v3_chkpt_ctx * dev_mgr_ctx = NULL;
+ uint32_t num_devs = 0;
+ char * name_table = NULL;
+ int i = 0;
+
+ dev_mgr_ctx = v3_chkpt_open_ctx(chkpt, NULL, "devices");
+
+ v3_chkpt_load(dev_mgr_ctx, "num_devs", 4, &num_devs);
+
+ V3_Print("Loading State for %d devices\n", num_devs);
+
+ name_table = V3_Malloc(32 * num_devs);
+
+ v3_chkpt_load(dev_mgr_ctx, "names", 32 * num_devs, name_table);
+
+ for (i = 0; i < num_devs; i++) {
+ char * name = &(name_table[i * 32]);
+ struct v3_chkpt_ctx * dev_ctx = NULL;
+ dev = v3_find_dev(vm, name);
+
+ if (!dev) {
+ PrintError("Tried to load state into non existant device: %s\n", name);
+ continue;
+ }
+
+ if (!dev->ops->load) {
+ PrintError("Error Device (%s) does not support load operation\n", name);
+ continue;
+ }
+
+ dev_ctx = v3_chkpt_open_ctx(chkpt, dev_mgr_ctx, name);
+
+ if (!dev_ctx) {
+ PrintError("Error missing device context (%s)\n", name);
+ continue;
+ }
+
+
+ dev->ops->load(dev_ctx, dev->private_data);
+ }
+
+ return 0;
+}
+
+
+#endif
+
static int free_frontends(struct v3_vm_info * vm, struct vmm_dev_mgr * mgr);
int v3_deinit_dev_mgr(struct v3_vm_info * vm) {
#include <palacios/vmx_io.h>
#include <palacios/vmx_msr.h>
#include <palacios/vmm_decoder.h>
+#include <palacios/vmm_barrier.h>
+
+#ifdef V3_CONFIG_CHECKPOINT
+#include <palacios/vmm_checkpoint.h>
+#endif
#include <palacios/vmx_ept.h>
#include <palacios/vmx_assist.h>
}
+
+#ifdef V3_CONFIG_CHECKPOINT
+/*
+ * JRL: This is broken
+ */
+int v3_vmx_save_core(struct guest_info * core, void * ctx){
+ uint64_t vmcs_ptr = vmcs_store();
+
+ v3_chkpt_save(ctx, "vmcs_data", PAGE_SIZE, (void *)vmcs_ptr);
+
+ return 0;
+}
+
+int v3_vmx_load_core(struct guest_info * core, void * ctx){
+ struct vmx_data * vmx_info = (struct vmx_data *)(core->vmm_data);
+ struct cr0_32 * shadow_cr0;
+ char vmcs[PAGE_SIZE_4KB];
+
+ v3_chkpt_load(ctx, "vmcs_data", PAGE_SIZE_4KB, vmcs);
+
+ vmcs_clear(vmx_info->vmcs_ptr_phys);
+ vmcs_load((addr_t)vmcs);
+
+ v3_vmx_save_vmcs(core);
+
+ shadow_cr0 = (struct cr0_32 *)&(core->ctrl_regs.cr0);
+
+
+ /* Get the CPU mode to set the guest_ia32e entry ctrl */
+
+ if (core->shdw_pg_mode == SHADOW_PAGING) {
+ if (shadow_cr0->pg){
+ if (v3_activate_passthrough_pt(core) == -1) {
+ PrintError("Failed to activate passthrough page tables\n");
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+
static int update_irq_exit_state(struct guest_info * info) {
struct vmx_exit_idt_vec_info idt_vec_info;
return -1;
}
+ v3_wait_at_barrier(info);
if (info->vm_info->run_state == VM_STOPPED) {