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.


merge VNET Linux backend code into Linux module directory
[palacios.releases.git] / palacios / src / palacios / vmm_v3dec.c
index f02d04b..74c8c56 100644 (file)
 #include <palacios/vmm_instr_decoder.h>
 
 
-/* Disgusting mask hack...
-   I can't think right now, so we'll do it this way...
-*/
-static const ullong_t mask_1 = 0x00000000000000ffLL;
-static const ullong_t mask_2 = 0x000000000000ffffLL;
-static const ullong_t mask_4 = 0x00000000ffffffffLL;
-static const ullong_t mask_8 = 0xffffffffffffffffLL;
-
-
-#define MASK(val, length) ({                   \
-           ullong_t mask = 0x0LL;              \
-           switch (length) {                   \
-               case 1:                         \
-                   mask = mask_1;              \
-                   break;                      \
-               case 2:                         \
-                   mask = mask_2;              \
-                   break;                      \
-               case 4:                         \
-                   mask = mask_4;              \
-                   break;                      \
-               case 8:                         \
-                   mask = mask_8;              \
-                   break;                      \
-           }                                   \
-           val & mask;                         \
-       })
+#define MASK(val, length) ({                                           \
+            ullong_t mask = 0x0LL;                                     \
+            switch (length) {                                          \
+               case 1:                                                 \
+                   mask = 0x00000000000000ffLL;                        \
+                    break;                                             \
+                case 2:                                                        \
+                    mask = 0x000000000000ffffLL;                       \
+                    break;                                             \
+                case 4:                                                        \
+                    mask = 0x00000000ffffffffLL;                       \
+                    break;                                             \
+                case 8:                                                        \
+                    mask = 0xffffffffffffffffLL;                       \
+                    break;                                             \
+            }                                                          \
+            val & mask;                                                        \
+        })
 
 static v3_op_type_t op_form_to_type(op_form_t form);
 static int parse_operands(struct guest_info * core, uint8_t * instr_ptr, struct x86_instr * instr, op_form_t form);
@@ -87,7 +78,21 @@ int v3_decode(struct guest_info * core, addr_t instr_ptr, struct x86_instr * ins
     length = v3_get_prefixes((uint8_t *)instr_ptr, &(instr->prefixes));
 
 
-    // check for REX prefix
+    // REX prefix
+    if (v3_get_vm_cpu_mode(core) == LONG) {
+       uint8_t prefix = *(uint8_t *)(instr_ptr + length);
+
+       if ((prefix & 0xf0) == 0x40) {
+           instr->prefixes.rex = 1;
+
+           instr->prefixes.rex_rm = (prefix & 0x01);
+           instr->prefixes.rex_sib_idx = ((prefix & 0x02) >> 1);
+           instr->prefixes.rex_reg = ((prefix & 0x04) >> 2);
+           instr->prefixes.rex_op_size = ((prefix & 0x08) >> 3);
+
+           length += 1;
+       }
+    }
 
 
     form = op_code_to_form((uint8_t *)(instr_ptr + length), &length);
@@ -124,7 +129,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
                          struct x86_instr * instr, op_form_t form) {
     // get operational mode of the guest for operand width
     uint8_t operand_width = get_operand_width(core, instr, form);
-    uint8_t addr_width = get_addr_width(core, instr, form);
+    uint8_t addr_width = get_addr_width(core, instr);
     int ret = 0;
     uint8_t * instr_start = instr_ptr;
     
@@ -148,9 +153,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
        case MOV_IMM2:{
            uint8_t reg_code = 0;
 
-           instr->dst_operand.size = operand_width;
-
-           ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
+           ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
 
            if (ret == -1) {
                PrintError("Error decoding operand\n");
@@ -162,6 +165,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            instr->src_operand.type = IMM_OPERAND;
            instr->src_operand.size = operand_width;
 
+
            if (operand_width == 1) {
                instr->src_operand.operand = *(uint8_t *)instr_ptr;
            } else if (operand_width == 2) {
@@ -173,6 +177,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
                return -1;
            }
 
+           instr->src_operand.read = 1;
+           instr->dst_operand.write = 1;
+
            instr_ptr += operand_width;
 
            instr->num_operands = 2;
@@ -195,9 +202,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
        case MOV_2MEM: {
            uint8_t reg_code = 0;
 
-           instr->dst_operand.size = operand_width;
-
-           ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
+           ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
 
            if (ret == -1) {
                PrintError("Error decoding operand\n");
@@ -209,6 +214,10 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            instr->src_operand.type = REG_OPERAND;
            instr->src_operand.size = operand_width;
 
+           instr->src_operand.read = 1;
+           instr->dst_operand.write = 1;
+
+
            decode_gpr(core, reg_code, &(instr->src_operand));
 
            instr->num_operands = 2;
@@ -229,9 +238,8 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
        case XOR_MEM2:
        case MOV_MEM2: {
            uint8_t reg_code = 0;
-           instr->src_operand.size = operand_width;
 
-           ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand), &reg_code);
+           ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand), &reg_code);
 
            if (ret == -1) {
                PrintError("Error decoding operand\n");
@@ -244,6 +252,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            instr->dst_operand.type = REG_OPERAND;
            decode_gpr(core, reg_code, &(instr->dst_operand));
 
+           instr->src_operand.read = 1;
+           instr->dst_operand.write = 1;
+
            instr->num_operands = 2;
 
            break;
@@ -255,9 +266,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
        case SUB_IMM2SX_8:
        case XOR_IMM2SX_8: {
            uint8_t reg_code = 0;
-           instr->src_operand.size = operand_width;
 
-           ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand), &reg_code);
+           ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
+
 
            if (ret == -1) {
                PrintError("Error decoding operand\n");
@@ -270,6 +281,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            instr->src_operand.size = operand_width;
            instr->src_operand.operand = *(sint8_t *)instr_ptr;  // sign extend.
 
+           instr->src_operand.read = 1;
+           instr->dst_operand.write = 1;
+
            instr_ptr += 1;
 
            instr->num_operands = 2;
@@ -293,10 +307,15 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            instr->src_operand.size = operand_width;
            instr->src_operand.operand = get_addr_linear(core,  MASK(core->vm_regs.rsi, addr_width), &(core->segments.ds));
 
+
            instr->dst_operand.type = MEM_OPERAND;
            instr->dst_operand.size = operand_width;
            instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
 
+
+           instr->src_operand.read = 1;
+           instr->dst_operand.write = 1;
+
            instr->num_operands = 2;
 
            break;
@@ -304,9 +323,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            case MOV_2CR: {
                uint8_t reg_code = 0;
 
-               instr->src_operand.size = operand_width;
-
-               ret = decode_rm_operand(core, instr_ptr, instr, &(instr->src_operand),
+               ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->src_operand),
                                        &reg_code);
 
                if (ret == -1) {
@@ -320,17 +337,19 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
                instr->dst_operand.size = operand_width;
                decode_cr(core, reg_code, &(instr->dst_operand));
 
+               instr->src_operand.read = 1;
+               instr->dst_operand.write = 1;
+
                instr->num_operands = 2;
                break;
            }
            case MOV_CR2: {
                uint8_t reg_code = 0;
 
-               instr->dst_operand.size = operand_width;
-
-               ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand),
+               ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand),
                                        &reg_code);
 
+
                if (ret == -1) {
                    PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));
                    return -1;
@@ -342,6 +361,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
                instr->src_operand.size = operand_width;
                decode_cr(core, reg_code, &(instr->src_operand));
 
+               instr->src_operand.read = 1;
+               instr->dst_operand.write = 1;
+
                instr->num_operands = 2;
                break;
            }
@@ -363,6 +385,9 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
                instr->dst_operand.size = operand_width;
                instr->dst_operand.operand = get_addr_linear(core, MASK(core->vm_regs.rdi, addr_width), &(core->segments.es));
 
+               instr->src_operand.read = 1;
+               instr->dst_operand.write = 1;
+
                instr->num_operands = 2;
 
                break;
@@ -370,11 +395,7 @@ static int parse_operands(struct guest_info * core, uint8_t * instr_ptr,
            case INVLPG: {
                uint8_t reg_code = 0;
 
-               // We use the dst operand here to maintain bug-for-bug compatibility with XED
-
-               instr->dst_operand.size = operand_width;
-
-               ret = decode_rm_operand(core, instr_ptr, instr, &(instr->dst_operand), &reg_code);
+               ret = decode_rm_operand(core, instr_ptr, form, instr, &(instr->dst_operand), &reg_code);
 
                if (ret == -1) {
                    PrintError("Error decoding operand for (%s)\n", op_form_to_str(form));