From: Peter Dinda Date: Tue, 11 Oct 2011 22:12:11 +0000 (-0500) Subject: Merge branch 'devel' of newskysaw.cs.northwestern.edu:/home/palacios/palacios into... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=dc62d23e63c32afac8c38ec4ccb8fbea3e62ac20;hp=ed0e255bee17901009000903d6059cf1e8335cfb Merge branch 'devel' of newskysaw.cs.northwestern.edu:/home/palacios/palacios into devel --- diff --git a/linux_module/main.c b/linux_module/main.c index 9317635..62a0fb5 100644 --- a/linux_module/main.c +++ b/linux_module/main.c @@ -61,7 +61,7 @@ static long v3_dev_ioctl(struct file * filp, 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); @@ -73,7 +73,7 @@ static long v3_dev_ioctl(struct file * filp, memset(guest, 0, sizeof(struct v3_guest)); - printk("Palacios: Starting V3 Guest...\n"); + printk("Palacios: Creating V3 Guest...\n"); vm_minor = register_vm(guest); @@ -106,32 +106,23 @@ static long v3_dev_ioctl(struct file * filp, 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; } diff --git a/linux_module/palacios-stubs.c b/linux_module/palacios-stubs.c index 8eeeb7d..21aa4fd 100644 --- a/linux_module/palacios-stubs.c +++ b/linux_module/palacios-stubs.c @@ -155,12 +155,11 @@ palacios_xcall( 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); @@ -169,12 +168,14 @@ static int lnx_thread_target(void * arg) { */ - 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. } /** @@ -190,7 +191,6 @@ palacios_start_kernel_thread( thread_info->fn = fn; thread_info->arg = arg; - thread_info->name = thread_name; return kthread_run( lnx_thread_target, thread_info, thread_name ); } @@ -209,7 +209,6 @@ palacios_start_thread_on_cpu(int cpu_id, thread_info->fn = fn; thread_info->arg = arg; - thread_info->name = thread_name; thread = kthread_create( lnx_thread_target, thread_info, thread_name ); diff --git a/linux_module/palacios.h b/linux_module/palacios.h index 1ac8c03..5eca55d 100644 --- a/linux_module/palacios.h +++ b/linux_module/palacios.h @@ -8,8 +8,6 @@ /* Global Control IOCTLs */ -#define V3_START_GUEST 10 -#define V3_STOP_GUEST 11 #define V3_CREATE_GUEST 12 #define V3_FREE_GUEST 13 diff --git a/linux_module/vm.c b/linux_module/vm.c index abb798f..9869334 100644 --- a/linux_module/vm.c +++ b/linux_module/vm.c @@ -127,6 +127,27 @@ static long v3_vm_ioctl(struct file * filp, 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); @@ -246,7 +267,7 @@ extern u32 pg_frees; 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); @@ -283,17 +304,7 @@ int start_palacios_vm(struct v3_guest * 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; } @@ -301,11 +312,8 @@ int start_palacios_vm(struct v3_guest * guest) { -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); diff --git a/linux_module/vm.h b/linux_module/vm.h index f8df6c7..53af2af 100644 --- a/linux_module/vm.h +++ b/linux_module/vm.h @@ -8,8 +8,8 @@ #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, diff --git a/linux_usr/Makefile b/linux_usr/Makefile index c36a212..5bdf906 100644 --- a/linux_usr/Makefile +++ b/linux_usr/Makefile @@ -2,13 +2,14 @@ all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_stream v3_user_host_dev_exampl -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 @@ -19,8 +20,8 @@ v3_mem : v3_mem.c v3_ctrl.h 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 diff --git a/linux_usr/v3_create.c b/linux_usr/v3_create.c new file mode 100644 index 0000000..a73297f --- /dev/null +++ b/linux_usr/v3_create.c @@ -0,0 +1,113 @@ +/* + * V3 Control utility + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} diff --git a/linux_usr/v3_ctrl.h b/linux_usr/v3_ctrl.h index 0826825..442c2d9 100644 --- a/linux_usr/v3_ctrl.h +++ b/linux_usr/v3_ctrl.h @@ -6,8 +6,6 @@ #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 diff --git a/linux_usr/v3_free.c b/linux_usr/v3_free.c new file mode 100644 index 0000000..8e3c41f --- /dev/null +++ b/linux_usr/v3_free.c @@ -0,0 +1,52 @@ +/* + * V3 Control utility + * (c) Jack lange, 2011 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} + + diff --git a/linux_usr/v3_launch.c b/linux_usr/v3_launch.c new file mode 100644 index 0000000..6eb4dde --- /dev/null +++ b/linux_usr/v3_launch.c @@ -0,0 +1,48 @@ +/* + * V3 Control utility + * (c) Jack lange, 2010 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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; +} + + diff --git a/linux_usr/v3_stop.c b/linux_usr/v3_stop.c index 061cd28..a5f3249 100644 --- a/linux_usr/v3_stop.c +++ b/linux_usr/v3_stop.c @@ -15,31 +15,25 @@ #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 \n"); + printf("Usage: ./v3_stop \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); diff --git a/palacios/include/devices/pci.h b/palacios/include/devices/pci.h index 46864fd..ff2e27d 100644 --- a/palacios/include/devices/pci.h +++ b/palacios/include/devices/pci.h @@ -83,7 +83,7 @@ struct v3_pci_bar { // Internal PCI data uint32_t val; - int updated; + uint8_t updated; uint32_t mask; }; diff --git a/palacios/include/palacios/vmm_checkpoint.h b/palacios/include/palacios/vmm_checkpoint.h index 9bb5e81..17beb58 100644 --- a/palacios/include/palacios/vmm_checkpoint.h +++ b/palacios/include/palacios/vmm_checkpoint.h @@ -39,9 +39,38 @@ struct v3_chkpt_ctx { #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); diff --git a/palacios/src/devices/8259a.c b/palacios/src/devices/8259a.c index 5103791..b383151 100644 --- a/palacios/src/devices/8259a.c +++ b/palacios/src/devices/8259a.c @@ -124,35 +124,35 @@ struct ocw3 { 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; @@ -375,11 +375,11 @@ static int read_master_port1(struct guest_info * core, ushort_t port, void * dst } 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; @@ -393,7 +393,7 @@ static int read_master_port2(struct guest_info * core, ushort_t port, void * dst return -1; } - *(uchar_t *)dst = state->master_imr; + *(uint8_t *)dst = state->master_imr; return 1; @@ -408,11 +408,11 @@ static int read_slave_port1(struct guest_info * core, ushort_t port, void * dst, } 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; @@ -426,7 +426,7 @@ static int read_slave_port2(struct guest_info * core, ushort_t port, void * dst, return -1; } - *(uchar_t *)dst = state->slave_imr; + *(uint8_t *)dst = state->slave_imr; return 1; } @@ -434,7 +434,7 @@ static int read_slave_port2(struct guest_info * core, ushort_t port, void * dst, 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); @@ -502,7 +502,7 @@ static int write_master_port1(struct guest_info * core, ushort_t port, void * sr 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); @@ -563,7 +563,7 @@ static int write_master_port2(struct guest_info * core, ushort_t port, void * sr 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); @@ -624,7 +624,7 @@ static int write_slave_port1(struct guest_info * core, ushort_t port, void * src 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); @@ -741,38 +741,38 @@ static int pic_free(struct pic_internal * state) { 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; @@ -782,38 +782,39 @@ static int pic_save(struct v3_chkpt_ctx * ctx, void * private_data) { 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; } diff --git a/palacios/src/devices/atapi-types.h b/palacios/src/devices/atapi-types.h index 3fd752d..299a2bb 100644 --- a/palacios/src/devices/atapi-types.h +++ b/palacios/src/devices/atapi-types.h @@ -67,6 +67,36 @@ struct atapi_sense_data { } __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 { @@ -282,29 +312,6 @@ struct atapi_inquiry_resp { -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 { diff --git a/palacios/src/devices/cga.c b/palacios/src/devices/cga.c index 0081609..3fe3743 100644 --- a/palacios/src/devices/cga.c +++ b/palacios/src/devices/cga.c @@ -1116,6 +1116,8 @@ static int cga_free(struct video_internal * video_state) { 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]); @@ -1146,12 +1148,18 @@ static int cga_save(struct v3_chkpt_ctx * ctx, void * private_data) { 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]); @@ -1182,6 +1190,10 @@ static int cga_load(struct v3_chkpt_ctx * ctx, void * private_data) { 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; } diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c index d407551..f5baf95 100644 --- a/palacios/src/devices/ide.c +++ b/palacios/src/devices/ide.c @@ -110,16 +110,16 @@ struct ide_cd_state { }; 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 { @@ -137,11 +137,11 @@ 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; @@ -209,7 +209,7 @@ struct ide_channel { 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; }; @@ -1507,9 +1507,146 @@ static int ide_free(struct ide_internal * ide) { return 0; } +#ifdef V3_CONFIG_CHECKPOINT + +#include +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 }; diff --git a/palacios/src/devices/keyboard.c b/palacios/src/devices/keyboard.c index 5943fd3..1dc482d 100644 --- a/palacios/src/devices/keyboard.c +++ b/palacios/src/devices/keyboard.c @@ -211,8 +211,8 @@ struct keyboard_internal { // 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; @@ -1053,6 +1053,18 @@ static int keyboard_reset_device(struct keyboard_internal * kbd) { #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; } @@ -1060,6 +1072,17 @@ static int keyboard_save(struct v3_chkpt_ctx * ctx, void * private_data) { 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; } diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 0400751..05272a8 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -634,10 +634,105 @@ static int pci_free(struct pci_internal * pci_state) { return 0; } +#ifdef V3_CONFIG_CHECKPOINT + +#include + +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 }; diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 5319f90..6064855 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -345,61 +345,20 @@ int v3_deinit_svm_vmcb(struct guest_info * core) { #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 diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index 7bd275f..72f980c 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -321,6 +321,14 @@ void v3_print_guest_state(struct guest_info * info) { 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); diff --git a/palacios/src/palacios/vmcs.c b/palacios/src/palacios/vmcs.c index 2d36a3f..1de8e6a 100644 --- a/palacios/src/palacios/vmcs.c +++ b/palacios/src/palacios/vmcs.c @@ -277,8 +277,12 @@ int v3_vmx_restore_vmcs(struct guest_info * 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; " @@ -322,12 +326,48 @@ int v3_update_vmcs_host_state(struct guest_info * info) { 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__ @@ -408,8 +448,6 @@ int v3_update_vmcs_host_state(struct guest_info * info) { #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 diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index 87746ef..341996a 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -414,13 +414,9 @@ int v3_move_vm_core(struct v3_vm_info * vm, int vcore_id, int target_cpu) { */ 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; diff --git a/palacios/src/palacios/vmm_checkpoint.c b/palacios/src/palacios/vmm_checkpoint.c index f33f64e..3258779 100644 --- a/palacios/src/palacios/vmm_checkpoint.c +++ b/palacios/src/palacios/vmm_checkpoint.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -310,6 +311,8 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { 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); @@ -331,6 +334,20 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { 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: @@ -371,6 +388,8 @@ static int load_core(struct guest_info * info, struct v3_chkpt * chkpt) { return -1; } + v3_print_guest_state(info); + return 0; } @@ -382,11 +401,15 @@ static int save_core(struct guest_info * info, struct v3_chkpt * chkpt) { 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); diff --git a/palacios/src/palacios/vmm_dev_mgr.c b/palacios/src/palacios/vmm_dev_mgr.c index de6209b..d08b227 100644 --- a/palacios/src/palacios/vmm_dev_mgr.c +++ b/palacios/src/palacios/vmm_dev_mgr.c @@ -153,7 +153,8 @@ int v3_save_vm_devices(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { 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); @@ -436,6 +437,13 @@ struct vm_device * v3_add_device(struct v3_vm_info * vm, 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) { diff --git a/palacios/src/palacios/vmx.c b/palacios/src/palacios/vmx.c index 1b286ae..bdfc8c0 100644 --- a/palacios/src/palacios/vmx.c +++ b/palacios/src/palacios/vmx.c @@ -136,53 +136,6 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) /******* 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 ***********/ @@ -213,10 +166,6 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state) - - - - #ifdef __V3_64BIT__ // Ensure host runs in 64-bit mode at each VM EXIT vmx_state->exit_ctrls.host_64_on = 1;