From: Jack Lange Date: Mon, 14 Jul 2008 22:53:03 +0000 (+0000) Subject: ugg X-Git-Tag: reaches-user-mode-on-qemu-and-both-amd-boxes-nested-paging-faults~4 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=526ffdd06c1afb982d0d9831b99f337b6a094960 ugg --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 6eb1cc9..b295bfc 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -80,7 +80,7 @@ struct vm_ctrl_ops { typedef enum {SHADOW_PAGING, NESTED_PAGING} vmm_paging_mode_t; -typedef enum {REAL, PROTECTED, PROTECTED_PAE, LONG} vm_cpu_mode_t; +typedef enum {REAL, /*UNREAL,*/ PROTECTED, PROTECTED_PAE, LONG} vm_cpu_mode_t; typedef enum {PHYSICAL_MEM, VIRTUAL_MEM} vm_mem_mode_t; struct guest_info { @@ -94,6 +94,7 @@ struct guest_info { vmm_paging_mode_t shdw_pg_mode; struct shadow_page_state shdw_pg_state; + addr_t direct_map_pt; // nested_paging_t nested_page_state; diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index 130e1ae..9319da8 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -165,8 +165,11 @@ static inline v3_reg_t get_gpr_mask(struct guest_info * info) { static inline addr_t get_addr_linear(struct guest_info * info, addr_t addr, struct v3_segment * seg) { switch (info->cpu_mode) { case REAL: - return addr + (seg->selector << 4); - break; + // It appears that the segment values are computed and cached in the vmcb structure + // We Need to check this for Intel + /* return addr + (seg->selector << 4); + break;*/ + case PROTECTED: return addr + seg->base; break; diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 1bd4241..8c650ff 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -49,14 +49,14 @@ static vmcb_t * Allocate_VMCB() { -static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { +static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); vmcb_saved_state_t * guest_state = GET_VMCB_SAVE_STATE_AREA(vmcb); uint_t i; - guest_state->rsp = vm_info.vm_regs.rsp; - // guest_state->rip = vm_info.rip; + guest_state->rsp = vm_info->vm_regs.rsp; + // guest_state->rip = vm_info->rip; guest_state->rip = 0xfff0; guest_state->cpl = 0; @@ -85,7 +85,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { ctrl_area->exceptions.of = 1; ctrl_area->exceptions.nmi = 1; - vm_info.vm_regs.rdx = 0x00000f00; + vm_info->vm_regs.rdx = 0x00000f00; guest_state->cr0 = 0x60000010; @@ -122,7 +122,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { guest_state->dr6 = 0x00000000ffff0ff0LL; guest_state->dr7 = 0x0000000000000400LL; - if (vm_info.io_map.num_ports > 0) { + if (vm_info->io_map.num_ports > 0) { vmm_io_hook_t * iter; addr_t io_port_bitmap; @@ -133,7 +133,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { //PrintDebug("Setting up IO Map at 0x%x\n", io_port_bitmap); - FOREACH_IO_HOOK(vm_info.io_map, iter) { + FOREACH_IO_HOOK(vm_info->io_map, iter) { ushort_t port = iter->port; uchar_t * bitmap = (uchar_t *)io_port_bitmap; @@ -155,15 +155,16 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { ctrl_area->instrs.INTR = 1; - if (vm_info.shdw_pg_mode == SHADOW_PAGING) { + if (vm_info->shdw_pg_mode == SHADOW_PAGING) { PrintDebug("Creating initial shadow page table\n"); - vm_info.shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); - vm_info.shdw_pg_state.guest_cr0 = 0x0000000000000010LL; + vm_info->direct_map_pt = (addr_t)create_passthrough_pde32_pts(vm_info); + vm_info->shdw_pg_state.shadow_cr3 |= (vm_info->direct_map_pt & ~0xfff); + vm_info->shdw_pg_state.guest_cr0 = 0x0000000000000010LL; PrintDebug("Created\n"); - guest_state->cr3 = vm_info.shdw_pg_state.shadow_cr3; + guest_state->cr3 = vm_info->shdw_pg_state.shadow_cr3; - //PrintDebugPageTables((pde32_t*)(vm_info.shdw_pg_state.shadow_cr3.e_reg.low)); + //PrintDebugPageTables((pde32_t*)(vm_info->shdw_pg_state.shadow_cr3.e_reg.low)); ctrl_area->cr_reads.cr3 = 1; ctrl_area->cr_writes.cr3 = 1; @@ -182,7 +183,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { guest_state->cr0 |= 0x80000000; - } else if (vm_info.shdw_pg_mode == NESTED_PAGING) { + } else if (vm_info->shdw_pg_mode == NESTED_PAGING) { // Flush the TLB on entries/exits ctrl_area->TLB_CONTROL = 1; @@ -192,7 +193,8 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info vm_info) { PrintDebug("NP_Enable at 0x%x\n", &(ctrl_area->NP_ENABLE)); // Set the Nested Page Table pointer - ctrl_area->N_CR3 = ((addr_t)create_passthrough_pde32_pts(&vm_info) & ~0xfff); + vm_info->direct_map_pt = ((addr_t)create_passthrough_pde32_pts(vm_info) & ~0xfff); + ctrl_area->N_CR3 = vm_info->direct_map_pt; // ctrl_area->N_CR3 = Get_CR3(); // guest_state->cr3 |= (Get_CR3() & 0xfffff000); @@ -226,7 +228,7 @@ static int init_svm_guest(struct guest_info *info) { PrintDebug("Initializing VMCB (addr=%x)\n", info->vmm_data); - Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), *info); + Init_VMCB_BIOS((vmcb_t*)(info->vmm_data), info); // info->rip = 0; diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index cc42089..a059573 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -29,6 +29,8 @@ int handle_cr0_write(struct guest_info * info) { PrintDebug("Real Mode write to CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs))); + PrintV3Segments(&(info->segments)); + // The real rip address is actually a combination of the rip + CS base ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); if (ret != 15) { @@ -38,6 +40,19 @@ int handle_cr0_write(struct guest_info * info) { } while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } index++; } @@ -72,7 +87,7 @@ int handle_cr0_write(struct guest_info * info) { new_cr0 = (struct cr0_real *)host_addr; } else { - PrintDebug("Memory operand in real mode write to CR0 is UNIMPLEMENTED\n"); + // error... don't know what to do return -1; } @@ -83,7 +98,7 @@ int handle_cr0_write(struct guest_info * info) { info->cpu_mode = REAL; } - new_cr0_val = *(char*)(new_cr0) & 0x0f; + new_cr0_val = (*(char*)(new_cr0)) & 0x0f; if (info->shdw_pg_mode == SHADOW_PAGING) { @@ -154,12 +169,22 @@ int handle_cr0_write(struct guest_info * info) { } - if (new_cr0->pg == 1) { + + if ((new_cr0->pg == 1) && (new_cr0->pe == 1)) { PrintDebug("Paging is already turned on in switch to protected mode in CR0 write\n"); + // Actually This appears to be Ok. + // Why shouldn't windows be allowed to switch to real mode whenever it wants to modify its page tables? + + info->mem_mode = VIRTUAL_MEM; + // GPF the guest?? + // return -1; + } else if ((new_cr0->pg == 1) && (new_cr0->pe == 0)) { + PrintDebug("Will the madness Never End??\n"); return -1; } + if (info->shdw_pg_mode == SHADOW_PAGING) { struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); @@ -172,6 +197,12 @@ int handle_cr0_write(struct guest_info * info) { *shadow_cr0 = *new_cr0; shadow_cr0->et = 1; + // Setup the page tables...??? + if (info->mem_mode == VIRTUAL_MEM) { + // If we aren't in paged mode then we have to preserve the identity mapped CR3 + info->ctrl_regs.cr3 = *(addr_t*)&(info->shdw_pg_state.shadow_cr3); + } + PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0); } else { PrintDebug("Old CR0=%x\n", *real_cr0); @@ -218,10 +249,30 @@ int handle_cr0_write(struct guest_info * info) { return -1; } + while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } index++; } + /* + while (is_prefix_byte(instr[index])) { + index++; + } + */ + struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0); struct cr0_32 * real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0); @@ -289,8 +340,7 @@ int handle_cr0_write(struct guest_info * info) { //info->shdw_pg_state.shadow_cr3 |= ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff); //info->ctrl_regs.cr3 = info->shdw_pg_state.shadow_cr3; - info->ctrl_regs.cr3 = ((addr_t)create_passthrough_pde32_pts(info) & ~0xfff); - + info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt); *shadow_cr0 = *new_cr0; *real_cr0 = *new_cr0; @@ -298,6 +348,8 @@ int handle_cr0_write(struct guest_info * info) { shadow_cr0->et = 1; real_cr0->et = 1; + PrintV3CtrlRegs(&(info->ctrl_regs)); + } @@ -306,6 +358,83 @@ int handle_cr0_write(struct guest_info * info) { } info->rip += index; + } else if ((instr[index] == cr_access_byte) && + (instr[index + 1] == lmsw_byte) && + (MODRM_REG(instr[index + 2]) == lmsw_reg_byte)) { + addr_t first_operand; + addr_t second_operand; + struct cr0_real *real_cr0; + struct cr0_real *new_cr0; + operand_type_t addr_type; + char new_cr0_val = 0; + + index += 2; + + real_cr0 = (struct cr0_real*)&(info->ctrl_regs.cr0); + + addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG16); + + if (addr_type == REG_OPERAND) { + new_cr0 = (struct cr0_real *)first_operand; + } else if (addr_type == MEM_OPERAND) { + addr_t host_addr; + // check segment descriptors.... + + /* TODO, TODO, TODO: Lookup segment overrides */ + struct v3_segment *lmsw_segment = &(info->segments.ds); + + if (info->mem_mode == PHYSICAL_MEM) { + if (guest_pa_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) { + return -1; + } + } else { + if (guest_va_to_host_va(info, get_addr_linear(info, first_operand, lmsw_segment), &host_addr) == -1) { + return -1; + } + } + + new_cr0 = (struct cr0_real *)host_addr; + } else { + return -1; + } + + + if (new_cr0->pe == 0) { + // According to the intel manual this it is illegal to use + // lmsw to turn _off_ Protected mode + PrintDebug("Cannot switch to real mode with LMSW, unclear what to do\n"); + return -1; + } + + new_cr0_val = (*(char *)(new_cr0)) & 0x0f; + + + if (info->shdw_pg_mode == SHADOW_PAGING) { + struct cr0_real * shadow_cr0 = (struct cr0_real*)&(info->shdw_pg_state.guest_cr0); + + PrintDebug("Old CR0=%x, Old Shadow CR0=%x\n", *real_cr0, *shadow_cr0); + /* struct cr0_real is only 4 bits wide, + * so we can overwrite the real_cr0 without worrying about the shadow fields + */ + *(char*)real_cr0 &= 0xf0; + *(char*)real_cr0 |= new_cr0_val; + + *(char*)shadow_cr0 &= 0xf0; + *(char*)shadow_cr0 |= new_cr0_val; + + + PrintDebug("New CR0=%x, New Shadow CR0=%x\n", *real_cr0, *shadow_cr0); + } else { + PrintDebug("Old CR0=%x\n", *real_cr0); + // for now we just pass through.... + *(char*)real_cr0 &= 0xf0; + *(char*)real_cr0 |= new_cr0_val; + + PrintDebug("New CR0=%x\n", *real_cr0); + } + + info->rip += index; + } else if ((instr[index] == 0x0f) && (instr[index + 1] == 0x06)) { @@ -359,6 +488,7 @@ int handle_cr0_read(struct guest_info * info) { int ret; PrintDebug("Real Mode read from CR0 at linear guest pa 0x%x\n",get_addr_linear(info,info->rip,&(info->segments.cs))); + PrintV3Segments(&(info->segments)); // The real rip address is actually a combination of the rip + CS base ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); @@ -370,9 +500,28 @@ int handle_cr0_read(struct guest_info * info) { while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } index++; } + /* + while (is_prefix_byte(instr[index])) { + index++; + } + */ + if ((instr[index] == cr_access_byte) && (instr[index + 1] == smsw_byte) && (MODRM_REG(instr[index + 2]) == smsw_reg_byte)) { @@ -478,6 +627,10 @@ int handle_cr0_read(struct guest_info * info) { ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); } + + PrintDebug("Instr (15 bytes) at %x:\n", instr); + PrintTraceMemDump((char*)instr, 15); + if (ret != 15) { // I think we should inject a GPF into the guest PrintDebug("Could not read Protected %s mode instruction (ret=%d)\n", @@ -485,11 +638,31 @@ int handle_cr0_read(struct guest_info * info) { return -1; } + while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } index++; } + /* + while (is_prefix_byte(instr[index])) { + index++; + } + */ + if ((instr[index] == cr_access_byte) && (instr[index+1] == mov_from_cr_byte)) { @@ -561,7 +734,124 @@ int handle_cr0_read(struct guest_info * info) { int handle_cr3_write(struct guest_info * info) { - if (info->cpu_mode == PROTECTED) { + if (info->cpu_mode == REAL) { + // WHAT THE HELL DOES THIS EVEN MEAN????? + + int index = 0; + int ret; + char instr[15]; + + PrintDebug("Real Mode Write to CR3??? What the fuck???\n"); + // We need to read the instruction, which is at CS:IP, but that + // linear address is guest physical without PG and guest virtual with PG + + ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr); + + if (ret != 15) { + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } + index++; + } + + + if ((instr[index] == cr_access_byte) && + (instr[index + 1] == mov_to_cr_byte)) { + + addr_t first_operand; + addr_t second_operand; + struct cr3_32 * new_cr3; + // struct cr3_32 * real_cr3; + operand_type_t addr_type; + + index += 2; + + addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32); + + if (addr_type != REG_OPERAND) { + /* Mov to CR3 can only be a 32 bit register */ + return -1; + } + + new_cr3 = (struct cr3_32 *)first_operand; + + if (info->shdw_pg_mode == SHADOW_PAGING) { + addr_t shadow_pt; + struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3); + struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); + + /* + + if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) { + PrintDebug("Shadow Page Table\n"); + PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); + } + */ + + /* Delete the current Page Tables */ + delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); + + PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n", + *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3); + + + *guest_cr3 = *new_cr3; + + + + // Something like this + shadow_pt = create_new_shadow_pt32(info); + //shadow_pt = setup_shadow_pt32(info, CR3_TO_PDE32(*(addr_t *)new_cr3)); + + /* Copy Various flags */ + *shadow_cr3 = *new_cr3; + + /* + { + addr_t tmp_addr; + guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr); + PrintDebug("Guest PD\n"); + PrintPD32((pde32_t *)tmp_addr); + + } + */ + + + shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt); + + PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n", + *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3); + + + + + } + info->rip += index; + + } else { + PrintDebug("Unknown Instruction\n"); + SerialMemDump(instr,15); + return -1; + } + + + + } else if (info->cpu_mode == PROTECTED) { int index = 0; int ret; char instr[15]; @@ -587,10 +877,29 @@ int handle_cr3_write(struct guest_info * info) { PrintDebug("Could not read instruction (ret=%d)\n", ret); return -1; } - + while (is_prefix_byte(instr[index])) { - index++; + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } + index++; } + + /* + while (is_prefix_byte(instr[index])) { + index++; + } + */ if ((instr[index] == cr_access_byte) && (instr[index + 1] == mov_to_cr_byte)) { @@ -618,10 +927,12 @@ int handle_cr3_write(struct guest_info * info) { struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); + /* if (CR3_TO_PDE32(*(uint_t*)shadow_cr3) != 0) { PrintDebug("Shadow Page Table\n"); PrintDebugPageTables((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); } + */ /* Delete the current Page Tables */ delete_page_tables_pde32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3)); @@ -641,6 +952,7 @@ int handle_cr3_write(struct guest_info * info) { /* Copy Various flags */ *shadow_cr3 = *new_cr3; + /* { addr_t tmp_addr; guest_pa_to_host_va(info, ((*(uint_t*)guest_cr3) & 0xfffff000), &tmp_addr); @@ -648,7 +960,7 @@ int handle_cr3_write(struct guest_info * info) { PrintPD32((pde32_t *)tmp_addr); } - + */ shadow_cr3->pdt_base_addr = PD32_BASE_ADDR(shadow_pt); @@ -685,34 +997,76 @@ int handle_cr3_write(struct guest_info * info) { int handle_cr3_read(struct guest_info * info) { if (info->cpu_mode == REAL) { - // what does this mean??? - - /* - - addr_t host_addr; + char instr[15]; + int ret; + int index = 0; addr_t linear_addr = 0; - - linear_addr = get_addr_linear(info, info->rip, &(info->segments.cs)); PrintDebug("RIP Linear: %x\n", linear_addr); PrintV3Segments(&(info->segments)); - - if (info->mem_mode == PHYSICAL_MEM) { - guest_pa_to_host_pa(info, linear_addr, &host_addr); - } else if (info->mem_mode == VIRTUAL_MEM) { - guest_va_to_host_pa(info, linear_addr, &host_addr); + ret = read_guest_pa_memory(info, linear_addr, 15, instr); + + if (ret != 15) { + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + while (is_prefix_byte(instr[index])) { + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } + index++; } - pt32_lookup((pde32_t *)CR3_TO_PDE32(info->shdw_pg_state.shadow_cr3), , addr_t * paddr); - */ + if ((instr[index] == cr_access_byte) && + (instr[index + 1] == mov_from_cr_byte)) { + addr_t first_operand; + addr_t second_operand; + struct cr3_32 * virt_cr3; + struct cr3_32 * real_cr3 = (struct cr3_32 *)&(info->ctrl_regs.cr3); + operand_type_t addr_type; + + index += 2; + addr_type = decode_operands16(&(info->vm_regs), instr + index, &index, &first_operand, &second_operand, REG32); - return -1; + if (addr_type != REG_OPERAND) { + /* Mov to CR3 can only be a 32 bit register */ + return -1; + } + + virt_cr3 = (struct cr3_32 *)first_operand; + + if (info->shdw_pg_mode == SHADOW_PAGING) { + *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3); + } else { + *virt_cr3 = *real_cr3; + } + + info->rip += index; + } else { + PrintDebug("Unknown Instruction\n"); + SerialMemDump(instr,15); + return -1; + } + + + return 0; } else if (info->cpu_mode == PROTECTED) { int index = 0; @@ -736,9 +1090,28 @@ int handle_cr3_read(struct guest_info * info) { } while (is_prefix_byte(instr[index])) { - index++; + switch(instr[index]) { + case PREFIX_CS_OVERRIDE: + case PREFIX_SS_OVERRIDE: + case PREFIX_DS_OVERRIDE: + case PREFIX_ES_OVERRIDE: + case PREFIX_FS_OVERRIDE: + case PREFIX_GS_OVERRIDE: + PrintDebug("Segment Override!!\n"); + return -1; + break; + default: + break; + } + index++; } + /* + while (is_prefix_byte(instr[index])) { + index++; + } + */ + if ((instr[index] == cr_access_byte) && (instr[index + 1] == mov_from_cr_byte)) { addr_t first_operand; diff --git a/palacios/src/palacios/vmm_shadow_paging.c b/palacios/src/palacios/vmm_shadow_paging.c index a69900a..abb190b 100644 --- a/palacios/src/palacios/vmm_shadow_paging.c +++ b/palacios/src/palacios/vmm_shadow_paging.c @@ -30,10 +30,8 @@ int handle_shadow_pagefault(struct guest_info * info, addr_t fault_addr, pf_erro break; case PROTECTED_PAE: case LONG: - // currently not handled - return -1; - break; default: + PrintDebug("Unhandled CPU Mode\n"); return -1; } } else { @@ -136,12 +134,14 @@ int handle_shadow_pagefault32(struct guest_info * info, addr_t fault_addr, pf_er PrintDebug("Injecting PDE pf to guest: (guest access error=%d) (pf error code=%d)\n", guest_pde_access, error_code); return 0; - PrintDebug("Guest CR3=%x\n", guest_cr3); - PrintDebug("Guest PD\n"); - PrintPD32(guest_pd); - PrintDebug("Shadow PD\n"); - PrintPD32(shadow_pd); - + + /* + PrintDebug("Guest CR3=%x\n", guest_cr3); + PrintDebug("Guest PD\n"); + PrintPD32(guest_pd); + PrintDebug("Shadow PD\n"); + PrintPD32(shadow_pd); + */ return -1; }