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));
#include <linux/module.h>
#include <palacios/vmm.h>
+#include <palacios/vmm_host_events.h>
#include "palacios.h"
#include "vm.h"
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;
} __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... */
--- /dev/null
+/*
+ * 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;
+}
+
+
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
*/
-#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__
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:
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__
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 {
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);
};
struct list_head timer_events;
struct list_head serial_events;
struct list_head console_events;
+ struct list_head debug_events;
};
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
#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
#include <palacios/vmm_rbtree.h>
#include <palacios/vmm_barrier.h>
+#include <palacios/vmm_debug.h>
#ifdef V3_CONFIG_CHECKPOINT
#include <palacios/vmm_checkpoint.h>
#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) {
}
-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>
v3_init_time_vm(vm);
+ v3_init_vm_debugging(vm);
+
#ifdef V3_CONFIG_SYMBIOTIC
v3_init_symbiotic_vm(vm);
#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_ctrl_regs.h>
#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_debug.h>
#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>
* 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
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;
}
V3_Free(hook);
}
+
+ list_for_each_entry_safe(hook, tmp, &(host_evts->debug_events), link) {
+ list_del(&(hook->link));
+ V3_Free(hook);
+ }
+
return 0;
}
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;
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;
+}
+
#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>
}
+//
+// 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,
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;
#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>
#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>
#include <palacios/vmm_halt.h>
#include <palacios/vmx_ept.h>
+
#ifndef V3_CONFIG_DEBUG_VMX
#undef PrintDebug
#define PrintDebug(fmt, args...)