Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added dedicated debugging framework with associated interface
Jack Lange [Wed, 20 Jun 2012 19:28:38 +0000 (15:28 -0400)]
19 files changed:
linux_module/palacios.h
linux_module/vm.c
linux_usr/v3_ctrl.h
linux_usr/v3_debug.c [new file with mode: 0644]
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_debug.h
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_host_events.h
palacios/src/devices/keyboard.c
palacios/src/palacios/svm.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vmcs.c
palacios/src/palacios/vmm_checkpoint.c
palacios/src/palacios/vmm_debug.c
palacios/src/palacios/vmm_host_events.c
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_symcall.c
palacios/src/palacios/vmx.c
palacios/src/palacios/vmx_handler.c

index 11d3314..4933028 100644 (file)
@@ -70,7 +70,12 @@ struct v3_mem_region {
     unsigned long long num_pages;
 } __attribute__((packed));
 
-struct v3_core_move_cmd{
+struct v3_debug_cmd {
+    unsigned int core; 
+    unsigned int cmd;
+} __attribute__((packed));
+
+struct v3_core_move_cmd {
     unsigned short vcore_id;
     unsigned short pcore_id;
 } __attribute__((packed));
index 88e3bef..40cfa06 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 
 #include <palacios/vmm.h>
+#include <palacios/vmm_host_events.h>
 
 #include "palacios.h"
 #include "vm.h"
@@ -208,6 +209,30 @@ static long v3_vm_ioctl(struct file * filp,
            break;
        }
 #endif
+       case V3_VM_DEBUG: {
+           struct v3_debug_cmd cmd;
+           struct v3_debug_event evt;
+           void __user * argp = (void __user *)arg;        
+
+           memset(&cmd, 0, sizeof(struct v3_debug_cmd));
+           
+           if (copy_from_user(&cmd, argp, sizeof(struct v3_debug_cmd))) {
+               printk("Error: Could not copy debug command from user space\n");
+               return -EFAULT;
+           }
+
+           evt.core_id = cmd.core;
+           evt.cmd = cmd.cmd;
+
+           printk("Debugging VM\n");
+
+           if (v3_deliver_debug_event(guest->v3_ctx, &evt) == -1) {
+               printk("Error could not deliver debug cmd\n");
+               return -EFAULT;
+           }
+
+           break;
+       }
        case V3_VM_MOVE_CORE: {
            struct v3_core_move_cmd cmd;
            void __user * argp = (void __user *)arg;
index e904263..97cb0fd 100644 (file)
@@ -56,6 +56,11 @@ struct v3_core_move_cmd{
 } __attribute__((packed));
 
 
+struct v3_debug_cmd {
+    unsigned int core; 
+    unsigned int cmd;
+} __attribute__((packed));
+
 struct v3_chkpt_info {
     char store[128];
     char url[256]; /* This might need to be bigger... */
diff --git a/linux_usr/v3_debug.c b/linux_usr/v3_debug.c
new file mode 100644 (file)
index 0000000..b609646
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+ * V3 debug interface
+ * (c) Jack Lange, 2012
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h> 
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "v3_ctrl.h"
+
+
+int main(int argc, char* argv[]) {
+    int vm_fd;
+    char * vm_dev = NULL;
+    struct v3_debug_cmd cmd; 
+
+    if (argc < 4) {
+       printf("Usage: v3_core_migrate <vm_device> <vm core> <cmd>\n");
+       return -1;
+    }
+
+    vm_dev = argv[1];
+    cmd.core = atoi(argv[2]);
+    cmd.cmd = atoi(argv[3]);
+
+    printf("Debug Virtual Core %d with Command %d\n", cmd.core, cmd.cmd);
+
+    vm_fd = open(vm_dev, O_RDONLY);
+
+    if (vm_fd == -1) {
+       printf("Error opening VM device: %s\n", vm_dev);
+       return -1;
+    }
+
+    int err = ioctl(vm_fd, V3_VM_DEBUG, &cmd); 
+
+    if (err < 0) {
+       printf("Error write core migrating command to vm\n");
+       return -1;
+    }
+
+    close(vm_fd); 
+
+    return 0; 
+}
+
+
index 49e8598..fb91c1d 100644 (file)
@@ -219,19 +219,10 @@ v3_mem_mode_t v3_get_vm_mem_mode(struct guest_info * info);
 const uchar_t * v3_cpu_mode_to_str(v3_cpu_mode_t mode);
 const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode);
 
-int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg);
 
 
-void v3_print_guest_state(struct guest_info * info);
-
-void v3_print_segments(struct v3_segments * segs);
-void v3_print_ctrl_regs(struct guest_info * info);
-void v3_print_GPRs(struct guest_info * info);
-
-void v3_print_stack(struct guest_info * info);
-
 #endif /* ! __V3VEE__ */
 
-void v3_print_guest_state_all(struct v3_vm_info * vm);
+
 
 #endif
index 9d68359..bbb253e 100644 (file)
  */
 
 
-#ifndef __VMM_DEBUG_H
-#define __VMM_DEBUG_H
+#ifndef __VMM_DEBUG_H__
+#define __VMM_DEBUG_H__
 
 
 #ifdef __V3VEE__
 
 #include <palacios/vmm.h>
+#include <palacios/vmm_regs.h>
 
-struct dbg_bp32 {
-    uint_t breakpoint : 32;
-};
+int v3_init_vm_debugging(struct v3_vm_info * vm);
 
-struct dbg_bp64 {
-    ullong_t breakpoint;
-};
 
-struct dr6_32 {
-    uint_t bp0 : 1;
-    uint_t bp1 : 1;
-    uint_t bp2 : 1;
-    uint_t bp3 : 1;
-    uint_t rsvd1 : 8; // read as ones
-    uint_t rsvd2 : 1; // read as zero
-    uint_t bd  : 1; 
-    uint_t bs  : 1;
-    uint_t bt  : 1;
-    uint_t rsvd3 : 16; // read as one
-};
-
-
-struct dr6_64 {
-    uint_t bp0 : 1;
-    uint_t bp1 : 1;
-    uint_t bp2 : 1;
-    uint_t bp3 : 1;
-    uint_t rsvd1 : 8; // read as ones
-    uint_t rsvd2 : 1; // read as zero
-    uint_t bd  : 1; 
-    uint_t bs  : 1;
-    uint_t bt  : 1;
-    uint_t rsvd3 : 16; // read as one
-    uint_t rsvd4 : 32; // MBZ
-};
-
-
-struct dr7_32 {
-    uint_t L0   : 1;
-    uint_t G0   : 1;
-    uint_t L1   : 1;
-    uint_t G1   : 1;
-    uint_t L2   : 1;
-    uint_t G2   : 1;
-    uint_t L3   : 1;
-    uint_t G3   : 1;
-    uint_t LE   : 1;
-    uint_t GE   : 1;
-    uint_t rsvd1 : 1; // Read as one
-    uint_t rsvd2 : 2; // Read as zero
-    uint_t GD   : 1;
-    uint_t rsvd3 : 2; // Read as zero
-    uint_t rw0  : 1;
-    uint_t len0 : 1;
-    uint_t rw1  : 1;
-    uint_t len1 : 1;
-    uint_t rw2  : 1;
-    uint_t len2 : 1;
-    uint_t rw3  : 1;
-    uint_t len3 : 1;
-};
-
-
-struct dr7_64 {
-    uint_t L0   : 1;
-    uint_t G0   : 1;
-    uint_t L1   : 1;
-    uint_t G1   : 1;
-    uint_t L2   : 1;
-    uint_t G2   : 1;
-    uint_t L3   : 1;
-    uint_t G3   : 1;
-    uint_t LE   : 1;
-    uint_t GE   : 1;
-    uint_t rsvd1 : 1; // Read as one
-    uint_t rsvd2 : 2; // Read as zero
-    uint_t GD   : 1;
-    uint_t rsvd3 : 2; // Read as zero
-    uint_t rw0  : 1;
-    uint_t len0 : 1;
-    uint_t rw1  : 1;
-    uint_t len1 : 1;
-    uint_t rw2  : 1;
-    uint_t len2 : 1;
-    uint_t rw3  : 1;
-    uint_t len3 : 1;
-    uint_t rsvd4 : 32; // MBZ
-};
-
-
-
-
-
-
-void PrintDebugHex(uchar_t x);
-void PrintDebugMemDump(uchar_t * start, int n);
+void v3_print_guest_state(struct guest_info * core);
+void v3_print_arch_state(struct guest_info * core);
 
+void v3_print_segments(struct v3_segments * segs);
+void v3_print_ctrl_regs(struct guest_info * core);
+void v3_print_GPRs(struct guest_info * core);
 
+void v3_print_backtrace(struct guest_info * core);
+void v3_print_stack(struct guest_info * core);
+void v3_print_guest_state_all(struct v3_vm_info * vm);
 
 #endif // !__V3VEE__
 
index 03c5edb..b1e87c2 100644 (file)
@@ -204,12 +204,10 @@ static inline v3_reg_t get_gpr_mask(struct guest_info * info) {
 
 static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) {
     switch (info->cpu_mode) {
-       case REAL:
-           // It appears that the segment values are computed and cached in the vmcb structure 
-           // We Need to check this for Intel
-           /*   return addr + (seg->selector << 4);
-                break;*/
-
+       case REAL: {
+           return ((seg->selector & 0xffff) << 4) + (addr & 0xffff);
+           break;
+       }
        case PROTECTED:
        case PROTECTED_PAE:
        case LONG_32_COMPAT:
index 47c6715..21d4c01 100644 (file)
@@ -43,9 +43,11 @@ struct v3_console_event {
     unsigned int cmd;
 };
 
-struct v3_packet_event {
-    unsigned char * pkt;
-    unsigned int size;
+
+struct v3_debug_event {
+    unsigned int core_id;
+    unsigned int cmd;
+
 };
 
 #ifdef __V3VEE__
@@ -58,7 +60,8 @@ typedef enum { HOST_KEYBOARD_EVT,
               HOST_MOUSE_EVT, 
               HOST_TIMER_EVT,
               HOST_CONSOLE_EVT,
-              HOST_SERIAL_EVT} v3_host_evt_type_t;
+              HOST_SERIAL_EVT, 
+               HOST_DEBUG_EVT} v3_host_evt_type_t;
 
 
 union v3_host_event_handler {
@@ -67,6 +70,7 @@ union v3_host_event_handler {
     int (*timer_handler)(struct v3_vm_info * vm, struct v3_timer_event * evt, void * priv_data);
     int (*serial_handler)(struct v3_vm_info * vm, struct v3_serial_event * evt, void * priv_data);
     int (*console_handler)(struct v3_vm_info * vm, struct v3_console_event * evt, void * priv_data);
+    int (*debug_handler)(struct v3_vm_info * vm, struct v3_debug_event * evt, void * priv_data);
 };
 
 
@@ -84,6 +88,7 @@ struct v3_host_events {
     struct list_head timer_events;
     struct list_head serial_events;
     struct list_head console_events;
+    struct list_head debug_events;
 };
 
 
@@ -107,6 +112,7 @@ int v3_deliver_mouse_event(struct v3_vm_info * vm, struct v3_mouse_event * evt);
 int v3_deliver_timer_event(struct v3_vm_info * vm, struct v3_timer_event * evt);
 int v3_deliver_serial_event(struct v3_vm_info * vm, struct v3_serial_event * evt);
 int v3_deliver_console_event(struct v3_vm_info * vm, struct v3_console_event * evt);
+int v3_deliver_debug_event(struct v3_vm_info * vm, struct v3_debug_event * evt);
 
 
 #endif
index 039db76..b451e2e 100644 (file)
@@ -26,6 +26,7 @@
 #include <palacios/vmm_intr.h>
 #include <palacios/vmm_host_events.h>
 #include <palacios/vm_guest.h>
+#include <palacios/vmm_debug.h>
 
 
 #ifndef V3_CONFIG_DEBUG_KEYBOARD
index 434e3bd..c98a48b 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <palacios/vmm_rbtree.h>
 #include <palacios/vmm_barrier.h>
+#include <palacios/vmm_debug.h>
 
 #ifdef V3_CONFIG_CHECKPOINT
 #include <palacios/vmm_checkpoint.h>
index df30d1d..e17feb9 100644 (file)
@@ -31,6 +31,7 @@
 #include <palacios/vmm_xed.h>
 #include <palacios/vmm_direct_paging.h>
 #include <palacios/vmm_barrier.h>
+#include <palacios/vmm_debug.h>
 
 
 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
@@ -162,326 +163,9 @@ const uchar_t * v3_mem_mode_to_str(v3_mem_mode_t mode) {
 }
 
 
-void v3_print_segments(struct v3_segments * segs) {
-    int i = 0;
-    struct v3_segment * seg_ptr;
 
-    seg_ptr=(struct v3_segment *)segs;
-  
-    char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
-    V3_Print("Segments\n");
 
-    for (i = 0; seg_names[i] != NULL; i++) {
 
-       V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
-                  (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
-                  seg_ptr[i].long_mode, seg_ptr[i].db);
-
-    }
-}
-
-//
-// We don't handle those fancy 64 bit system segments...
-//
-int v3_translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
-    struct v3_segment * gdt = &(info->segments.gdtr);
-    addr_t gdt_addr = 0;
-    uint16_t seg_offset = (selector & ~0x7);
-    addr_t seg_addr = 0;
-    struct gen_segment * gen_seg = NULL;
-    struct seg_selector sel;
-
-    memset(seg, 0, sizeof(struct v3_segment));
-
-    sel.value = selector;
-
-    if (sel.ti == 1) {
-       PrintError("LDT translations not supported\n");
-       return -1;
-    }
-
-    if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
-       PrintError("Unable to translate GDT address\n");
-       return -1;
-    }
-
-    seg_addr = gdt_addr + seg_offset;
-    gen_seg = (struct gen_segment *)seg_addr;
-
-    //translate
-    seg->selector = selector;
-
-    seg->limit = gen_seg->limit_hi;
-    seg->limit <<= 16;
-    seg->limit += gen_seg->limit_lo;
-
-    seg->base = gen_seg->base_hi;
-    seg->base <<= 24;
-    seg->base += gen_seg->base_lo;
-
-    if (gen_seg->granularity == 1) {
-       seg->limit <<= 12;
-       seg->limit |= 0xfff;
-    }
-
-    seg->type = gen_seg->type;
-    seg->system = gen_seg->system;
-    seg->dpl = gen_seg->dpl;
-    seg->present = gen_seg->present;
-    seg->avail = gen_seg->avail;
-    seg->long_mode = gen_seg->long_mode;
-    seg->db = gen_seg->db;
-    seg->granularity = gen_seg->granularity;
-    
-    return 0;
-}
-
-
-
-
-void v3_print_ctrl_regs(struct guest_info * info) {
-    struct v3_ctrl_regs * regs = &(info->ctrl_regs);
-    int i = 0;
-    v3_reg_t * reg_ptr;
-    char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
-   
-
-    reg_ptr = (v3_reg_t *)regs;
-
-    V3_Print("Ctrl Regs:\n");
-
-    for (i = 0; reg_names[i] != NULL; i++) {
-       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
-    }
-
-
-}
-
-#if 0
-static int safe_gva_to_hva(struct guest_info * info, addr_t linear_addr, addr_t * host_addr) {
-    /* select the proper translation based on guest mode */
-    if (info->mem_mode == PHYSICAL_MEM) {
-       if (v3_gpa_to_hva(info, linear_addr, host_addr) == -1) return -1;
-    } else if (info->mem_mode == VIRTUAL_MEM) {
-       if (v3_gva_to_hva(info, linear_addr, host_addr) == -1) return -1;
-    }
-    return 0;
-}
-
-static int v3_print_disassembly(struct guest_info * info) {
-    int passed_rip = 0;
-    addr_t rip, rip_linear, rip_host;
-
-    /* we don't know where the instructions preceding RIP start, so we just take
-     * a guess and hope the instruction stream synced up with our disassembly
-     * some time before RIP; if it has not we correct RIP at that point
-     */
-
-    /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
-    rip = (addr_t) info->rip - 64;
-    while ((int) (rip - info->rip) < 32) {
-       V3_Print("disassembly step\n");
-
-       /* always print RIP, even if the instructions before were bad */
-       if (!passed_rip && rip >= info->rip) {
-           if (rip != info->rip) {
-               V3_Print("***** bad disassembly up to this point *****\n");
-               rip = info->rip;
-           }
-           passed_rip = 1;
-       }
-
-       /* look up host virtual address for this instruction */
-       rip_linear = get_addr_linear(info, rip, &(info->segments.cs));
-       if (safe_gva_to_hva(info, rip_linear, &rip_host) < 0) {
-           rip++;
-           continue;
-       }
-
-       /* print disassembled instrcution (updates rip) */
-       if (v3_disasm(info, (void *) rip_host, &rip, rip == info->rip) < 0) {
-           rip++;
-           continue;
-       }
-
-    }
-
-    return 0;
-}
-
-#endif
-
-void v3_print_guest_state(struct guest_info * info) {
-    addr_t linear_addr = 0; 
-
-    V3_Print("RIP: %p\n", (void *)(addr_t)(info->rip));
-    linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs));
-    V3_Print("RIP Linear: %p\n", (void *)linear_addr);
-
-    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);
-
-    if (info->shdw_pg_mode == SHADOW_PAGING) {
-       V3_Print("Shadow Paging Guest Registers:\n");
-       V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr0));
-       V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_cr3));
-       V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(info->shdw_pg_state.guest_efer.value));
-       // CR4
-    }
-    v3_print_GPRs(info);
-
-    v3_print_mem_map(info->vm_info);
-
-    v3_print_stack(info);
-
-    //  v3_print_disassembly(info);
-}
-
-void v3_print_guest_state_all(struct v3_vm_info * vm) {
-    int i = 0;
-
-    V3_Print("VM Core states for %s\n", vm->name);
-
-    for (i = 0; i < 80; i++) {
-       V3_Print("-");
-    }
-
-    for (i = 0; i < vm->num_cores; i++) {
-       v3_print_guest_state(&vm->cores[i]);  
-    }
-    
-    for (i = 0; i < 80; i++) {
-       V3_Print("-");
-    }
-
-    V3_Print("\n");    
-}
-
-static void print_real_mode_stack(struct guest_info *info)
-{
-    uint16_t ss;
-    uint16_t sp;
-    addr_t   addr;
-    addr_t   host_addr;
-    int      i;
-
-
-    ss = info->segments.ss.selector & 0xffff;
-    sp = info->vm_regs.rsp & 0xffff;
-    addr = (((uint32_t)ss)<<4) + sp;
-
-   
-    V3_Print("Real Mode Stack starting at 0x%x:0x%x (0x%p):\n",ss,sp,(void*)addr);
-
-    if (info->mem_mode!=PHYSICAL_MEM) {
-       PrintError("Cannot print real mode stack when virtual memory active\n");
-       return;
-    }
-       
-    for (i=0;i<=24;i++,sp+=2) { 
-       // note that it's correct for this to wrap around
-       addr = (((uint32_t)ss)<<4) + sp;
-       if (v3_gpa_to_hva(info,addr,&host_addr)) { 
-           PrintError("Could not translate physical stack address 0x%p\n",(void*)addr);
-           return;
-       }
-       V3_Print("\t0x%.4x\n",*((uint16_t*)host_addr));
-    }
-}
-       
-
-
-
-void v3_print_stack(struct guest_info * info) {
-    addr_t linear_addr = 0;
-    addr_t host_addr = 0;
-    int i = 0;
-    v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(info);
-
-
-    if (cpu_mode==REAL) { 
-       print_real_mode_stack(info);
-       return;
-    }
-
-    // protected mode, 32 or 64 bit
-
-    linear_addr = get_addr_linear(info, info->vm_regs.rsp, &(info->segments.ss));
-    V3_Print("Stack at %p:\n", (void *)linear_addr);
-   
-    if (info->mem_mode == PHYSICAL_MEM) {
-       if (v3_gpa_to_hva(info, linear_addr, &host_addr) == -1) {
-           PrintError("Could not translate Stack address\n");
-           return;
-       }
-    } else if (info->mem_mode == VIRTUAL_MEM) {
-       if (v3_gva_to_hva(info, linear_addr, &host_addr) == -1) {
-           PrintError("Could not translate Virtual Stack address\n");
-           return;
-       }
-    }
-    
-    V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
-    // We start i at one because the current stack pointer points to an unused stack element
-    for (i = 0; i <= 24; i++) {
-       if (cpu_mode == LONG) {
-           V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
-       } else {
-           // 32 bit stacks...
-           V3_Print("\t%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
-       }
-    }
-
-}    
-
-#ifdef __V3_32BIT__
-
-void v3_print_GPRs(struct guest_info * info) {
-    struct v3_gprs * regs = &(info->vm_regs);
-    int i = 0;
-    v3_reg_t * reg_ptr;
-    char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
-
-    reg_ptr = (v3_reg_t *)regs;
-
-    V3_Print("32 bit GPRs:\n");
-
-    for (i = 0; reg_names[i] != NULL; i++) {
-       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
-    }
-}
-
-#elif __V3_64BIT__
-
-void v3_print_GPRs(struct guest_info * info) {
-    struct v3_gprs * regs = &(info->vm_regs);
-    int i = 0;
-    v3_reg_t * reg_ptr;
-    char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
-                          "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
-
-    reg_ptr = (v3_reg_t *)regs;
-
-    V3_Print("64 bit GPRs:\n");
-
-    for (i = 0; reg_names[i] != NULL; i++) {
-       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
-    }
-}
-
-#endif
 
 
 #include <palacios/vmcs.h>
@@ -564,6 +248,8 @@ int v3_init_vm(struct v3_vm_info * vm) {
 
     v3_init_time_vm(vm);
 
+    v3_init_vm_debugging(vm);
+
 
 #ifdef V3_CONFIG_SYMBIOTIC
     v3_init_symbiotic_vm(vm);
index 67c6f69..85ee7a7 100644 (file)
@@ -24,6 +24,7 @@
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_ctrl_regs.h>
 #include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_debug.h>
 
 
 
index ef99cdf..f1ac18d 100644 (file)
@@ -27,6 +27,7 @@
 #include <palacios/vmm_checkpoint.h>
 #include <palacios/vmm_hashtable.h>
 #include <palacios/vmm_direct_paging.h>
+#include <palacios/vmm_debug.h>
 
 #include <palacios/vmm_dev_mgr.h>
 
index 51f1c0f..9b2eb6a 100644 (file)
  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
+
 #include <palacios/vmm_debug.h>
 #include <palacios/vmm.h>
+#include <palacios/vmm_host_events.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_decoder.h>
+#include <palacios/vm_guest_mem.h>
+
+#define PRINT_TELEMETRY  1
+#define PRINT_CORE_STATE 2
+#define PRINT_ARCH_STATE 3
+#define PRINT_STACK      4
+#define PRINT_BACKTRACE  5
+
+
+#define PRINT_ALL        100 // Absolutely everything
+#define PRINT_STATE      101 // telemetry, core state, arch state
+
+
+
+
+static int core_handler(struct guest_info * core, uint32_t cmd) {
+
+
+    switch (cmd) {
+       case PRINT_TELEMETRY: 
+           v3_print_core_telemetry(core);
+           break;
+       
+       case PRINT_CORE_STATE:
+           v3_raise_barrier(core->vm_info, NULL);
+
+           v3_print_guest_state(core);
+
+           v3_lower_barrier(core->vm_info);
+           break;
+       case PRINT_ARCH_STATE:
+           v3_raise_barrier(core->vm_info, NULL);
+
+           v3_print_arch_state(core);
+
+           v3_lower_barrier(core->vm_info);
+           break;
+       case PRINT_STACK:
+           v3_raise_barrier(core->vm_info, NULL);
+
+           v3_print_stack(core);
+
+           v3_lower_barrier(core->vm_info);
+           break;
+       case PRINT_BACKTRACE:
+           v3_raise_barrier(core->vm_info, NULL);
+
+           v3_print_backtrace(core);
+           
+           v3_lower_barrier(core->vm_info);
+           break;
+
+       case PRINT_STATE:
+           v3_raise_barrier(core->vm_info, NULL);
+
+           v3_print_core_telemetry(core);
+           v3_print_guest_state(core);
+           v3_print_arch_state(core);
+
+           v3_lower_barrier(core->vm_info);
+           break;
+
+    }
+
+    return 0;
+}
+
+
+static int evt_handler(struct v3_vm_info * vm, struct v3_debug_event * evt, void * priv_data) {
+
+    V3_Print("Debug Event Handler for core %d\n", evt->core_id);
+
+    if (evt->core_id == -1) {
+       int i = 0;
+       for (i = 0; i < vm->num_cores; i++) {
+           core_handler(&(vm->cores[i]), evt->cmd);
+       }
+    } else {
+       return core_handler(&vm->cores[evt->core_id], evt->cmd);
+    }
+
+    
+    return 0;
+}
 
 
-void PrintDebugHex(uchar_t x) {
-    unsigned char z;
+int v3_init_vm_debugging(struct v3_vm_info * vm) {
+    v3_hook_host_event(vm, HOST_DEBUG_EVT, 
+                      V3_HOST_EVENT_HANDLER(evt_handler), 
+                      NULL);
+
+
+    return 0;
+}
+
+
+
+
+
+void v3_print_segments(struct v3_segments * segs) {
+    int i = 0;
+    struct v3_segment * seg_ptr;
+
+    seg_ptr=(struct v3_segment *)segs;
   
-    z = (x >> 4) & 0xf ;
-    PrintDebug("%x", z);
-    z = x & 0xf;
-    PrintDebug("%x", z);
+    char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
+    V3_Print("Segments\n");
+
+    for (i = 0; seg_names[i] != NULL; i++) {
+
+       V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
+                  (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
+                  seg_ptr[i].long_mode, seg_ptr[i].db);
+
+    }
 }
 
-void PrintDebugMemDump(uchar_t *start, int n) {
-    int i, j;
 
-    for (i = 0; i < n; i += 16) {
-       PrintDebug("%p", (void *)(start + i));
 
-       for (j = i; (j < (i + 16)) && (j < n); j += 2) {
-           PrintDebug(" ");
-           PrintDebugHex(*((uchar_t *)(start + j)));
+void v3_print_ctrl_regs(struct guest_info * core) {
+    struct v3_ctrl_regs * regs = &(core->ctrl_regs);
+    int i = 0;
+    v3_reg_t * reg_ptr;
+    char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
+   
 
-           if ((j + 1) < n) { 
-               PrintDebugHex(*((uchar_t *)(start + j + 1)));
-           }
+    reg_ptr = (v3_reg_t *)regs;
+
+    V3_Print("Ctrl Regs:\n");
+
+    for (i = 0; reg_names[i] != NULL; i++) {
+       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
+    }
+
+
+}
+
+#if 0
+static int safe_gva_to_hva(struct guest_info * core, addr_t linear_addr, addr_t * host_addr) {
+    /* select the proper translation based on guest mode */
+    if (core->mem_mode == PHYSICAL_MEM) {
+       if (v3_gpa_to_hva(core, linear_addr, host_addr) == -1) return -1;
+    } else if (core->mem_mode == VIRTUAL_MEM) {
+       if (v3_gva_to_hva(core, linear_addr, host_addr) == -1) return -1;
+    }
+    return 0;
+}
+
+static int v3_print_disassembly(struct guest_info * core) {
+    int passed_rip = 0;
+    addr_t rip, rip_linear, rip_host;
+
+    /* we don't know where the instructions preceding RIP start, so we just take
+     * a guess and hope the instruction stream synced up with our disassembly
+     * some time before RIP; if it has not we correct RIP at that point
+     */
+
+    /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
+    rip = (addr_t) core->rip - 64;
+    while ((int) (rip - core->rip) < 32) {
+       V3_Print("disassembly step\n");
+
+       /* always print RIP, even if the instructions before were bad */
+       if (!passed_rip && rip >= core->rip) {
+           if (rip != core->rip) {
+               V3_Print("***** bad disassembly up to this point *****\n");
+               rip = core->rip;
+           }
+           passed_rip = 1;
+       }
+
+       /* look up host virtual address for this instruction */
+       rip_linear = get_addr_linear(core, rip, &(core->segments.cs));
+       if (safe_gva_to_hva(core, rip_linear, &rip_host) < 0) {
+           rip++;
+           continue;
+       }
+
+       /* print disassembled instrcution (updates rip) */
+       if (v3_disasm(core, (void *) rip_host, &rip, rip == core->rip) < 0) {
+           rip++;
+           continue;
+       }
+
+    }
 
+    return 0;
+}
+
+#endif
+
+void v3_print_guest_state(struct guest_info * core) {
+    addr_t linear_addr = 0; 
+
+    V3_Print("RIP: %p\n", (void *)(addr_t)(core->rip));
+    linear_addr = get_addr_linear(core, core->rip, &(core->segments.cs));
+    V3_Print("RIP Linear: %p\n", (void *)linear_addr);
+
+    V3_Print("NumExits: %u\n", (uint32_t)core->num_exits);
+
+    V3_Print("IRQ STATE: started=%d, pending=%d\n", 
+            core->intr_core_state.irq_started, 
+            core->intr_core_state.irq_pending);
+    V3_Print("EXCP STATE: err_code_valid=%d, err_code=%x\n", 
+            core->excp_state.excp_error_code_valid, 
+            core->excp_state.excp_error_code);
+
+
+    v3_print_segments(&(core->segments));
+    v3_print_ctrl_regs(core);
+
+    if (core->shdw_pg_mode == SHADOW_PAGING) {
+       V3_Print("Shadow Paging Guest Registers:\n");
+       V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr0));
+       V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr3));
+       V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_efer.value));
+       // CR4
+    }
+    v3_print_GPRs(core);
+
+    v3_print_mem_map(core->vm_info);
+
+    v3_print_stack(core);
+
+    //  v3_print_disassembly(core);
+}
+
+
+void v3_print_arch_state(struct guest_info * core) {
+
+
+}
+
+
+void v3_print_guest_state_all(struct v3_vm_info * vm) {
+    int i = 0;
+
+    V3_Print("VM Core states for %s\n", vm->name);
+
+    for (i = 0; i < 80; i++) {
+       V3_Print("-");
+    }
+
+    for (i = 0; i < vm->num_cores; i++) {
+       v3_print_guest_state(&vm->cores[i]);  
+    }
+    
+    for (i = 0; i < 80; i++) {
+       V3_Print("-");
+    }
+
+    V3_Print("\n");    
+}
+
+
+
+void v3_print_stack(struct guest_info * core) {
+    addr_t linear_addr = 0;
+    addr_t host_addr = 0;
+    int i = 0;
+    v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
+
+    linear_addr = get_addr_linear(core, core->vm_regs.rsp, &(core->segments.ss));
+    V3_Print("Stack at %p:\n", (void *)linear_addr);
+   
+    if (core->mem_mode == PHYSICAL_MEM) {
+       if (v3_gpa_to_hva(core, linear_addr, &host_addr) == -1) {
+           PrintError("Could not translate Stack address\n");
+           return;
+       }
+    } else if (core->mem_mode == VIRTUAL_MEM) {
+       if (v3_gva_to_hva(core, linear_addr, &host_addr) == -1) {
+           PrintError("Could not translate Virtual Stack address\n");
+           return;
+       }
+    }
+    
+    V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
+    // We start i at one because the current stack pointer points to an unused stack element
+    for (i = 0; i <= 24; i++) {
+
+       if (cpu_mode == REAL) {
+           V3_Print("\t0x%.4x\n", *((uint16_t *)host_addr + (i * 2)));
+       } else if (cpu_mode == LONG) {
+           V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
+       } else {
+           // 32 bit stacks...
+           V3_Print("\t0x%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
        }
+    }
+
+}    
+
 
-       PrintDebug(" ");
+void v3_print_backtrace(struct guest_info * core) {
+    addr_t gla_rbp = 0;
+    int i = 0;
+    v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
 
-       for (j = i; (j < (i + 16)) && (j < n); j++) {
-           PrintDebug("%c", ((start[j] >= 32) && (start[j] <= 126)) ? start[j] : '.');
+    V3_Print("Performing Backtrace for Core %d\n", core->vcpu_id);
+    V3_Print("\tRSP=%p, RBP=%p\n", (void *)core->vm_regs.rsp, (void *)core->vm_regs.rbp);
+
+    gla_rbp = get_addr_linear(core, core->vm_regs.rbp, &(core->segments.ss));
+
+    for (i = 0; i < 10; i++) {
+       addr_t hva_rbp = 0; 
+       addr_t hva_rip = 0; 
+
+       if (core->mem_mode == PHYSICAL_MEM) {
+           if (v3_gpa_to_hva(core, gla_rbp, &hva_rbp) == -1) {
+               PrintError("Could not translate Stack address\n");
+               return;
+           }
+       } else if (core->mem_mode == VIRTUAL_MEM) {
+           if (v3_gva_to_hva(core, gla_rbp, &hva_rbp) == -1) {
+               PrintError("Could not translate Virtual Stack address\n");
+               return;
+           }
        }
 
-       PrintDebug("\n");
+       hva_rip = hva_rbp + v3_get_addr_width(core);
+
+       
+       if (cpu_mode == REAL) {
+           V3_Print("Next RBP=0x%.4x, RIP=0x%.4x\n", *(uint16_t *)hva_rbp,*(uint16_t *)hva_rip);
+           gla_rbp = *(uint16_t *)hva_rbp;
+       } else if (cpu_mode == LONG) {
+           V3_Print("Next RBP=%p, RIP=%p\n", (void *)*(uint64_t *)hva_rbp, (void *)*(uint64_t *)hva_rip);
+           gla_rbp = *(uint64_t *)hva_rbp;
+       } else {
+           V3_Print("Next RBP=0x%.8x, RIP=0x%.8x\n", *(uint32_t *)hva_rbp, *(uint32_t *)hva_rip);
+           gla_rbp = *(uint32_t *)hva_rbp;
+       }
     }
 }
+
+
+#ifdef __V3_32BIT__
+
+void v3_print_GPRs(struct guest_info * core) {
+    struct v3_gprs * regs = &(core->vm_regs);
+    int i = 0;
+    v3_reg_t * reg_ptr;
+    char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
+
+    reg_ptr = (v3_reg_t *)regs;
+
+    V3_Print("32 bit GPRs:\n");
+
+    for (i = 0; reg_names[i] != NULL; i++) {
+       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
+    }
+}
+
+#elif __V3_64BIT__
+
+void v3_print_GPRs(struct guest_info * core) {
+    struct v3_gprs * regs = &(core->vm_regs);
+    int i = 0;
+    v3_reg_t * reg_ptr;
+    char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
+                          "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
+
+    reg_ptr = (v3_reg_t *)regs;
+
+    V3_Print("64 bit GPRs:\n");
+
+    for (i = 0; reg_names[i] != NULL; i++) {
+       V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
+    }
+}
+
+#endif
index 28543f7..9d834d6 100644 (file)
@@ -29,6 +29,7 @@ int v3_init_host_events(struct v3_vm_info * vm) {
     INIT_LIST_HEAD(&(host_evts->timer_events));
     INIT_LIST_HEAD(&(host_evts->serial_events));
     INIT_LIST_HEAD(&(host_evts->console_events));
+    INIT_LIST_HEAD(&(host_evts->debug_events));
 
     return 0;
 }
@@ -66,6 +67,12 @@ int v3_deinit_host_events(struct v3_vm_info * vm) {
        V3_Free(hook);
     }
 
+
+    list_for_each_entry_safe(hook, tmp, &(host_evts->debug_events), link) {
+       list_del(&(hook->link));
+       V3_Free(hook);
+    }
+
     return 0;
 }
 
@@ -103,6 +110,9 @@ int v3_hook_host_event(struct v3_vm_info * vm,
        case HOST_CONSOLE_EVT:
            list_add(&(hook->link), &(host_evts->console_events));
            break;
+       case HOST_DEBUG_EVT:
+           list_add(&(hook->link), &(host_evts->debug_events));
+           break;
     }
 
     return 0;
@@ -218,3 +228,26 @@ int v3_deliver_console_event(struct v3_vm_info * vm,
     return 0;
 }
 
+
+
+int v3_deliver_debug_event(struct v3_vm_info * vm, 
+                          struct v3_debug_event * evt) {
+    struct v3_host_events * host_evts = NULL;
+    struct v3_host_event_hook * hook = NULL;
+
+
+    host_evts = &(vm->host_event_hooks);
+
+    if (vm->run_state != VM_RUNNING) {
+       return -1;
+    }
+
+    list_for_each_entry(hook, &(host_evts->debug_events), link) {
+       if (hook->cb.debug_handler(vm, evt, hook->private_data) == -1) {
+           return -1;
+       }
+    }
+
+    return 0;
+}
+
index 3753a93..ee99811 100644 (file)
@@ -22,6 +22,7 @@
 #include <palacios/vmm_util.h>
 #include <palacios/vmm_emulator.h>
 #include <palacios/vm_guest.h>
+#include <palacios/vmm_debug.h>
 
 #include <palacios/vmm_shadow_paging.h>
 #include <palacios/vmm_direct_paging.h>
index c78fe88..7044e9a 100644 (file)
@@ -161,6 +161,64 @@ static int execute_symcall(struct guest_info * core) {
 }
 
 
+//
+// We don't handle those fancy 64 bit system segments...
+//
+static int translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
+    struct v3_segment * gdt = &(info->segments.gdtr);
+    addr_t gdt_addr = 0;
+    uint16_t seg_offset = (selector & ~0x7);
+    addr_t seg_addr = 0;
+    struct gen_segment * gen_seg = NULL;
+    struct seg_selector sel;
+
+    memset(seg, 0, sizeof(struct v3_segment));
+
+    sel.value = selector;
+
+    if (sel.ti == 1) {
+       PrintError("LDT translations not supported\n");
+       return -1;
+    }
+
+    if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
+       PrintError("Unable to translate GDT address\n");
+       return -1;
+    }
+
+    seg_addr = gdt_addr + seg_offset;
+    gen_seg = (struct gen_segment *)seg_addr;
+
+    //translate
+    seg->selector = selector;
+
+    seg->limit = gen_seg->limit_hi;
+    seg->limit <<= 16;
+    seg->limit += gen_seg->limit_lo;
+
+    seg->base = gen_seg->base_hi;
+    seg->base <<= 24;
+    seg->base += gen_seg->base_lo;
+
+    if (gen_seg->granularity == 1) {
+       seg->limit <<= 12;
+       seg->limit |= 0xfff;
+    }
+
+    seg->type = gen_seg->type;
+    seg->system = gen_seg->system;
+    seg->dpl = gen_seg->dpl;
+    seg->present = gen_seg->present;
+    seg->avail = gen_seg->avail;
+    seg->long_mode = gen_seg->long_mode;
+    seg->db = gen_seg->db;
+    seg->granularity = gen_seg->granularity;
+    
+    return 0;
+}
+
+
+
 int v3_sym_call(struct guest_info * core, 
                uint64_t call_num, sym_arg_t * arg0, 
                sym_arg_t * arg1, sym_arg_t * arg2,
@@ -200,10 +258,10 @@ int v3_sym_call(struct guest_info * core,
     core->rip = state->sym_call_rip;
     core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
 
-    v3_translate_segment(core, state->sym_call_cs, &sym_cs);
+    translate_segment(core, state->sym_call_cs, &sym_cs);
     memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment));
  
-    v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss);
+    translate_segment(core, state->sym_call_cs + 8, &sym_ss);
     memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment));
 
     core->segments.gs.base = state->sym_call_gs;
index 0950045..d9fc081 100644 (file)
@@ -34,6 +34,7 @@
 #include <palacios/vmm_decoder.h>
 #include <palacios/vmm_barrier.h>
 #include <palacios/vmm_timeout.h>
+#include <palacios/vmm_debug.h>
 
 #ifdef V3_CONFIG_CHECKPOINT
 #include <palacios/vmm_checkpoint.h>
index 51bf62d..0cf500f 100644 (file)
@@ -24,6 +24,7 @@
 #include <palacios/vmx_lowlevel.h>
 #include <palacios/vmx_io.h>
 #include <palacios/vmm_cpuid.h>
+#include <palacios/vmm_debug.h>
 
 #include <palacios/vmx.h>
 #include <palacios/vmm_ctrl_regs.h>
@@ -33,6 +34,7 @@
 #include <palacios/vmm_halt.h>
 #include <palacios/vmx_ept.h>
 
+
 #ifndef V3_CONFIG_DEBUG_VMX
 #undef PrintDebug
 #define PrintDebug(fmt, args...)