switch (ioctl) {
- case V3_START_GUEST:{
+ case V3_CREATE_GUEST:{
int vm_minor = 0;
struct v3_guest_img user_image;
struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
memset(guest, 0, sizeof(struct v3_guest));
- printk("Palacios: Starting V3 Guest...\n");
+ printk("Palacios: Creating V3 Guest...\n");
vm_minor = register_vm(guest);
strncpy(guest->name, user_image.name, 127);
- printk("Palacios: Launching VM\n");
-
INIT_LIST_HEAD(&(guest->exts));
- if (start_palacios_vm(guest) == -1) {
- printk("Palacios: Error starting guest\n");
+ if (create_palacios_vm(guest) == -1) {
+ printk("Palacios: Error creating guest\n");
return -EFAULT;
}
- return guest->vm_dev;
+ return vm_minor;
break;
}
- case V3_STOP_GUEST: {
+ case V3_FREE_GUEST: {
unsigned long vm_idx = arg;
struct v3_guest * guest = guest_map[vm_idx];
- printk("Stopping VM idx=%d\n", vm_idx);
- printk("Stopping VM (%s) (%p)\n", guest->name, guest);
-
-
- if (irqs_disabled()) {
- printk("WHAT!!?? IRQs are disabled??\n");
- break;
- }
+ printk("Freeing VM (%s) (%p)\n", guest->name, guest);
- stop_palacios_vm(guest);
+ free_palacios_vm(guest);
guest_map[vm_idx] = NULL;
break;
}
struct lnx_thread_arg {
int (*fn)(void * arg);
void * arg;
- char * name;
};
static int lnx_thread_target(void * arg) {
struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
-
+ int ret = 0;
/*
printk("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
*/
- thread_info->fn(thread_info->arg);
+ ret = thread_info->fn(thread_info->arg);
kfree(thread_info);
// handle cleanup
+
+ do_exit(ret);
- return 0;
+ return 0; // should not get here.
}
/**
thread_info->fn = fn;
thread_info->arg = arg;
- thread_info->name = thread_name;
return kthread_run( lnx_thread_target, thread_info, thread_name );
}
thread_info->fn = fn;
thread_info->arg = arg;
- thread_info->name = thread_name;
thread = kthread_create( lnx_thread_target, thread_info, thread_name );
/* Global Control IOCTLs */
-#define V3_START_GUEST 10
-#define V3_STOP_GUEST 11
#define V3_CREATE_GUEST 12
#define V3_FREE_GUEST 13
printk("V3 IOCTL %d\n", ioctl);
switch (ioctl) {
+ case V3_VM_LAUNCH: {
+ printk("palacios: launching vm\n");
+
+ if (v3_start_vm(guest->v3_ctx, 0xfffffffe) < 0) {
+ printk("palacios: launch of vm failed\n");
+ return -1;
+ }
+
+ break;
+ }
+ case V3_VM_STOP: {
+ printk("Stopping VM (%s) (%p)\n", guest->name, guest);
+
+ if (irqs_disabled()) {
+ printk("WHAT!!?? IRQs are disabled??\n");
+ break;
+ }
+
+ v3_stop_vm(guest->v3_ctx);
+ break;
+ }
case V3_VM_PAUSE: {
printk("Pausing VM (%s)\n", guest->name);
v3_pause_vm(guest->v3_ctx);
extern u32 mallocs;
extern u32 frees;
-int start_palacios_vm(struct v3_guest * guest) {
+int create_palacios_vm(struct v3_guest * guest) {
int err;
init_vm_extensions(guest);
return -1;
}
- printk("palacios: launching vm\n");
-
- if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) {
- printk("palacios: launch of vm failed\n");
- device_destroy(v3_class, guest->vm_dev);
- cdev_del(&(guest->cdev));
- v3_free_vm(guest->v3_ctx);
- return -1;
- }
-
- printk("palacios: vm completed. returning.\n");
+ printk("palacios: vm created at /dev/v3-vm%d\n", MINOR(guest->vm_dev));
return 0;
}
-int stop_palacios_vm(struct v3_guest * guest) {
-
-
- v3_stop_vm(guest->v3_ctx);
+int free_palacios_vm(struct v3_guest * guest) {
v3_free_vm(guest->v3_ctx);
#include "palacios.h"
-int start_palacios_vm(struct v3_guest * guest);
-int stop_palacios_vm(struct v3_guest * guest);
+int create_palacios_vm(struct v3_guest * guest);
+int free_palacios_vm(struct v3_guest * guest);
int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd,
-v3_ctrl : v3_ctrl.c v3_pause.c v3_continue.c v3_ctrl.h
- gcc -static v3_ctrl.c -o v3_ctrl
+v3_ctrl : v3_ctrl.c v3_pause.c v3_continue.c v3_launch.c v3_stop.c v3_create.c v3_free.c
+ gcc -static v3_launch.c -o v3_launch
+ gcc -static v3_stop.c -o v3_stop
gcc -static v3_pause.c -o v3_pause
gcc -static v3_continue.c -o v3_continue
+ gcc -static v3_create.c -o v3_create
+ gcc -static v3_free.c -o v3_free
-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
gcc -static v3_mem.c -o v3_mem
v3_cons : v3_cons.c v3_cons_sc.c v3_ctrl.h
- gcc v3_cons.c -o v3_cons -lcurses
- gcc v3_cons_sc.c -o v3_cons_sc -lcurses
+ gcc -static v3_cons.c -o v3_cons -lcurses
+ gcc -static v3_cons_sc.c -o v3_cons_sc -lcurses
v3_stream : v3_stream.c v3_ctrl.h
gcc -static v3_stream.c -o v3_stream
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2010
+ */
+
+
+#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 "v3_ctrl.h"
+
+int read_file(int fd, int size, unsigned char * buf);
+
+int main(int argc, char* argv[]) {
+ char * filename = argv[1];
+ char * name = argv[2];
+ int guest_fd = 0;
+ int v3_fd = 0;
+ struct v3_guest_img guest_img;
+ struct stat guest_stats;
+ int dev_idx = 0;
+
+ memset(&guest_img, 0, sizeof(struct v3_guest_img));
+
+ if (argc <= 2) {
+ printf("Usage: ./v3_ctrl <guest_img> <vm name>\n");
+ return -1;
+ }
+
+ printf("Launching guest: %s\n", filename);
+
+ guest_fd = open(filename, O_RDONLY);
+
+ if (guest_fd == -1) {
+ printf("Error Opening guest image: %s\n", filename);
+ return -1;
+ }
+
+ if (fstat(guest_fd, &guest_stats) == -1) {
+ printf("ERROR: Could not stat guest image file -- %s\n", filename);
+ return -1;
+ }
+
+
+ guest_img.size = guest_stats.st_size;
+
+ // load guest image into user memory
+ guest_img.guest_data = malloc(guest_img.size);
+
+ read_file(guest_fd, guest_img.size, guest_img.guest_data);
+
+ close(guest_fd);
+
+ printf("Loaded guest image. Launching to V3Vee\n");
+
+ strncpy(guest_img.name, name, 127);
+
+
+ v3_fd = open(v3_dev, O_RDONLY);
+
+ if (v3_fd == -1) {
+ printf("Error opening V3Vee control device\n");
+ return -1;
+ }
+
+ dev_idx = ioctl(v3_fd, V3_CREATE_GUEST, &guest_img);
+
+
+ if (dev_idx < 0) {
+ printf("Error (%d) creating VM\n", dev_idx);
+ return -1;
+ }
+
+ printf("VM (%s) created at /dev/v3-vm%d\n", name, dev_idx);
+
+ /* Close the file descriptor. */
+ close(v3_fd);
+
+
+
+ return 0;
+}
+
+
+
+int read_file(int fd, int size, unsigned char * buf) {
+ int left_to_read = size;
+ int have_read = 0;
+
+ while (left_to_read != 0) {
+ int bytes_read = read(fd, buf + have_read, left_to_read);
+
+ if (bytes_read <= 0) {
+ break;
+ }
+
+ have_read += bytes_read;
+ left_to_read -= bytes_read;
+ }
+
+ if (left_to_read != 0) {
+ printf("Error could not finish reading file\n");
+ return -1;
+ }
+
+ return 0;
+}
#ifndef _v3_ctrl_h
#define _v3_ctrl_h
-#define V3_START_GUEST 10
-#define V3_STOP_GUEST 11
#define V3_CREATE_GUEST 12
#define V3_FREE_GUEST 13
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2011
+ */
+
+
+#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 "v3_ctrl.h"
+
+int main(int argc, char* argv[]) {
+ int vm_fd = 0;
+ unsigned long vm_idx = 0;
+
+
+ if (argc <= 1) {
+ printf("Usage: ./v3_free <vm-dev-idx>\n");
+ return -1;
+ }
+
+
+ vm_idx = atoi(argv[1]);
+
+ printf("Freeing VM %d\n", vm_idx);
+
+ vm_fd = open("/dev/v3vee", O_RDONLY);
+
+ if (vm_fd == -1) {
+ printf("Error opening V3Vee VM device\n");
+ return -1;
+ }
+
+ ioctl(vm_fd, V3_FREE_GUEST, vm_idx);
+
+
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+
+
+ return 0;
+}
+
+
--- /dev/null
+/*
+ * V3 Control utility
+ * (c) Jack lange, 2010
+ */
+
+
+#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 "v3_ctrl.h"
+
+int main(int argc, char* argv[]) {
+ int vm_fd = 0;
+ char * filename = argv[1];
+
+ if (argc <= 1) {
+ printf("Usage: ./v3_launch <vm-device>\n");
+ return -1;
+ }
+
+ printf("Launching VM (%s)\n", filename);
+
+ vm_fd = open(filename, O_RDONLY);
+
+ if (vm_fd == -1) {
+ printf("Error opening V3Vee VM device\n");
+ return -1;
+ }
+
+ ioctl(vm_fd, V3_VM_LAUNCH, NULL);
+
+
+
+ /* Close the file descriptor. */
+ close(vm_fd);
+
+
+
+ return 0;
+}
+
+
#include "v3_ctrl.h"
-int read_file(int fd, int size, unsigned char * buf);
-
int main(int argc, char* argv[]) {
int vm_fd = 0;
- unsigned long vm_idx = 0;
-
+ char * filename = argv[1];
if (argc <= 1) {
- printf("Usage: ./v3_stop <vm-dev-idx>\n");
+ printf("Usage: ./v3_stop <vm-device>\n");
return -1;
}
-
- vm_idx = atoi(argv[1]);
-
- printf("Stopping VM\n");
+ printf("Stopping VM (%s)\n", filename);
- vm_fd = open("/dev/v3vee", O_RDONLY);
+ vm_fd = open(filename, O_RDONLY);
if (vm_fd == -1) {
printf("Error opening V3Vee VM device\n");
return -1;
}
- ioctl(vm_fd, V3_STOP_GUEST, vm_idx);
+ ioctl(vm_fd, V3_VM_STOP, NULL);
// Internal PCI data
uint32_t val;
- int updated;
+ uint8_t updated;
uint32_t mask;
};
#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);
+static inline int v3_chkpt_save_64(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_save(ctx, tag, 8, buf);
+}
+static inline int v3_chkpt_save_32(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_save(ctx, tag, 4, buf);
+}
+static inline int v3_chkpt_save_16(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_save(ctx, tag, 2, buf);
+}
+static inline int v3_chkpt_save_8(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_save(ctx, tag, 1, buf);
+}
+
+static inline int v3_chkpt_load_64(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_load(ctx, tag, 8, buf);
+}
+static inline int v3_chkpt_load_32(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_load(ctx, tag, 4, buf);
+}
+static inline int v3_chkpt_load_16(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_load(ctx, tag, 2, buf);
+}
+static inline int v3_chkpt_load_8(struct v3_chkpt_ctx * ctx, char * tag, void * buf) {
+ return v3_chkpt_load(ctx, tag, 1, 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);
struct pic_internal {
- uchar_t master_irr;
- uchar_t slave_irr;
+ uint8_t master_irr;
+ uint8_t slave_irr;
- uchar_t master_isr;
- uchar_t slave_isr;
+ uint8_t master_isr;
+ uint8_t slave_isr;
- uchar_t master_elcr;
- uchar_t slave_elcr;
- uchar_t master_elcr_mask;
- uchar_t slave_elcr_mask;
+ uint8_t master_elcr;
+ uint8_t slave_elcr;
+ uint8_t master_elcr_mask;
+ uint8_t slave_elcr_mask;
- uchar_t master_icw1;
- uchar_t master_icw2;
- uchar_t master_icw3;
- uchar_t master_icw4;
+ uint8_t master_icw1;
+ uint8_t master_icw2;
+ uint8_t master_icw3;
+ uint8_t master_icw4;
- uchar_t slave_icw1;
- uchar_t slave_icw2;
- uchar_t slave_icw3;
- uchar_t slave_icw4;
+ uint8_t slave_icw1;
+ uint8_t slave_icw2;
+ uint8_t slave_icw3;
+ uint8_t slave_icw4;
- uchar_t master_imr;
- uchar_t slave_imr;
- uchar_t master_ocw2;
- uchar_t master_ocw3;
- uchar_t slave_ocw2;
- uchar_t slave_ocw3;
+ uint8_t master_imr;
+ uint8_t slave_imr;
+ uint8_t master_ocw2;
+ uint8_t master_ocw3;
+ uint8_t slave_ocw2;
+ uint8_t slave_ocw3;
pic_state_t master_state;
pic_state_t slave_state;
}
if ((state->master_ocw3 & 0x03) == 0x02) {
- *(uchar_t *)dst = state->master_irr;
+ *(uint8_t *)dst = state->master_irr;
} else if ((state->master_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->master_isr;
+ *(uint8_t *)dst = state->master_isr;
} else {
- *(uchar_t *)dst = 0;
+ *(uint8_t *)dst = 0;
}
return 1;
return -1;
}
- *(uchar_t *)dst = state->master_imr;
+ *(uint8_t *)dst = state->master_imr;
return 1;
}
if ((state->slave_ocw3 & 0x03) == 0x02) {
- *(uchar_t*)dst = state->slave_irr;
+ *(uint8_t*)dst = state->slave_irr;
} else if ((state->slave_ocw3 & 0x03) == 0x03) {
- *(uchar_t *)dst = state->slave_isr;
+ *(uint8_t *)dst = state->slave_isr;
} else {
- *(uchar_t *)dst = 0;
+ *(uint8_t *)dst = 0;
}
return 1;
return -1;
}
- *(uchar_t *)dst = state->slave_imr;
+ *(uint8_t *)dst = state->slave_imr;
return 1;
}
static int write_master_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write master port 1 with 0x%x\n",cw);
static int write_master_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write master port 2 with 0x%x\n",cw);
static int write_slave_port1(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write slave port 1 with 0x%x\n",cw);
static int write_slave_port2(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
struct pic_internal * state = (struct pic_internal *)priv_data;
- uchar_t cw = *(uchar_t *)src;
+ uint8_t cw = *(uint8_t *)src;
PrintDebug("8259 PIC: Write slave port 2 with 0x%x\n",cw);
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_save_8(ctx, "MASTER_IRR", &(pic->master_irr));
+ v3_chkpt_save_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
- V3_CHKPT_STD_SAVE(ctx, pic->master_isr);
- V3_CHKPT_STD_SAVE(ctx, pic->slave_isr);
+ v3_chkpt_save_8(ctx, "MASTER_ISR", &(pic->master_isr));
+ v3_chkpt_save_8(ctx, "SLAVE_ISR", &(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_save_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
+ v3_chkpt_save_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
+ v3_chkpt_save_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
+ v3_chkpt_save_8(ctx, "SLAVE_ELCR_MASK", &(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_save_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
+ v3_chkpt_save_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
+ v3_chkpt_save_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
+ v3_chkpt_save_8(ctx, "MASTER_ICW4", &(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_save_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
+ v3_chkpt_save_8(ctx, "SLAVE_ICW4", &(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_save_8(ctx, "MASTER_IMR", &(pic->master_imr));
+ v3_chkpt_save_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
+ v3_chkpt_save_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
+ v3_chkpt_save_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
+ v3_chkpt_save_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
+ v3_chkpt_save_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
- V3_CHKPT_STD_SAVE(ctx, pic->master_state);
- V3_CHKPT_STD_SAVE(ctx, pic->slave_state);
+ v3_chkpt_save_8(ctx, "MASTER_STATE", &(pic->master_state));
+ v3_chkpt_save_8(ctx, "SLAVE_STATE", &(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_load_8(ctx, "MASTER_IRR", &(pic->master_irr));
+ v3_chkpt_load_8(ctx, "SLAVE_IRR", &(pic->slave_irr));
- V3_CHKPT_STD_LOAD(ctx, pic->master_isr);
- V3_CHKPT_STD_LOAD(ctx, pic->slave_isr);
+ v3_chkpt_load_8(ctx, "MASTER_ISR", &(pic->master_isr));
+ v3_chkpt_load_8(ctx, "SLAVE_ISR", &(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_load_8(ctx, "MASTER_ELCR", &(pic->master_elcr));
+ v3_chkpt_load_8(ctx, "SLAVE_ELCR", &(pic->slave_elcr));
+ v3_chkpt_load_8(ctx, "MASTER_ELCR_MASK", &(pic->master_elcr_mask));
+ v3_chkpt_load_8(ctx, "SLAVE_ELCR_MASK", &(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_load_8(ctx, "MASTER_ICW1", &(pic->master_icw1));
+ v3_chkpt_load_8(ctx, "MASTER_ICW2", &(pic->master_icw2));
+ v3_chkpt_load_8(ctx, "MASTER_ICW3", &(pic->master_icw3));
+ v3_chkpt_load_8(ctx, "MASTER_ICW4", &(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_load_8(ctx, "SLAVE_ICW1", &(pic->slave_icw1));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW2", &(pic->slave_icw2));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW3", &(pic->slave_icw3));
+ v3_chkpt_load_8(ctx, "SLAVE_ICW4", &(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_load_8(ctx, "MASTER_IMR", &(pic->master_imr));
+ v3_chkpt_load_8(ctx, "SLAVE_IMR", &(pic->slave_imr));
+ v3_chkpt_load_8(ctx, "MASTER_OCW2", &(pic->master_ocw2));
+ v3_chkpt_load_8(ctx, "MASTER_OCW3", &(pic->master_ocw3));
+ v3_chkpt_load_8(ctx, "SLAVE_OCW2", &(pic->slave_ocw2));
+ v3_chkpt_load_8(ctx, "SLAVE_OCW3", &(pic->slave_ocw3));
- V3_CHKPT_STD_LOAD(ctx, pic->master_state);
- V3_CHKPT_STD_LOAD(ctx, pic->slave_state);
+ v3_chkpt_load_8(ctx, "MASTER_STATE", &(pic->master_state));
+ v3_chkpt_load_8(ctx, "SLAVE_STATE", &(pic->slave_state));
return 0;
}
} __attribute__((packed));
+struct atapi_error_recovery {
+ union {
+ uint8_t buf[12];
+ struct {
+ uint8_t page_code : 6;
+ uint8_t rsvd : 1;
+ uint8_t page_ctrl : 1;
+ uint8_t page_len;
+ uint8_t dcr : 1;
+ uint8_t dte : 1;
+ uint8_t per : 1;
+ uint8_t rsvd1 : 1;
+ uint8_t rc : 1;
+ uint8_t tb : 1;
+ uint8_t arre : 1;
+ uint8_t awre : 1;
+ uint8_t rd_retry_cnt;
+ uint8_t correct_spin;
+ uint8_t head_offset;
+ uint8_t data_strobe_offset;
+ uint8_t emcdr : 2;
+ uint8_t rsvd2 : 6;
+ uint8_t wr_retry_cnt;
+ uint8_t rsvd3;
+ uint16_t recovery_time_limit;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
struct atapi_read10_cmd {
-struct atapi_error_recovery {
- uint8_t page_code : 6;
- uint8_t rsvd : 1;
- uint8_t page_ctrl : 1;
- uint8_t page_len;
- uint8_t dcr : 1;
- uint8_t dte : 1;
- uint8_t per : 1;
- uint8_t rsvd1 : 1;
- uint8_t rc : 1;
- uint8_t tb : 1;
- uint8_t arre : 1;
- uint8_t awre : 1;
- uint8_t rd_retry_cnt;
- uint8_t correct_spin;
- uint8_t head_offset;
- uint8_t data_strobe_offset;
- uint8_t emcdr : 2;
- uint8_t rsvd2 : 6;
- uint8_t wr_retry_cnt;
- uint8_t rsvd3;
- uint16_t recovery_time_limit;
-} __attribute__((packed));
struct atapi_cdrom_caps {
static int cga_save(struct v3_chkpt_ctx * ctx, void * private_data) {
struct video_internal * cga = (struct video_internal *)private_data;
+ v3_chkpt_save(ctx, "FRAMEBUFFER", FRAMEBUF_SIZE, cga->framebuf);
+
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->passthrough);
+ v3_chkpt_save_16(ctx, "SCREEN_OFFSET", &(cga->screen_offset));
+ v3_chkpt_save_16(ctx, "CURSOR_OFFSET", &(cga->cursor_offset));
+
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_load(ctx, "FRAMEBUFFER", FRAMEBUF_SIZE, cga->framebuf);
+
+
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->passthrough);
+ v3_chkpt_load_16(ctx, "SCREEN_OFFSET", &(cga->screen_offset));
+ v3_chkpt_load_16(ctx, "CURSOR_OFFSET", &(cga->cursor_offset));
+
+
return 0;
}
};
struct ide_hd_state {
- int accessed;
+ uint32_t accessed;
/* this is the multiple sector transfer size as configured for read/write multiple sectors*/
- uint_t mult_sector_num;
+ uint32_t mult_sector_num;
/* This is the current op sector size:
* for multiple sector ops this equals mult_sector_num
* for standard ops this equals 1
*/
- uint_t cur_sector_num;
+ uint32_t cur_sector_num;
};
struct ide_drive {
char model[41];
// Where we are in the data transfer
- uint_t transfer_index;
+ uint32_t transfer_index;
// the length of a transfer
// calculated for easy access
- uint_t transfer_length;
+ uint32_t transfer_length;
uint64_t current_lba;
struct ide_dma_cmd_reg dma_cmd;
struct ide_dma_status_reg dma_status;
uint32_t dma_prd_addr;
- uint_t dma_tbl_index;
+ uint32_t dma_tbl_index;
};
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+
+#include <palacios/vmm_sprintf.h>
+static int ide_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct ide_internal * ide = (struct ide_internal *)private_data;
+ int ch_num = 0;
+ int drive_num = 0;
+ char buf[128];
+
+
+ for (ch_num = 0; ch_num < 2; ch_num++) {
+ struct v3_chkpt_ctx * ch_ctx = NULL;
+ struct ide_channel * ch = &(ide->channels[ch_num]);
+
+ snprintf(buf, 128, "channel-%d", ch_num);
+ ch_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+ v3_chkpt_save_8(ch_ctx, "ERROR", &(ch->error_reg.val));
+ v3_chkpt_save_8(ch_ctx, "FEATURES", &(ch->features.val));
+ v3_chkpt_save_8(ch_ctx, "DRIVE_HEAD", &(ch->drive_head.val));
+ v3_chkpt_save_8(ch_ctx, "STATUS", &(ch->status.val));
+ v3_chkpt_save_8(ch_ctx, "CMD_REG", &(ch->cmd_reg));
+ v3_chkpt_save_8(ch_ctx, "CTRL_REG", &(ch->ctrl_reg.val));
+ v3_chkpt_save_8(ch_ctx, "DMA_CMD", &(ch->dma_cmd.val));
+ v3_chkpt_save_8(ch_ctx, "DMA_STATUS", &(ch->dma_status.val));
+ v3_chkpt_save_32(ch_ctx, "PRD_ADDR", &(ch->dma_prd_addr));
+ v3_chkpt_save_32(ch_ctx, "DMA_TBL_IDX", &(ch->dma_tbl_index));
+
+
+ for (drive_num = 0; drive_num < 2; drive_num++) {
+ struct v3_chkpt_ctx * drive_ctx = NULL;
+ struct ide_drive * drive = &(ch->drives[drive_num]);
+
+ snprintf(buf, 128, "drive-%d-%d", ch_num, drive_num);
+ drive_ctx = v3_chkpt_open_ctx(ctx->chkpt, ch_ctx, buf);
+
+ v3_chkpt_save_8(drive_ctx, "DRIVE_TYPE", &(drive->drive_type));
+ v3_chkpt_save_8(drive_ctx, "SECTOR_COUNT", &(drive->sector_count));
+ v3_chkpt_save_8(drive_ctx, "SECTOR_NUM", &(drive->sector_num));
+ v3_chkpt_save_16(drive_ctx, "CYLINDER", &(drive->cylinder));
+
+ v3_chkpt_save_64(drive_ctx, "CURRENT_LBA", &(drive->current_lba));
+ v3_chkpt_save_32(drive_ctx, "TRANSFER_LENGTH", &(drive->transfer_length));
+ v3_chkpt_save_32(drive_ctx, "TRANSFER_INDEX", &(drive->transfer_index));
+
+ v3_chkpt_save(drive_ctx, "DATA_BUF", DATA_BUFFER_SIZE, drive->data_buf);
+
+
+ /* For now we'll just pack the type specific data at the end... */
+ /* We should probably add a new context here in the future... */
+ if (drive->drive_type == BLOCK_CDROM) {
+ v3_chkpt_save(drive_ctx, "ATAPI_SENSE_DATA", 18, drive->cd_state.sense.buf);
+ v3_chkpt_save_8(drive_ctx, "ATAPI_CMD", &(drive->cd_state.atapi_cmd));
+ v3_chkpt_save(drive_ctx, "ATAPI_ERR_RECOVERY", 12, drive->cd_state.err_recovery.buf);
+ } else if (drive->drive_type == BLOCK_DISK) {
+ v3_chkpt_save_32(drive_ctx, "ACCESSED", &(drive->hd_state.accessed));
+ v3_chkpt_save_32(drive_ctx, "MULT_SECT_NUM", &(drive->hd_state.mult_sector_num));
+ v3_chkpt_save_32(drive_ctx, "CUR_SECT_NUM", &(drive->hd_state.cur_sector_num));
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+static int ide_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct ide_internal * ide = (struct ide_internal *)private_data;
+ int ch_num = 0;
+ int drive_num = 0;
+ char buf[128];
+
+
+ for (ch_num = 0; ch_num < 2; ch_num++) {
+ struct v3_chkpt_ctx * ch_ctx = NULL;
+ struct ide_channel * ch = &(ide->channels[ch_num]);
+
+ snprintf(buf, 128, "channel-%d", ch_num);
+ ch_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+ v3_chkpt_load_8(ch_ctx, "ERROR", &(ch->error_reg.val));
+ v3_chkpt_load_8(ch_ctx, "FEATURES", &(ch->features.val));
+ v3_chkpt_load_8(ch_ctx, "DRIVE_HEAD", &(ch->drive_head.val));
+ v3_chkpt_load_8(ch_ctx, "STATUS", &(ch->status.val));
+ v3_chkpt_load_8(ch_ctx, "CMD_REG", &(ch->cmd_reg));
+ v3_chkpt_load_8(ch_ctx, "CTRL_REG", &(ch->ctrl_reg.val));
+ v3_chkpt_load_8(ch_ctx, "DMA_CMD", &(ch->dma_cmd.val));
+ v3_chkpt_load_8(ch_ctx, "DMA_STATUS", &(ch->dma_status.val));
+ v3_chkpt_load_32(ch_ctx, "PRD_ADDR", &(ch->dma_prd_addr));
+ v3_chkpt_load_32(ch_ctx, "DMA_TBL_IDX", &(ch->dma_tbl_index));
+
+
+ for (drive_num = 0; drive_num < 2; drive_num++) {
+ struct v3_chkpt_ctx * drive_ctx = NULL;
+ struct ide_drive * drive = &(ch->drives[drive_num]);
+
+ snprintf(buf, 128, "drive-%d-%d", ch_num, drive_num);
+ drive_ctx = v3_chkpt_open_ctx(ctx->chkpt, ch_ctx, buf);
+
+ v3_chkpt_load_8(drive_ctx, "DRIVE_TYPE", &(drive->drive_type));
+ v3_chkpt_load_8(drive_ctx, "SECTOR_COUNT", &(drive->sector_count));
+ v3_chkpt_load_8(drive_ctx, "SECTOR_NUM", &(drive->sector_num));
+ v3_chkpt_load_16(drive_ctx, "CYLINDER", &(drive->cylinder));
+
+ v3_chkpt_load_64(drive_ctx, "CURRENT_LBA", &(drive->current_lba));
+ v3_chkpt_load_32(drive_ctx, "TRANSFER_LENGTH", &(drive->transfer_length));
+ v3_chkpt_load_32(drive_ctx, "TRANSFER_INDEX", &(drive->transfer_index));
+
+ v3_chkpt_load(drive_ctx, "DATA_BUF", DATA_BUFFER_SIZE, drive->data_buf);
+
+
+ /* For now we'll just pack the type specific data at the end... */
+ /* We should probably add a new context here in the future... */
+ if (drive->drive_type == BLOCK_CDROM) {
+ v3_chkpt_load(drive_ctx, "ATAPI_SENSE_DATA", 18, drive->cd_state.sense.buf);
+ v3_chkpt_load_8(drive_ctx, "ATAPI_CMD", &(drive->cd_state.atapi_cmd));
+ v3_chkpt_load(drive_ctx, "ATAPI_ERR_RECOVERY", 12, drive->cd_state.err_recovery.buf);
+ } else if (drive->drive_type == BLOCK_DISK) {
+ v3_chkpt_load_32(drive_ctx, "ACCESSED", &(drive->hd_state.accessed));
+ v3_chkpt_load_32(drive_ctx, "MULT_SECT_NUM", &(drive->hd_state.mult_sector_num));
+ v3_chkpt_load_32(drive_ctx, "CUR_SECT_NUM", &(drive->hd_state.cur_sector_num));
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+#endif
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))ide_free,
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = ide_save,
+ .load = ide_load
+#endif
};
// Data for system
uint8_t wrap;
- int mouse_enabled;
- int scancode_set;
+ uint8_t mouse_enabled;
+ uint8_t scancode_set;
struct queue kbd_queue;
struct queue mouse_queue;
#ifdef V3_CONFIG_CHECKPOINT
static int keyboard_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct keyboard_internal * kbd = (struct keyboard_internal *)private_data;
+
+ v3_chkpt_save_8(ctx, "CMD_REG", &(kbd->cmd.val));
+ v3_chkpt_save_8(ctx, "STATUS_REG", &(kbd->status.val));
+ v3_chkpt_save_8(ctx, "STATE", &(kbd->state));
+ v3_chkpt_save_8(ctx, "MOUSE_STATE", &(kbd->mouse_state));
+ v3_chkpt_save_8(ctx, "OUTPUT", &(kbd->output_byte));
+ v3_chkpt_save_8(ctx, "INPUT", &(kbd->input_byte));
+ v3_chkpt_save_8(ctx, "SCANCODE_SET", &(kbd->scancode_set));
+ v3_chkpt_save_8(ctx, "MOUSE_ENABLED", &(kbd->mouse_enabled));
+
+
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);
+
+ v3_chkpt_load_8(ctx, "CMD_REG", &(kbd->cmd.val));
+ v3_chkpt_load_8(ctx, "STATUS_REG", &(kbd->status.val));
+ v3_chkpt_load_8(ctx, "STATE", &(kbd->state));
+ v3_chkpt_load_8(ctx, "MOUSE_STATE", &(kbd->mouse_state));
+ v3_chkpt_load_8(ctx, "OUTPUT", &(kbd->output_byte));
+ v3_chkpt_load_8(ctx, "INPUT", &(kbd->input_byte));
+ v3_chkpt_load_8(ctx, "SCANCODE_SET", &(kbd->scancode_set));
+ v3_chkpt_load_8(ctx, "MOUSE_ENABLED", &(kbd->mouse_enabled));
+
+
return 0;
}
return 0;
}
+#ifdef V3_CONFIG_CHECKPOINT
+
+#include <palacios/vmm_sprintf.h>
+
+static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pci_internal * pci = (struct pci_internal *)private_data;
+ char buf[128];
+ int i = 0;
+
+ v3_chkpt_save_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
+ v3_chkpt_save_16(ctx, "IO_BASE", &(pci->dev_io_base));
+
+ for (i = 0; i < PCI_BUS_COUNT; i++) {
+ struct pci_bus * bus = &(pci->bus_list[i]);
+ struct rb_node * node = v3_rb_first(&(bus->devices));
+ struct pci_device * dev = NULL;
+ struct v3_chkpt_ctx * bus_ctx = NULL;
+
+ snprintf(buf, 128, "pci-%d\n", i);
+
+ bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+ while (node) {
+ struct v3_chkpt_ctx * dev_ctx = NULL;
+ int bar_idx = 0;
+ dev = rb_entry(node, struct pci_device, dev_tree_node);
+
+ snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
+ dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
+
+ v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+
+ for (bar_idx = 0; bar_idx < 6; bar_idx++) {
+ snprintf(buf, 128, "BAR-%d", bar_idx);
+ v3_chkpt_save_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
+ }
+
+ node = v3_rb_next(node);
+ }
+ }
+
+
+ return 0;
+}
+
+
+static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+ struct pci_internal * pci = (struct pci_internal *)private_data;
+ char buf[128];
+ int i = 0;
+
+ v3_chkpt_load_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
+ v3_chkpt_load_16(ctx, "IO_BASE", &(pci->dev_io_base));
+
+ for (i = 0; i < PCI_BUS_COUNT; i++) {
+ struct pci_bus * bus = &(pci->bus_list[i]);
+ struct rb_node * node = v3_rb_first(&(bus->devices));
+ struct pci_device * dev = NULL;
+ struct v3_chkpt_ctx * bus_ctx = NULL;
+
+ snprintf(buf, 128, "pci-%d\n", i);
+
+ bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+ while (node) {
+ struct v3_chkpt_ctx * dev_ctx = NULL;
+ int bar_idx = 0;
+ dev = rb_entry(node, struct pci_device, dev_tree_node);
+
+ snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
+ dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
+
+ v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+
+ for (bar_idx = 0; bar_idx < 6; bar_idx++) {
+ snprintf(buf, 128, "BAR-%d", bar_idx);
+ v3_chkpt_load_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
+ }
+
+ node = v3_rb_next(node);
+ }
+ }
+
+
+ return 0;
+}
+
+
+#endif
+
+
+
static struct v3_device_ops dev_ops = {
.free = (int (*)(void *))pci_free,
-
+#ifdef V3_CONFIG_CHECKPOINT
+ .save = pci_save,
+ .load = pci_load
+#endif
};
#ifdef V3_CONFIG_CHECKPOINT
int v3_svm_save_core(struct guest_info * core, void * ctx){
+ v3_chkpt_save_8(ctx, "cpl", &(core->cpl));
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;
-
-
+int v3_svm_load_core(struct guest_info * core, void * ctx){
+
+ v3_chkpt_load_8(ctx, "cpl", &(core->cpl));
- if (v3_chkpt_load(chkpt_ctx, "vmcb_data", PAGE_SIZE, core->vmm_data) == -1){
+ if (v3_chkpt_load(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 (v3_get_vm_mem_mode(core) == VIRTUAL_MEM) {
- if (v3_activate_shadow_pt(core) == -1) {
- PrintError("Failed to activate shadow page tables\n");
- return -1;
- }
- } else {
- 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
V3_Print("NumExits: %u\n", (uint32_t)info->num_exits);
+ V3_Print("IRQ STATE: started=%d, pending=%d\n",
+ info->intr_core_state.irq_started,
+ info->intr_core_state.irq_pending);
+ V3_Print("EXCP STATE: err_code_valid=%d, err_code=%x\n",
+ info->excp_state.excp_error_code_valid,
+ info->excp_state.excp_error_code);
+
+
v3_print_segments(&(info->segments));
v3_print_ctrl_regs(info);
int v3_update_vmcs_host_state(struct guest_info * info) {
int vmx_ret = 0;
addr_t tmp;
- struct vmx_data * arch_data = (struct vmx_data *)(info->vmm_data);
struct v3_msr tmp_msr;
+ addr_t gdtr_base;
+ struct {
+ uint16_t selector;
+ addr_t base;
+ } __attribute__((packed)) tmp_seg;
#ifdef __V3_64BIT__
__asm__ __volatile__ ( "movq %%cr0, %0; "
vmx_ret |= check_vmcs_write(VMCS_HOST_CR4, tmp);
+ __asm__ __volatile__(
+ "sgdt (%0);"
+ :
+ : "q"(&tmp_seg)
+ : "memory"
+ );
+ gdtr_base = tmp_seg.base;
+ vmx_ret |= check_vmcs_write(VMCS_HOST_GDTR_BASE, tmp_seg.base);
+
+ __asm__ __volatile__(
+ "sidt (%0);"
+ :
+ : "q"(&tmp_seg)
+ : "memory"
+ );
+ vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, tmp_seg.base);
+
+ __asm__ __volatile__(
+ "str (%0);"
+ :
+ : "q"(&tmp_seg)
+ : "memory"
+ );
+ vmx_ret |= check_vmcs_write(VMCS_HOST_TR_SELECTOR, tmp_seg.selector);
+
+ /* The GDTR *index* is bits 3-15 of the selector. */
+ {
+ struct tss_descriptor * desc = NULL;
+ desc = (struct tss_descriptor *)(gdtr_base + (8 * (tmp_seg.selector >> 3)));
+
+ tmp_seg.base = ((desc->base1) |
+ (desc->base2 << 16) |
+ (desc->base3 << 24) |
+#ifdef __V3_64BIT__
+ ((uint64_t)desc->base4 << 32)
+#else
+ (0)
+#endif
+ );
- vmx_ret |= check_vmcs_write(VMCS_HOST_GDTR_BASE, arch_data->host_state.gdtr.base);
- vmx_ret |= check_vmcs_write(VMCS_HOST_IDTR_BASE, arch_data->host_state.idtr.base);
- vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, arch_data->host_state.tr.base);
-
-
+ vmx_ret |= check_vmcs_write(VMCS_HOST_TR_BASE, tmp_seg.base);
+ }
#ifdef __V3_64BIT__
#endif
vmx_ret |= check_vmcs_write(VMCS_HOST_GS_SELECTOR, tmp);
- vmx_ret |= check_vmcs_write(VMCS_HOST_TR_SELECTOR, arch_data->host_state.tr.selector);
-
#define SYSENTER_CS_MSR 0x00000174
#define SYSENTER_ESP_MSR 0x00000175
*/
core->pcpu_id = target_cpu;
- V3_Print("core now at %d\n", core->pcpu_id);
-
+ V3_Print("core now at %d\n", core->pcpu_id);
}
-
-
-
v3_lower_barrier(vm);
return 0;
#include <palacios/vmx.h>
#include <palacios/vmm_checkpoint.h>
#include <palacios/vmm_hashtable.h>
+#include <palacios/vmm_direct_paging.h>
#include <palacios/vmm_dev_mgr.h>
ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+ v3_chkpt_load_64(ctx, "RIP", &(info->rip));
+
V3_CHKPT_STD_LOAD(ctx, info->vm_regs);
V3_CHKPT_STD_LOAD(ctx, info->ctrl_regs.cr0);
info->cpu_mode = v3_get_vm_cpu_mode(info);
info->mem_mode = v3_get_vm_mem_mode(info);
+ if (info->shdw_pg_mode == SHADOW_PAGING) {
+ if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) {
+ if (v3_activate_shadow_pt(info) == -1) {
+ PrintError("Failed to activate shadow page tables\n");
+ return -1;
+ }
+ } else {
+ if (v3_activate_passthrough_pt(info) == -1) {
+ PrintError("Failed to activate passthrough page tables\n");
+ return -1;
+ }
+ }
+ }
+
switch (cpu_type) {
case V3_SVM_CPU:
return -1;
}
+ v3_print_guest_state(info);
+
return 0;
}
memset(key_name, 0, 16);
+ v3_print_guest_state(info);
+
snprintf(key_name, 16, "guest_info%d", info->vcpu_id);
ctx = v3_chkpt_open_ctx(chkpt, NULL, key_name);
+ v3_chkpt_save_64(ctx, "RIP", &(info->rip));
+
V3_CHKPT_STD_SAVE(ctx, info->vm_regs);
V3_CHKPT_STD_SAVE(ctx, info->ctrl_regs.cr0);
if (dev->ops->save) {
struct v3_chkpt_ctx * dev_ctx = NULL;
-
+
+ V3_Print("Saving state for device (%s)\n", dev->name);
dev_ctx = v3_chkpt_open_ctx(chkpt, dev_mgr_ctx, dev->name);
struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
struct vm_device * dev = NULL;
+
+ // Check if we already registered a device of the same name
+ if (v3_htable_search(mgr->dev_table, (addr_t)name) != (addr_t)NULL) {
+ PrintError("Device with name (%s) already registered with VM\n", name);
+ return NULL;
+ }
+
dev = (struct vm_device *)V3_Malloc(sizeof(struct vm_device));
if (dev == NULL) {
/******* Setup Host State **********/
/* Cache GDTR, IDTR, and TR in host struct */
- addr_t gdtr_base;
- struct {
- uint16_t selector;
- addr_t base;
- } __attribute__((packed)) tmp_seg;
-
-
- __asm__ __volatile__(
- "sgdt (%0);"
- :
- : "q"(&tmp_seg)
- : "memory"
- );
- gdtr_base = tmp_seg.base;
- vmx_state->host_state.gdtr.base = gdtr_base;
-
- __asm__ __volatile__(
- "sidt (%0);"
- :
- : "q"(&tmp_seg)
- : "memory"
- );
- vmx_state->host_state.idtr.base = tmp_seg.base;
-
- __asm__ __volatile__(
- "str (%0);"
- :
- : "q"(&tmp_seg)
- : "memory"
- );
- vmx_state->host_state.tr.selector = tmp_seg.selector;
-
- /* The GDTR *index* is bits 3-15 of the selector. */
- struct tss_descriptor * desc = NULL;
- desc = (struct tss_descriptor *)(gdtr_base + (8 * (tmp_seg.selector >> 3)));
-
- tmp_seg.base = ((desc->base1) |
- (desc->base2 << 16) |
- (desc->base3 << 24) |
-#ifdef __V3_64BIT__
- ((uint64_t)desc->base4 << 32)
-#else
- (0)
-#endif
- );
-
- vmx_state->host_state.tr.base = tmp_seg.base;
/********** Setup VMX Control Fields ***********/
-
-
-
-
#ifdef __V3_64BIT__
// Ensure host runs in 64-bit mode at each VM EXIT
vmx_state->exit_ctrls.host_64_on = 1;