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.


changed the emulator to use single step break points instead of page insertion
Jack Lange [Mon, 4 Aug 2008 20:21:06 +0000 (20:21 +0000)]
can now handle rep instructions

palacios/build/Makefile
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_debug.h
palacios/include/palacios/vmm_emulator.h
palacios/include/palacios/vmm_mem.h
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_emulator.c

index f057439..9d2c700 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.55 $
+# $Revision: 1.56 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
@@ -49,7 +49,7 @@ DEBUG=1
 DEBUG_SECTIONS= 
 
 ifeq ($(DEBUG_ALL),1)
-  DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_IO -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM
+  DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_IO -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR -DDEBUG_GENERIC
 endif
 ifeq ($(DEBUG_SHADOW_PAGING),1)
 DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING
@@ -75,6 +75,12 @@ endif
 ifeq ($(DEBUG_NVRAM),1)
 DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_NVRAM
 endif
+ifeq ($(DEBUG_GENERIC),1)
+DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_GENERIC
+endif
+ifeq ($(DEBUG_EMULATOR),1)
+DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_EMULATOR
+endif
 
 
 ifeq ($(DEBUG),1)
@@ -191,7 +197,6 @@ VMM_C_SRCS :=   vm_guest.c \
                 svm_halt.c svm_pause.c vmm_config.c vmm_hashtable.c \
                vmm_string.c vmm_emulator.c \
                 $(DECODER_SRCS)
-#\
 #              vmx.c vmcs_gen.c vmcs.c
 
 VMM_C_OBJS := $(VMM_C_SRCS:%.c=palacios/%.o)
index 79ba15d..2aea24c 100644 (file)
@@ -40,6 +40,16 @@ struct v3_ctrl_regs {
 };
 
 
+
+struct v3_dbg_regs {
+  v3_reg_t dr0;
+  v3_reg_t dr1;
+  v3_reg_t dr2;
+  v3_reg_t dr3;
+  v3_reg_t dr6;
+  v3_reg_t dr7;
+};
+
 struct v3_segment {
   ushort_t selector;
   uint_t limit;
@@ -120,6 +130,7 @@ struct guest_info {
 
   struct v3_gprs vm_regs;
   struct v3_ctrl_regs ctrl_regs;
+  struct v3_dbg_regs dbg_regs;
   struct v3_segments segments;
 
   struct vm_ctrl_ops vm_ops;
index db37060..2e846cd 100644 (file)
@@ -2,6 +2,100 @@
 #define __VMM_DEBUG_H
 
 
+#ifdef __V3VEE__
+#include <palacios/vmm.h>
+
+struct dbg_bp32 {
+  uint_t breakpoint : 32;
+};
+
+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
+};
+
+
+
 
 
 
@@ -10,5 +104,6 @@ void PrintDebugMemDump(unsigned char *start, int n);
 
 
 
+#endif // !__V3VEE__
 
 #endif
index 3780d1c..6e909a6 100644 (file)
@@ -49,6 +49,8 @@ struct emulation_state {
 
   uint_t running : 1;
   uint_t instr_length;
+
+  uint_t tf_enabled : 1;
 };
 
 
index 3e418ec..c51802c 100644 (file)
@@ -115,8 +115,6 @@ void print_shadow_map(struct shadow_map * map);
 
 
 
-
-
 struct vmm_mem_hook {
   // Called when data is read from a memory page
   int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
index 96ab5fb..e634b2b 100644 (file)
@@ -30,6 +30,8 @@ int handle_svm_exit(struct guest_info * info) {
   info->ctrl_regs.cr2 = guest_state->cr2;
   info->ctrl_regs.cr3 = guest_state->cr3;
   info->ctrl_regs.cr4 = guest_state->cr4;
+  info->dbg_regs.dr6 = guest_state->dr6;
+  info->dbg_regs.dr7 = guest_state->dr7;
   info->ctrl_regs.cr8 = guest_ctrl->guest_ctrl.V_TPR;
   info->ctrl_regs.rflags = guest_state->rflags;
   info->ctrl_regs.efer = guest_state->efer;
@@ -192,8 +194,22 @@ int handle_svm_exit(struct guest_info * info) {
     if (handle_svm_pause(info) == -1) { 
       return -1;
     }
+  } else if (exit_code == VMEXIT_EXCP1) {
+#ifdef DEBUG_EMULATOR
+    PrintDebug("DEBUG EXCEPTION\n");
+#endif
+    if (info->run_state == VM_EMULATING) {
+      if (v3_emulation_exit_handler(info) == -1) {
+       return -1;
+      }
+    } else {
+      PrintError("VMMCALL with not emulator...\n");
+      return -1;
+    }
   } else if (exit_code == VMEXIT_VMMCALL) {
+#ifdef DEBUG_EMULATOR
     PrintDebug("VMMCALL\n");
+#endif
     if (info->run_state == VM_EMULATING) {
       if (v3_emulation_exit_handler(info) == -1) {
        return -1;
@@ -343,6 +359,8 @@ int handle_svm_exit(struct guest_info * info) {
   guest_state->cr2 = info->ctrl_regs.cr2;
   guest_state->cr3 = info->ctrl_regs.cr3;
   guest_state->cr4 = info->ctrl_regs.cr4;
+  guest_state->dr6 = info->dbg_regs.dr6;
+  guest_state->dr7 = info->dbg_regs.dr7;
   guest_ctrl->guest_ctrl.V_TPR = info->ctrl_regs.cr8 & 0xff;
   guest_state->rflags = info->ctrl_regs.rflags;
   guest_state->efer = info->ctrl_regs.efer;
index 1e3e2f3..65c6eff 100644 (file)
 #include <devices/generic.h>
 
 
-static int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
-  //  memcpy(dst, (void*)guest_addr, length);
-  int foo = 20;
+
+static int mem_test_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
+ int foo = 20;
 
 
   memcpy(dst, &foo, length);
 
   PrintDebug("Passthrough mem read returning: %d (length=%d)\n", foo + (guest_addr & 0xfff), length);
   return length;
+ }
+
+static int passthrough_mem_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
+    memcpy(dst, (void*)guest_addr, length);
+    return length;
 }
 
 static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
@@ -93,8 +98,8 @@ int config_guest(struct guest_info * info, void * config_ptr) {
       //     
   add_shadow_region_passthrough(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160));
   
-  add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000); 
-  //hook_guest_mem(info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL);
+  //add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000); 
+  hook_guest_mem(info, 0xa0000, 0xc0000, passthrough_mem_read, passthrough_mem_write, NULL);
   
   
   // TEMP
@@ -116,7 +121,7 @@ int config_guest(struct guest_info * info, void * config_ptr) {
   { 
     /* MEMORY HOOK TEST */
     add_shadow_region_passthrough(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
-    hook_guest_mem(info, 0xa00000, 0xa01000, passthrough_mem_read, passthrough_mem_write, NULL);
+    hook_guest_mem(info, 0xa00000, 0xa01000, mem_test_read, passthrough_mem_write, NULL);
     
     add_shadow_region_passthrough(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
 
index fcce7c3..3fedc51 100644 (file)
@@ -2,9 +2,18 @@
 #include <palacios/vmm_emulator.h>
 #include <palacios/vm_guest_mem.h>
 #include <palacios/vmm_decoder.h>
+#include <palacios/vmm_debug.h>
+#include <palacios/vmcb.h>
+#include <palacios/vmm_ctrl_regs.h>
 
 static const char VMMCALL[3] = {0x0f, 0x01, 0xd9};
 
+#ifndef DEBUG_EMULATOR
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+
 int init_emulator(struct guest_info * info) {
   struct emulation_state * emulator = &(info->emulator);
 
@@ -21,6 +30,8 @@ int init_emulator(struct guest_info * info) {
   emulator->running = 0;
   emulator->instr_length = 0;
 
+  emulator->tf_enabled = 0;
+
   return 0;
 }
 
@@ -31,7 +42,7 @@ static addr_t get_new_page() {
   return (addr_t)page;
 }
 
-
+/*
 static int setup_code_page(struct guest_info * info, char * instr, struct basic_instr_info * instr_info ) {
   addr_t code_page_offset = PT32_PAGE_OFFSET(info->rip);
   addr_t code_page = get_new_page();
@@ -52,10 +63,11 @@ static int setup_code_page(struct guest_info * info, char * instr, struct basic_
   memcpy((void *)(code_page + code_page_offset), instr, instr_info->instr_length);
   memcpy((void *)(code_page + code_page_offset + instr_info->instr_length), VMMCALL, 3);
 
+#ifdef DEBUG_EMULATOR
   PrintDebug("New Instr Stream:\n");
   PrintTraceMemDump((void *)(code_page + code_page_offset), 32);
   PrintDebug("rip =%x\n", info->rip);
-
+#endif
 
 
 
@@ -70,6 +82,34 @@ static int setup_code_page(struct guest_info * info, char * instr, struct basic_
 
   return 0;
 }
+*/
+
+
+static int set_stepping(struct guest_info * info) {
+  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+  ctrl_area->exceptions.db = 1;
+
+  info->emulator.tf_enabled = ((struct rflags *)&(info->ctrl_regs.rflags))->tf;
+
+  ((struct rflags *)&(info->ctrl_regs.rflags))->tf = 1;
+
+  return 0;
+}
+
+
+static int unset_stepping(struct guest_info * info) {
+  vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA((vmcb_t*)(info->vmm_data));
+  ctrl_area->exceptions.db = 0;
+
+  ((struct rflags *)&(info->ctrl_regs.rflags))->tf = info->emulator.tf_enabled;
+
+  if (info->emulator.tf_enabled) {
+    // Inject breakpoint exception into guest
+  }
+
+  return 0;
+
+}
 
 
 // get the current instr
@@ -95,21 +135,25 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
     ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
   }
 
+#ifdef DEBUG_EMULATOR
   PrintDebug("Instr (15 bytes) at %x:\n", instr);
   PrintTraceMemDump(instr, 15);
-  
+#endif  
+
+
   if (v3_basic_mem_decode(info, (addr_t)instr, &instr_info) == -1) {
     PrintError("Could not do a basic memory instruction decode\n");
     V3_Free(data_page);
     return -1;
   }
 
+  /*
   if (instr_info.has_rep == 1) {
     PrintError("We currently don't handle rep* instructions\n");
     V3_Free(data_page);
     return -1;
   }
-
+  */
 
   data_page->page_addr = get_new_page();
   data_page->va = PT32_PAGE_ADDR(read_gva);
@@ -143,7 +187,8 @@ int v3_emulate_memory_read(struct guest_info * info, addr_t read_gva,
   }
 
 
-  setup_code_page(info, instr, &instr_info);
+  // setup_code_page(info, instr, &instr_info);
+  set_stepping(info);
 
   info->emulator.running = 1;
   info->run_state = VM_EMULATING;
@@ -181,13 +226,14 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
     return -1;
   }
 
+  /*
   if (instr_info.has_rep == 1) {
     PrintError("We currently don't handle rep* instructions\n");
     V3_Free(write_op);
     V3_Free(data_page);
     return -1;
   }
-
+  */
 
   data_page->page_addr = get_new_page();
   data_page->va = PT32_PAGE_ADDR(write_gva);
@@ -225,7 +271,8 @@ int v3_emulate_memory_write(struct guest_info * info, addr_t write_gva,
 
 
   if (info->emulator.running == 0) {
-    setup_code_page(info, instr, &instr_info);
+    //    setup_code_page(info, instr, &instr_info);
+    set_stepping(info);
     info->emulator.running = 1;
     info->run_state = VM_EMULATING;
     info->emulator.instr_length = instr_info.instr_length;
@@ -290,7 +337,14 @@ int v3_emulation_exit_handler(struct guest_info * info) {
   info->emulator.running = 0;
   //info->rip += info->emulator.instr_length;
 
+
+  PrintDebug("Returning to rip: 0x%x\n", info->rip);
+
   info->emulator.instr_length = 0;
+  
+  
+  unset_stepping(info);
+
 
   PrintDebug("returning from emulation\n");