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 decoder support for cr0 write handler
[palacios-OLD.git] / palacios / src / palacios / vmm_xed.c
index 036501d..afa4f69 100644 (file)
@@ -6,6 +6,8 @@
 static xed_state_t decoder_state;
 
 
+// This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
+static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
 
 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len);
 
@@ -66,16 +68,9 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
   xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
 
-
-  
-
   xed_error = xed_decode(&xed_instr, 
                         REINTERPRET_CAST(const xed_uint8_t *, instr_ptr), 
                         XED_MAX_INSTRUCTION_BYTES);
-  
-
-
-
 
 
   if (xed_error != XED_ERROR_NONE) {
@@ -88,34 +83,41 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
   instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
   instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
 
+  xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
+
+  if (get_opcode(iform, &(instr->opcode)) == -1) {
+    PrintError("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
+    return -1;
+  }
+
+
 
   PrintDebug("Number of operands: %d\n", instr->num_operands);
+  PrintDebug("INSTR length: %d\n", instr->instr_length);
 
   // set first operand
   if (instr->num_operands >= 1) {
     const xed_operand_t * op = xed_inst_operand(xi, 0);
     xed_operand_type_enum_t op_type = xed_operand_type(op);
-    
-    switch (op_type) {
-    case XED_OPERAND_TYPE_REG:
-      {
-       xed_operand_enum_t op_enum = xed_operand_name(op);
-       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-       if (xed_reg_to_v3_reg(info, 
-                             xed_reg, 
-                             &(instr->dst_operand.operand), 
-                             &(instr->dst_operand.size)) == -1) {
-
-         PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
-         return -1;
-       }
+    xed_operand_enum_t op_enum = xed_operand_name(op);
+
+
+    if (xed_operand_is_register(op_enum)) {
+      xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
+      if (xed_reg_to_v3_reg(info, 
+                           xed_reg, 
+                           &(instr->first_operand.operand), 
+                           &(instr->first_operand.size)) == -1) {
+       
+       PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
+       instr->first_operand.type = INVALID_OPERAND;
+       return -1;
       }
-    case XED_OPERAND_TYPE_INVALID:
-    case XED_OPERAND_TYPE_ERROR:
-    case XED_OPERAND_TYPE_IMM:
-    case XED_OPERAND_TYPE_IMM_CONST:
-    case XED_OPERAND_TYPE_NT_LOOKUP_FN:
-    case XED_OPERAND_TYPE_LAST:
+
+      instr->first_operand.type = REG_OPERAND;
+      PrintDebug("xed_reg=0x%x, cr0=0x%x\n", instr->first_operand.operand, &(info->ctrl_regs.cr0));
+
+    } else {
       PrintError("Unhandled first operand type %s\n", xed_operand_type_enum_t2str(op_type));
       return -1;
     }
@@ -123,29 +125,26 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
   // set second operand
   if (instr->num_operands >= 2) {
-    const xed_operand_t * op = xed_inst_operand(xi, 0);
+    const xed_operand_t * op = xed_inst_operand(xi, 1);
     xed_operand_type_enum_t op_type = xed_operand_type(op);
+    xed_operand_enum_t op_enum = xed_operand_name(op);
     
-    switch (op_type) {
-    case XED_OPERAND_TYPE_REG:
-      {
-       xed_operand_enum_t op_enum = xed_operand_name(op);
-       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-       if (xed_reg_to_v3_reg(info, 
-                             xed_reg, 
-                             &(instr->src_operand.operand), 
-                             &(instr->src_operand.size)) == -1) {
-
-         PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
-         return -1;
-       }
+    if (xed_operand_is_register(op_enum)) {
+      xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
+      if (xed_reg_to_v3_reg(info, 
+                           xed_reg, 
+                           &(instr->second_operand.operand), 
+                           &(instr->second_operand.size)) == -1) {
+       
+       PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
+       instr->second_operand.type = INVALID_OPERAND;
+       return -1;
       }
-    case XED_OPERAND_TYPE_INVALID:
-    case XED_OPERAND_TYPE_ERROR:
-    case XED_OPERAND_TYPE_IMM:
-    case XED_OPERAND_TYPE_IMM_CONST:
-    case XED_OPERAND_TYPE_NT_LOOKUP_FN:
-    case XED_OPERAND_TYPE_LAST:
+
+      instr->second_operand.type = REG_OPERAND;
+      PrintDebug("xed_reg=0x%x, eax=0x%x\n", instr->second_operand.operand, &(info->vm_regs.rax));
+      
+    } else {
       PrintError("Unhandled second operand type %s\n", xed_operand_type_enum_t2str(op_type));
       return -1;
     }
@@ -153,29 +152,23 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
   // set third operand
   if (instr->num_operands >= 3) {
-    const xed_operand_t * op = xed_inst_operand(xi, 0);
+    const xed_operand_t * op = xed_inst_operand(xi, 2);
     xed_operand_type_enum_t op_type = xed_operand_type(op);
-    
-    switch (op_type) {
-    case XED_OPERAND_TYPE_REG:
-      {
-       xed_operand_enum_t op_enum = xed_operand_name(op);
-       xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
-       if (xed_reg_to_v3_reg(info, 
-                             xed_reg, 
-                             &(instr->extra_operand.operand), 
-                             &(instr->extra_operand.size)) == -1) {
-
-         PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
-         return -1;
-       }
+    xed_operand_enum_t op_enum = xed_operand_name(op);
+
+    if (xed_operand_is_register(op_enum)) {
+      xed_reg_enum_t xed_reg =  xed_decoded_inst_get_reg(&xed_instr, op_enum);
+      if (xed_reg_to_v3_reg(info, 
+                           xed_reg, 
+                           &(instr->third_operand.operand), 
+                           &(instr->third_operand.size)) == -1) {
+       
+       PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
+       instr->third_operand.type = INVALID_OPERAND;
+       return -1;
       }
-    case XED_OPERAND_TYPE_INVALID:
-    case XED_OPERAND_TYPE_ERROR:
-    case XED_OPERAND_TYPE_IMM:
-    case XED_OPERAND_TYPE_IMM_CONST:
-    case XED_OPERAND_TYPE_NT_LOOKUP_FN:
-    case XED_OPERAND_TYPE_LAST:
+      instr->third_operand.type = REG_OPERAND;
+    } else {
       PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
       return -1;
     }
@@ -207,7 +200,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins
 
 
 
-    return -1;
+    return 0;
 }
 
 
@@ -632,3 +625,35 @@ static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, a
 
   return 0;
 }
+
+
+
+static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
+
+  switch (iform) {
+  case XED_IFORM_MOV_CR_GPR64_CR:
+  case XED_IFORM_MOV_CR_GPR32_CR:
+    *opcode = (addr_t)&V3_OPCODE_MOVCR2;
+    break;
+
+  case XED_IFORM_MOV_CR_CR_GPR64:
+  case XED_IFORM_MOV_CR_CR_GPR32:
+    *opcode = (addr_t)&V3_OPCODE_MOV2CR;
+    break;
+
+
+  case XED_IFORM_LMSW_GPR16:
+    *opcode = (addr_t)&V3_OPCODE_LMSW;
+    break;
+
+  case XED_IFORM_CLTS:
+    *opcode = (addr_t)&V3_OPCODE_CLTS;
+    break;
+
+  default:
+    *opcode = 0;
+    return -1;
+  }
+
+  return 0;
+}