/* handle int15 from real mode code * we use CS:IP for vmcall instruction to get indication that there is int15 * check for E820 function, if true, then handle it * no other int15 function should come here */ boolean_t handle_int15_vmcall(guest_cpu_handle_t gcpu) { uint16_t selector = 0; uint64_t base = 0; uint32_t limit = 0; uint32_t attr = 0; uint32_t expected_lnr_addr; uint32_t vmcall_lnr_addr; volatile uint64_t r_rax = 0, r_rdx = 0, r_rip = 0; if (!(0x1 & gcpu_get_guest_visible_control_reg(gcpu, IA32_CTRL_CR0))) { /* PE = 0? then real mode * need to get CS:IP to make sure that this VMCALL from INT15 handler */ gcpu_get_segment_reg(gcpu, IA32_SEG_CS, &selector, &base, &limit, &attr); r_rip = gcpu_get_gp_reg(gcpu, IA32_REG_RIP); expected_lnr_addr = SEGMENT_OFFSET_TO_LINEAR( g_int15_trapped_page >> 16, g_int15_trapped_page + VMCALL_OFFSET); vmcall_lnr_addr = SEGMENT_OFFSET_TO_LINEAR((uint32_t)selector, (uint32_t)r_rip); /* check to see if the CS:IP is same as expected for VMCALL in INT15 * handler */ if (expected_lnr_addr == vmcall_lnr_addr) { r_rax = gcpu_get_gp_reg(gcpu, IA32_REG_RAX); r_rdx = gcpu_get_gp_reg(gcpu, IA32_REG_RDX); if ((0xE820 == r_rax) && (SMAP == r_rdx)) { if (g_emap == NULL) { g_emap = mon_malloc(sizeof( e820_map_state_t)); MON_ASSERT(g_emap != NULL); mon_memset(g_emap, 0, sizeof(e820_map_state_t)); } e820_save_guest_state(gcpu, g_emap); g_emap->guest_handle = mon_gcpu_guest_handle( gcpu); e820_int15_handler(g_emap); e820_restore_guest_state(gcpu, g_emap); gcpu_skip_guest_instruction(gcpu); return TRUE; } else { MON_LOG(mask_anonymous, level_error, "INT15 wasn't handled for function 0x%x\n", r_rax); MON_DEADLOOP(); /* Should not get here */ return FALSE; } } }
static void force_ring3_ss(guest_cpu_handle_t gcpu) { seg_reg_t ss; cr0_t cr0; eflags_t flags; cr0.value = (uint32_t)gcpu_get_guest_visible_control_reg(gcpu, IA32_CTRL_CR0); flags.value = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS); if ((cr0.bits.pe == 0) || (flags.bits.v86_mode == 1)) { return; } gcpu_get_segment_reg(gcpu, IA32_SEG_TR, (uint16_t *)&(ss.selector), (uint64_t *)&(ss.base), (uint32_t *)&(ss.limit), (uint32_t *)&(ss.ar)); ss.ar.bits.dpl = 3; gcpu_set_segment_reg(gcpu, IA32_SEG_SS, ss.selector, ss.base, ss.limit, ss.ar.value); return; }
void vmm_deadloop_dump(UINT32 file_code, UINT32 line_num) { #define DEFAULT_VIEW_HANDLE 0 GUEST_CPU_HANDLE gcpu; EM64T_RFLAGS rflags; IA32_VMX_VMCS_GUEST_INTERRUPTIBILITY interruptibility; gcpu = scheduler_current_gcpu(); if(!gcpu) VMM_UP_BREAKPOINT(); report_uvmm_event(UVMM_EVENT_VMM_ASSERT, (VMM_IDENTIFICATION_DATA)gcpu, (const GUEST_VCPU*)guest_vcpu(gcpu), NULL); // send debug info to serial port and guest buffer vmm_deadloop_internal(file_code, line_num, gcpu); // clear interrupt flag rflags.Uint64 = gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS); rflags.Bits.IFL = 0; gcpu_set_gp_reg(gcpu, IA32_REG_RFLAGS, rflags.Uint64); interruptibility.Uint32 = gcpu_get_interruptibility_state(gcpu); interruptibility.Bits.BlockNextInstruction = 0; gcpu_set_interruptibility_state(gcpu, interruptibility.Uint32); // generate BSOD gcpu_inject_gp0(gcpu); gcpu_resume(gcpu); }
/* * Copy guest status from VMCS to tss buffer. */ static void copy_vmcs_to_tss32(guest_cpu_handle_t gcpu, tss32_t *tss) { vmcs_object_t *vmcs = mon_gcpu_get_vmcs(gcpu); tss->eip = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RIP); tss->eflags = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS); tss->eax = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RAX); tss->ecx = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RCX); tss->edx = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RDX); tss->ebx = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RBX); tss->esp = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RSP); tss->ebp = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RBP); tss->esi = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RSI); tss->edi = (uint32_t)gcpu_get_gp_reg(gcpu, IA32_REG_RDI); tss->es = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_ES_SELECTOR); tss->cs = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_CS_SELECTOR); tss->ss = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_SS_SELECTOR); tss->ds = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_DS_SELECTOR); tss->fs = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_FS_SELECTOR); tss->gs = (uint32_t)mon_vmcs_read(vmcs, VMCS_GUEST_GS_SELECTOR); }
void print_guest_gprs(GUEST_CPU_HANDLE gcpu) { VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RCX = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RCX)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RDX = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RDX)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RBX = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RBX)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RBP = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RBP)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RSI = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RSI)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_RDI = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_RDI)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R8 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R8)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R9 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R9)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R10 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R10)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R11 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R11)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R12 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R12)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R13 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R13)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R14 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R14)); VMM_LOG(mask_anonymous, level_trace,"IA32_REG_R15 = %08X\n", gcpu_get_gp_reg(gcpu, IA32_REG_R15)); }