#define VMEXIT_MWAIT 0x0000008b
#define VMEXIT_MWAIT_CONDITIONAL 0x0000008c
+#define VMEXIT_NPF 0x00000400
+
#define VMEXIT_INVALID_VMCB -1
/******************************************/
};
-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
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;
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;
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);
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);
// 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;
// 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));
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) {
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;
#include <palacios/vm_guest.h>
#include <palacios/vmm.h>
-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;
}
-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};
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]);
+ }
+}
}
- 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;
}
-#include <palacios/vmm_mem.h>
+ #include <palacios/vmm_mem.h>
#include <palacios/vmm.h>
#include <palacios/vmcb.h>
#include <palacios/vmm_decoder.h>
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);
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;
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;
}
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);
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;
PrintDebug("RIP Linear: %x\n", linear_addr);
- PrintV3Segments(&(info->segments));
+ PrintV3Segments(info);
ret = read_guest_pa_memory(info, linear_addr, 15, instr);
}
} else {
PrintDebug("Invalid operating Mode (0x%x), control registers follow\n", info->cpu_mode);
- PrintV3CtrlRegs(&(info->ctrl_regs));
+ PrintV3CtrlRegs(info);
return -1;
}