From: Jack Lange Date: Wed, 16 Jul 2008 00:12:16 +0000 (+0000) Subject: some nested paging fixes X-Git-Tag: boots-puppy-iso-to-command-prompt~21 X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=8ee31494ea28d1756689574fb69791746daac3f3 some nested paging fixes --- diff --git a/palacios/include/palacios/svm_handler.h b/palacios/include/palacios/svm_handler.h index 1557ad0..da5967d 100644 --- a/palacios/include/palacios/svm_handler.h +++ b/palacios/include/palacios/svm_handler.h @@ -165,6 +165,8 @@ #define VMEXIT_MWAIT 0x0000008b #define VMEXIT_MWAIT_CONDITIONAL 0x0000008c +#define VMEXIT_NPF 0x00000400 + #define VMEXIT_INVALID_VMCB -1 /******************************************/ diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index b295bfc..bc2c814 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -122,9 +122,9 @@ struct guest_info { }; -void PrintV3Segments(struct v3_segments * segs); -void PrintV3CtrlRegs(struct v3_ctrl_regs * regs); - +void PrintV3Segments(struct guest_info * info); +void PrintV3CtrlRegs(struct guest_info * info); +void PrintV3GPRs(struct guest_info * info); #endif diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index 1d8d23b..55bda95 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -74,7 +74,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { ctrl_area->exceptions.de = 1; ctrl_area->exceptions.df = 1; - ctrl_area->exceptions.pf = 1; + ctrl_area->exceptions.ts = 1; ctrl_area->exceptions.ss = 1; ctrl_area->exceptions.ac = 1; @@ -182,6 +182,8 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) { ctrl_area->instrs.INVLPG = 1; ctrl_area->instrs.INVLPGA = 1; + ctrl_area->exceptions.pf = 1; + /* JRL: This is a performance killer, and a simplistic solution */ /* We need to fix this */ ctrl_area->TLB_CONTROL = 1; @@ -275,7 +277,6 @@ static int start_svm_guest(struct guest_info *info) { rdtscll(info->time_state.cached_host_tsc); guest_ctrl->TSC_OFFSET = info->time_state.guest_tsc - info->time_state.cached_host_tsc; - PrintDebug("Launching\n"); safe_svm_launch((vmcb_t*)(info->vmm_data), &(info->vm_regs)); rdtscll(tmp_tsc); @@ -301,9 +302,9 @@ static int start_svm_guest(struct guest_info *info) { PrintDebug("RIP Linear: %x\n", linear_addr); - PrintV3Segments(&(info->segments)); - PrintV3CtrlRegs(&(info->ctrl_regs)); - + PrintV3Segments(info); + PrintV3CtrlRegs(info); + PrintV3GPRs(info); if (info->mem_mode == PHYSICAL_MEM) { guest_pa_to_host_pa(info, linear_addr, &host_addr); diff --git a/palacios/src/palacios/svm_halt.c b/palacios/src/palacios/svm_halt.c index 299421c..a3749c1 100644 --- a/palacios/src/palacios/svm_halt.c +++ b/palacios/src/palacios/svm_halt.c @@ -12,11 +12,21 @@ int handle_svm_halt(struct guest_info * info) // What we will hackishly do instead is resume on any event // Plus is this totally GeekOS specific + ullong_t yield_start = 0; + ullong_t yield_stop = 0; + uint32_t gap = 0; + PrintDebug("GeekOS Yield\n"); + rdtscll(yield_start); Yield(); + rdtscll(yield_stop); + + + v3_update_time(info, yield_stop - yield_start); + gap = yield_stop - yield_start; - PrintDebug("GeekOS Yield Done\n"); + PrintDebug("GeekOS Yield Done (%d cycles)\n", gap); info->rip+=1; diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 10d3af6..9a994d2 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -41,7 +41,38 @@ int handle_svm_exit(struct guest_info * info) { // Disable printing io exits due to bochs debug messages //if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) { + PrintDebug("SVM Returned: Exit Code: 0x%x \t\t(tsc=%ul)\n",exit_code, (uint_t)info->time_state.guest_tsc); + + if (exit_code < 0x40) { + char instr[32]; + int ret; + // Dump out the instr stream + + //PrintDebug("RIP: %x\n", guest_state->rip); + PrintDebug("RIP Linear: %x\n", get_addr_linear(info, info->rip, &(info->segments.cs))); + + // OK, now we will read the instruction + // The only difference between PROTECTED and PROTECTED_PG is whether we read + // from guest_pa or guest_va + if (info->mem_mode == PHYSICAL_MEM) { + // 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)), 32, instr); + } else { + ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 32, instr); + } + + if (ret != 32) { + // I think we should inject a GPF into the guest + PrintDebug("Could not read instruction (ret=%d)\n", ret); + return -1; + } + + PrintDebug("Instr Stream:\n"); + PrintTraceMemDump(instr, 32); + } + + // } // PrintDebugVMCB((vmcb_t*)(info->vmm_data)); @@ -112,9 +143,14 @@ int handle_svm_exit(struct guest_info * info) { return -1; } } else { + PrintDebug("Page fault in un implemented paging mode\n"); + return -1; } + } else if (exit_code == VMEXIT_NPF) { + PrintDebug("Currently unhandled Nested Page Fault\n"); + return -1; } else if (exit_code == VMEXIT_INVLPG) { if (info->shdw_pg_mode == SHADOW_PAGING) { @@ -280,7 +316,7 @@ int handle_svm_exit(struct guest_info * info) { set_vmcb_segments((vmcb_t*)(info->vmm_data), &(info->segments)); if (exit_code == VMEXIT_INTR) { - PrintDebug("INTR ret IP = %x\n", guest_state->rip); + //PrintDebug("INTR ret IP = %x\n", guest_state->rip); } return 0; diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index b831962..f920d1b 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -1,7 +1,8 @@ #include #include -void PrintV3Segments(struct v3_segments * segs) { +void PrintV3Segments(struct guest_info * info) { + struct v3_segments * segs = &(info->segments); int i = 0; struct v3_segment * seg_ptr; @@ -19,7 +20,8 @@ void PrintV3Segments(struct v3_segments * segs) { } -void PrintV3CtrlRegs(struct v3_ctrl_regs * regs) { +void PrintV3CtrlRegs(struct guest_info * info) { + struct v3_ctrl_regs * regs = &(info->ctrl_regs); int i = 0; v3_reg_t * reg_ptr; char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", NULL}; @@ -32,3 +34,19 @@ void PrintV3CtrlRegs(struct v3_ctrl_regs * regs) { PrintDebug("\t%s=0x%x\n", reg_names[i], reg_ptr[i]); } } + + +void PrintV3GPRs(struct guest_info * info) { + struct v3_gprs * regs = &(info->vm_regs); + int i = 0; + v3_reg_t * reg_ptr; + char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL}; + + reg_ptr= (v3_reg_t *)regs; + + PrintDebug("32 bit GPRs:\n"); + + for (i = 0; reg_names[i] != NULL; i++) { + PrintDebug("\t%s=0x%x\n", reg_names[i], reg_ptr[i]); + } +} diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index 105322e..21c1b54 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -122,73 +122,72 @@ int guest_va_to_guest_pa(struct guest_info * guest_info, addr_t guest_va, addr_t } - if (guest_info->shdw_pg_mode == SHADOW_PAGING) { - // Guest Is in Paged mode - switch (guest_info->cpu_mode) { - case PROTECTED: - { - addr_t tmp_pa = 0; - pde32_t * pde = 0; - addr_t guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3); - - - if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) { - PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde); - return -1; - } - - - switch (pde32_lookup(pde, guest_va, &tmp_pa)) { - case PDE32_ENTRY_NOT_PRESENT: - *guest_pa = 0; - return -1; - case PDE32_ENTRY_LARGE_PAGE: - *guest_pa = tmp_pa; - return 0; - case PDE32_ENTRY_PTE32: - { - pte32_t * pte = 0; - - if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) { - PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa); - return -1; - } - - PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa); - - if (pte32_lookup(pte, guest_va, guest_pa) != 0) { - PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte); - // PrintPT32(PDE32_INDEX(guest_va) << 22, pte); - return -1; - } - - return 0; - } - default: - return -1; - } + // Guest Is in Paged mode + switch (guest_info->cpu_mode) { + case PROTECTED: + { + addr_t tmp_pa = 0; + pde32_t * pde = 0; + addr_t guest_pde = 0; + + if (guest_info->shdw_pg_mode == SHADOW_PAGING) { + guest_pde = CR3_TO_PDE32(guest_info->shdw_pg_state.guest_cr3); + } else if (guest_info->shdw_pg_mode == NESTED_PAGING) { + guest_pde = CR3_TO_PDE32(guest_info->ctrl_regs.cr3); } - case PROTECTED_PAE: - { - // Fill in - } - case LONG: + + if (guest_pa_to_host_va(guest_info, guest_pde, (addr_t *)&pde) == -1) { + PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PDE32 lookup\n", guest_pde); + return -1; + } + + + switch (pde32_lookup(pde, guest_va, &tmp_pa)) { + case PDE32_ENTRY_NOT_PRESENT: + *guest_pa = 0; + return -1; + case PDE32_ENTRY_LARGE_PAGE: + *guest_pa = tmp_pa; + return 0; + case PDE32_ENTRY_PTE32: { - // Fill in + pte32_t * pte = 0; + + + if (guest_pa_to_host_va(guest_info, tmp_pa, (addr_t*)&pte) == -1) { + PrintDebug("In GVA->GPA: Invalid GPA(%x)->HVA PTE32 lookup\n", guest_pa); + return -1; + } + + PrintDebug("PTE host addr=%x, GVA=%x, GPA=%x(should be 0)\n", pte, guest_va, *guest_pa); + + if (pte32_lookup(pte, guest_va, guest_pa) != 0) { + PrintDebug("In GVA->GPA: PTE32 Lookup failure GVA=%x; PTE=%x\n", guest_va, pte); + // PrintPT32(PDE32_INDEX(guest_va) << 22, pte); + return -1; + } + + return 0; } - default: - return -1; + default: + return -1; + } } - } else if (guest_info->shdw_pg_mode == NESTED_PAGING) { - - // Fill in - return -1; - } else { + case PROTECTED_PAE: + { + // Fill in + } + case LONG: + { + // Fill in + } + default: return -1; } - - + + + return 0; } diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index a059573..c02eb5c 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -1,4 +1,4 @@ -#include + #include #include #include #include @@ -29,7 +29,7 @@ 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)); + PrintV3Segments(info); // 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); @@ -333,7 +333,7 @@ int handle_cr0_write(struct guest_info * info) { info->mem_mode = PHYSICAL_MEM; PrintDebug("Entering Real Mode\n"); - PrintV3CtrlRegs(&(info->ctrl_regs)); + PrintV3CtrlRegs(info); // reinstate the identity mapped paged tables // But keep the shadow tables around to handle TLB issues.... UGH... //info->shdw_pg_state.shadow_cr3 &= 0x00000fff; @@ -348,12 +348,19 @@ int handle_cr0_write(struct guest_info * info) { shadow_cr0->et = 1; real_cr0->et = 1; - PrintV3CtrlRegs(&(info->ctrl_regs)); + PrintV3CtrlRegs(info); } } else { + if (new_cr0->pg == 1) { + info->mem_mode = VIRTUAL_MEM; + } else if (new_cr0->pg == 0) { + info->cpu_mode = REAL; + info->mem_mode = PHYSICAL_MEM; + } + *real_cr0 = *new_cr0; } @@ -488,7 +495,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)); + PrintV3Segments(info); // 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); @@ -691,14 +698,13 @@ int handle_cr0_read(struct guest_info * info) { if (info->mem_mode == PHYSICAL_MEM) { virt_cr0->pg = 0; // clear the pg bit because guest doesn't think it's on } - - PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0); - PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0); - } else { *virt_cr0 = *real_cr0; } + + PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0); + PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0); info->rip += index; @@ -1006,7 +1012,7 @@ int handle_cr3_read(struct guest_info * info) { PrintDebug("RIP Linear: %x\n", linear_addr); - PrintV3Segments(&(info->segments)); + PrintV3Segments(info); ret = read_guest_pa_memory(info, linear_addr, 15, instr); @@ -1145,7 +1151,7 @@ int handle_cr3_read(struct guest_info * info) { } } else { PrintDebug("Invalid operating Mode (0x%x), control registers follow\n", info->cpu_mode); - PrintV3CtrlRegs(&(info->ctrl_regs)); + PrintV3CtrlRegs(info); return -1; }