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.


Cleanup based on cppcheck pass (Core)
[palacios.git] / palacios / src / palacios / vmm_ctrl_regs.c
index f09bfb9..add91ff 100644 (file)
@@ -49,6 +49,11 @@ int v3_handle_cr0_write(struct guest_info * info) {
     } else { 
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
+
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
     
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
         PrintError(info->vm_info, info, "Could not decode instruction\n");
@@ -229,7 +234,11 @@ int v3_handle_cr0_read(struct guest_info * info) {
     } else { 
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
-    
+
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
     
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
@@ -304,6 +313,11 @@ int v3_handle_cr3_write(struct guest_info * info) {
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
     
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
        return -1;
@@ -381,6 +395,11 @@ int v3_handle_cr3_read(struct guest_info * info) {
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
     
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
        return -1;
@@ -428,13 +447,66 @@ int v3_handle_cr3_read(struct guest_info * info) {
 }
 
 
-// We don't need to virtualize CR4, all we need is to detect the activation of PAE
+//return guest cr4 - shadow PAE is always on
 int v3_handle_cr4_read(struct guest_info * info) {
-    PrintError(info->vm_info, info, "CR4 Read not handled\n");
-    // Do nothing...
+    uchar_t instr[15];
+    int ret;
+    struct x86_instr dec_instr;
+    
+    if (info->mem_mode == PHYSICAL_MEM) { 
+       ret = v3_read_gpa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    } else { 
+       ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
+    }
+    
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
+    if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
+       PrintError(info->vm_info, info, "Could not decode instruction\n");
+       return -1;
+    }
+    if (dec_instr.op_type != V3_OP_MOVCR2) {
+       PrintError(info->vm_info, info, "Invalid opcode in read CR4\n");
+       return -1;
+    }
+       
+       if (info->shdw_pg_mode == SHADOW_PAGING) {
+           
+           if ((v3_get_vm_cpu_mode(info) == LONG) || 
+               (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
+               struct cr4_64 * dst_reg = (struct cr4_64 *)(dec_instr.dst_operand.operand);
+               struct cr4_64 * guest_cr4 = (struct cr4_64 *)&(info->ctrl_regs.cr4);
+               *dst_reg = *guest_cr4;
+           } 
+           else {
+               struct cr4_32 * dst_reg = (struct cr4_32 *)(dec_instr.dst_operand.operand);
+               struct cr4_32 * guest_cr4 = (struct cr4_32 *)&(info->shdw_pg_state.guest_cr4);
+               *dst_reg = *guest_cr4;
+           }
+           
+       } else if (info->shdw_pg_mode == NESTED_PAGING) {
+           
+           
+           if ((v3_get_vm_cpu_mode(info) == LONG) || 
+               (v3_get_vm_cpu_mode(info) == LONG_32_COMPAT)) {
+               struct cr4_64 * dst_reg = (struct cr4_64 *)(dec_instr.dst_operand.operand);
+               struct cr4_64 * guest_cr4 = (struct cr4_64 *)&(info->ctrl_regs.cr4);
+               *dst_reg = *guest_cr4;
+           } else {
+               struct cr4_32 * dst_reg = (struct cr4_32 *)(dec_instr.dst_operand.operand);
+               struct cr4_32 * guest_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
+               *dst_reg = *guest_cr4;
+           }
+       }
+       
+       info->rip += dec_instr.instr_length;
     return 0;
 }
 
+
 int v3_handle_cr4_write(struct guest_info * info) {
     uchar_t instr[15];
     int ret;
@@ -448,6 +520,12 @@ int v3_handle_cr4_write(struct guest_info * info) {
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
     
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
+
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
        return -1;
@@ -463,7 +541,7 @@ int v3_handle_cr4_write(struct guest_info * info) {
 
     if (v3_get_vm_mem_mode(info) == VIRTUAL_MEM) { 
        struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
-       struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
+       struct cr4_32 * cr4 = (struct cr4_32 *)&(info->shdw_pg_state.guest_cr4);
        
        // if pse, pge, or pae have changed while PG (in any mode) is on
        // the side effect is a TLB flush, which means we need to
@@ -483,15 +561,15 @@ int v3_handle_cr4_write(struct guest_info * info) {
 
     if ((cpu_mode == PROTECTED) || (cpu_mode == PROTECTED_PAE)) {
        struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
-       struct cr4_32 * cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
-       
+       struct cr4_32 * shadow_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
+       struct cr4_32 * guest_cr4 = (struct cr4_32 *)&(info->shdw_pg_state.guest_cr4);
        PrintDebug(info->vm_info, info, "OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
-       PrintDebug(info->vm_info, info, "Old CR4=%x\n", *(uint_t *)cr4);
+       PrintDebug(info->vm_info, info, "Old guest CR4=%x\n", *(uint_t *)guest_cr4);
        
        if ((info->shdw_pg_mode == SHADOW_PAGING)) { 
            if (v3_get_vm_mem_mode(info) == PHYSICAL_MEM) {
                
-               if ((cr4->pae == 0) && (new_cr4->pae == 1)) {
+               if ((guest_cr4->pae == 0) && (new_cr4->pae == 1)) {
                    PrintDebug(info->vm_info, info, "Creating PAE passthrough tables\n");
                    
                    // create 32 bit PAE direct map page table
@@ -503,7 +581,7 @@ int v3_handle_cr4_write(struct guest_info * info) {
                    // reset cr3 to new page tables
                    info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
                    
-               } else if ((cr4->pae == 1) && (new_cr4->pae == 0)) {
+               } else if ((guest_cr4->pae == 1) && (new_cr4->pae == 0)) {
                    // Create passthrough standard 32bit pagetables
                    PrintError(info->vm_info, info, "Switching From PAE to Protected mode not supported\n");
                    return -1;
@@ -511,8 +589,10 @@ int v3_handle_cr4_write(struct guest_info * info) {
            }
        }
        
-       *cr4 = *new_cr4;
-       PrintDebug(info->vm_info, info, "New CR4=%x\n", *(uint_t *)cr4);
+       *guest_cr4 = *new_cr4;
+       *shadow_cr4 = *guest_cr4;
+       shadow_cr4->pae = 1;   // always on for the shadow pager
+       PrintDebug(info->vm_info, info, "New guest CR4=%x and shadow CR4=%x\n", *(uint_t *)guest_cr4,*(uint_t*)shadow_cr4);
        
     } else if ((cpu_mode == LONG) || (cpu_mode == LONG_32_COMPAT)) {
        struct cr4_64 * new_cr4 = (struct cr4_64 *)(dec_instr.src_operand.operand);
@@ -589,6 +669,11 @@ int v3_handle_cr8_write(struct guest_info * info) {
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
     
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
        return -1;
@@ -631,6 +716,11 @@ int v3_handle_cr8_read(struct guest_info * info) {
        ret = v3_read_gva_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
     }
     
+    if (ret!=15) { 
+       PrintError(info->vm_info, info, "Could not read instruction\n");
+       return -1;
+    }
+    
     if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
        PrintError(info->vm_info, info, "Could not decode instruction\n");
        return -1;