X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_ctrl_regs.c;h=b3d3356a3cc60126543813962b80fa45835b6410;hb=62406cf6b87a27a62921ce09a0aa44780ea25c06;hp=e2ab2bc89c6d295f483e2c6c9b2aaa64eb4c7b90;hpb=03a41b18bdb6ce4bf666f18acdaf302e2360efdc;p=palacios.git diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index e2ab2bc..b3d3356 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -96,6 +96,10 @@ int v3_handle_cr0_write(struct guest_info * info) { if (info->cpu_mode == LONG) { // 64 bit registers + // Set efer.lma = 1 + + PrintError("Long mode currently not handled\n"); + return -1; } else { // 32 bit registers struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0); @@ -270,14 +274,12 @@ int v3_handle_cr3_write(struct guest_info * info) { } else if (cached == 0) { addr_t shadow_pt; - if( info->mem_mode == VIRTUAL_MEM ) - { - PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 ); - - delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); + if(info->mem_mode == VIRTUAL_MEM) { + PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 ); + delete_page_tables_32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); } - shadow_pt = v3_create_new_shadow_pt32(); + shadow_pt = v3_create_new_shadow_pt(); shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt)); PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr ); @@ -361,3 +363,127 @@ int v3_handle_cr3_read(struct guest_info * info) { return 0; } + +int v3_handle_cr4_read(struct guest_info * info) { + PrintError("CR4 Read not handled\n"); + return -1; +} + +int v3_handle_cr4_write(struct guest_info * info) { + uchar_t instr[15]; + int ret; + struct x86_instr dec_instr; + + if (info->mem_mode == PHYSICAL_MEM) { + ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } else { + ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + } + + if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) { + PrintError("Could not decode instruction\n"); + return -1; + } + + if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) { + PrintError("Invalid opcode in write to CR4\n"); + return -1; + } + + if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PAE)) { + struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand); + struct cr4_32 * old_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4); + + PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size); + PrintDebug("Old CR4=%x\n", *(uint_t *)old_cr4); + + + + + if ((info->shdw_pg_mode == SHADOW_PAGING) && + (v3_get_mem_mode(info) == PHYSICAL_MEM)) { + + if ((old_cr4->pae == 0) && (new_cr4->pae == 1)) { + PrintDebug("Creating PAE passthrough tables\n"); + + // Delete the old 32 bit direct map page tables + delete_page_tables_32((pde32_t *)V3_VAddr((void *)(info->direct_map_pt))); + + // create 32 bit PAE direct map page table + info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32PAE(info)); + + // reset cr3 to new page tables + info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt); + + } else if ((old_cr4->pae == 1) && (new_cr4->pae == 0)) { + // Create passthrough standard 32bit pagetables + return -1; + } + } + + *old_cr4 = *new_cr4; + PrintDebug("New CR4=%x\n", *(uint_t *)old_cr4); + + } else { + return -1; + } + + info->rip += dec_instr.instr_length; + return 0; +} + + +int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) { + PrintError("EFER Read not handled\n"); + return -1; +} + + +int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) { + struct guest_info * info = (struct guest_info *)(priv_data); + struct efer_64 * new_efer = (struct efer_64 *)&(src.value); + struct efer_64 * old_efer = (struct efer_64 *)&(info->ctrl_regs.efer); + + PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(old_efer)); + + if ((info->shdw_pg_mode == SHADOW_PAGING) && + (v3_get_mem_mode(info) == PHYSICAL_MEM)) { + + if ((old_efer->lme == 0) && (new_efer->lme == 1)) { + PrintDebug("Transition to longmode\n"); + PrintDebug("Creating Passthrough 64 bit page tables\n"); + + // Delete the old 32 bit direct map page tables + /* + * JRL BUG? + * Will these page tables always be in PAE format?? + */ + PrintDebug("Deleting old PAE Page tables\n"); + PrintError("JRL BUG?: Will the old page tables always be in PAE format??\n"); + delete_page_tables_32PAE((pdpe32pae_t *)V3_VAddr((void *)(info->direct_map_pt))); + + // create 64 bit direct map page table + info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(info)); + + // reset cr3 to new page tables + info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt); + + + // Does this mean we will have to fully virtualize a shadow EFER?? + new_efer->lma = 1; + + } else if ((old_efer->lme == 1) && (new_efer->lme == 0)) { + // transition out of long mode + return -1; + } + + *old_efer = *new_efer; + PrintDebug("New EFER=%p\n", (void *)*(addr_t *)(old_efer)); + } else { + return -1; + } + + info->rip += 2; // WRMSR/RDMSR are two byte operands + + return 0; +}