void GetGuestState() { PHYSICAL_ADDRESS HighestAcceptableAddress; HighestAcceptableAddress.QuadPart = 0xFFFFFFFF00000000; g_GuestState.CR0 = __readcr0(); g_GuestState.CR3 = __readcr3(); g_GuestState.CR4 = __readcr4() | CR4_VMXE; g_GuestState.RFLAGS = __readeflags(); g_GuestState.Cs = __readcs(); g_GuestState.Ds = __readds(); g_GuestState.Es = __reades(); g_GuestState.Ss = __readss(); g_GuestState.Fs = __readfs(); g_GuestState.Gs = __readgs(); g_GuestState.Ldtr = __sldt(); g_GuestState.Tr = __str(); __sgdt(&(g_GuestState.Gdtr)); __sidt(&(g_GuestState.Idtr)); g_GuestState.S_CS = __readmsr(IA32_SYSENTER_CS); g_GuestState.SEIP = __readmsr(IA64_SYSENTER_EIP); g_GuestState.SESP = __readmsr(IA32_SYSENTER_ESP); g_GuestState.VMXON = MmAllocateNonCachedMemory(PAGE_SIZE); RtlZeroMemory(g_GuestState.VMXON, PAGE_SIZE); g_GuestState.VMCS = MmAllocateNonCachedMemory(PAGE_SIZE); RtlZeroMemory(g_GuestState.VMCS, PAGE_SIZE); g_GuestState.hvStack = // 分配的是非页面内存, 且保证在物理内存中是连续的, MmFreeContiguousMemory MmAllocateContiguousMemory(PAGE_SIZE * 2, HighestAcceptableAddress); RtlZeroMemory(g_GuestState.hvStack, PAGE_SIZE * 2); }
void save_cpu_state(mon_guest_cpu_startup_state_t *s) { ia32_gdtr_t gdtr; ia32_idtr_t idtr; ia32_selector_t sel; ia32_segment_descriptor_t *desc; s->size_of_this_struct = sizeof(mon_guest_cpu_startup_state_t); s->version_of_this_struct = MON_GUEST_CPU_STARTUP_STATE_VERSION; __readgdtr(&gdtr); __sidt(&idtr); s->control.gdtr.base = (uint64_t)gdtr.base; s->control.gdtr.limit = (uint32_t)gdtr.limit; s->control.idtr.base = (uint64_t)idtr.base; s->control.idtr.limit = (uint32_t)idtr.limit; s->control.cr[IA32_CTRL_CR0] = __readcr0(); s->control.cr[IA32_CTRL_CR2] = __readcr2(); s->control.cr[IA32_CTRL_CR3] = __readcr3(); s->control.cr[IA32_CTRL_CR4] = __readcr4(); s->msr.msr_sysenter_cs = (uint32_t)__readmsr(IA32_MSR_SYSENTER_CS); s->msr.msr_sysenter_eip = __readmsr(IA32_MSR_SYSENTER_EIP); s->msr.msr_sysenter_esp = __readmsr(IA32_MSR_SYSENTER_ESP); s->msr.msr_efer = __readmsr(IA32_MSR_EFER); s->msr.msr_pat = __readmsr(IA32_MSR_PAT); s->msr.msr_debugctl = __readmsr(IA32_MSR_DEBUGCTL); s->msr.pending_exceptions = 0; s->msr.interruptibility_state = 0; s->msr.activity_state = 0; s->msr.smbase = 0; sel.sel16 = __readldtr(); if (sel.bits.index != 0) { return; } s->seg.segment[IA32_SEG_LDTR].attributes = 0x00010000; s->seg.segment[IA32_SEG_TR].attributes = 0x0000808b; s->seg.segment[IA32_SEG_TR].limit = 0xffffffff; save_segment_data((uint16_t)__readcs(), &s->seg.segment[IA32_SEG_CS]); save_segment_data((uint16_t)__readds(), &s->seg.segment[IA32_SEG_DS]); save_segment_data((uint16_t)__reades(), &s->seg.segment[IA32_SEG_ES]); save_segment_data((uint16_t)__readfs(), &s->seg.segment[IA32_SEG_FS]); save_segment_data((uint16_t)__readgs(), &s->seg.segment[IA32_SEG_GS]); save_segment_data((uint16_t)__readss(), &s->seg.segment[IA32_SEG_SS]); return; }
static bool setup_vmcs(struct vcpu *vcpu, uintptr_t sp, uintptr_t ip, uintptr_t stack_base) { struct gdtr gdtr; __sgdt(&gdtr); struct gdtr idtr; __sidt(&idtr); /* Get this CPU's EPT */ struct ept *ept = &vcpu->ept; u64 cr0 = __readcr0(); u64 cr4 = __readcr4(); u64 err = 0; u16 es = __reades(); u16 cs = __readcs(); u16 ss = __readss(); u16 ds = __readds(); u16 fs = __readfs(); u16 gs = __readgs(); u16 ldt = __sldt(); u16 tr = __str(); vcpu->g_idt.base = idtr.base; vcpu->g_idt.limit = idtr.limit; struct kidt_entry64 *current = (struct kidt_entry64 *)idtr.base; struct kidt_entry64 *shadow = (struct kidt_entry64 *)vcpu->idt.base; unsigned count = idtr.limit / sizeof(*shadow); for (unsigned n = 0; n < count; ++n) memcpy(&shadow[n], ¤t[n], sizeof(*shadow)); vcpu_put_idt(vcpu, cs, X86_TRAP_VE, __ept_violation); u8 msr_off = 0; if (__readmsr(MSR_IA32_VMX_BASIC) & VMX_BASIC_TRUE_CTLS) msr_off = 0xC; u64 vm_entry = VM_ENTRY_IA32E_MODE;// | VM_ENTRY_LOAD_IA32_PAT; adjust_ctl_val(MSR_IA32_VMX_ENTRY_CTLS + msr_off, &vm_entry); u64 vm_exit = VM_EXIT_ACK_INTR_ON_EXIT | VM_EXIT_HOST_ADDR_SPACE_SIZE; adjust_ctl_val(MSR_IA32_VMX_EXIT_CTLS + msr_off, &vm_exit); u64 vm_pinctl = 0; adjust_ctl_val(MSR_IA32_VMX_PINBASED_CTLS + msr_off, &vm_pinctl); u64 vm_cpuctl = CPU_BASED_ACTIVATE_SECONDARY_CONTROLS | CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_MOV_DR_EXITING | CPU_BASED_USE_TSC_OFFSETING; adjust_ctl_val(MSR_IA32_VMX_PROCBASED_CTLS + msr_off, &vm_cpuctl); u64 vm_2ndctl = SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_TSC_SCALING | SECONDARY_EXEC_DESC_TABLE_EXITING | SECONDARY_EXEC_XSAVES | SECONDARY_EXEC_RDTSCP | SECONDARY_EXEC_ENABLE_VMFUNC | SECONDARY_EXEC_ENABLE_VE; adjust_ctl_val(MSR_IA32_VMX_PROCBASED_CTLS2, &vm_2ndctl); /* Processor control fields */ err |= __vmx_vmwrite(PIN_BASED_VM_EXEC_CONTROL, vm_pinctl); err |= __vmx_vmwrite(CPU_BASED_VM_EXEC_CONTROL, vm_cpuctl); err |= __vmx_vmwrite(EXCEPTION_BITMAP, __EXCEPTION_BITMAP); err |= __vmx_vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); err |= __vmx_vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); err |= __vmx_vmwrite(CR3_TARGET_COUNT, 0); err |= __vmx_vmwrite(VM_EXIT_CONTROLS, vm_exit); err |= __vmx_vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); err |= __vmx_vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); err |= __vmx_vmwrite(VM_ENTRY_CONTROLS, vm_entry); err |= __vmx_vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); err |= __vmx_vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); err |= __vmx_vmwrite(SECONDARY_VM_EXEC_CONTROL, vm_2ndctl); /* Control Fields */ err |= __vmx_vmwrite(IO_BITMAP_A, 0); err |= __vmx_vmwrite(IO_BITMAP_B, 0); err |= __vmx_vmwrite(MSR_BITMAP, __pa(ksm.msr_bitmap)); err |= __vmx_vmwrite(EPT_POINTER, EPTP(ept, EPTP_DEFAULT)); err |= __vmx_vmwrite(VM_FUNCTION_CTRL, VM_FUNCTION_CTL_EPTP_SWITCHING); err |= __vmx_vmwrite(EPTP_INDEX, EPTP_DEFAULT); err |= __vmx_vmwrite(EPTP_LIST_ADDRESS, __pa(ept->ptr_list)); err |= __vmx_vmwrite(VE_INFO_ADDRESS, __pa(vcpu->ve)); err |= __vmx_vmwrite(CR0_GUEST_HOST_MASK, __CR0_GUEST_HOST_MASK); err |= __vmx_vmwrite(CR4_GUEST_HOST_MASK, __CR4_GUEST_HOST_MASK); err |= __vmx_vmwrite(CR0_READ_SHADOW, cr0); err |= __vmx_vmwrite(CR4_READ_SHADOW, cr4); err |= __vmx_vmwrite(VMCS_LINK_POINTER, -1ULL); /* Guest */ err |= __vmx_vmwrite(GUEST_ES_SELECTOR, es); err |= __vmx_vmwrite(GUEST_CS_SELECTOR, cs); err |= __vmx_vmwrite(GUEST_SS_SELECTOR, ss); err |= __vmx_vmwrite(GUEST_DS_SELECTOR, ds); err |= __vmx_vmwrite(GUEST_FS_SELECTOR, fs); err |= __vmx_vmwrite(GUEST_GS_SELECTOR, gs); err |= __vmx_vmwrite(GUEST_LDTR_SELECTOR, ldt); err |= __vmx_vmwrite(GUEST_TR_SELECTOR, tr); err |= __vmx_vmwrite(GUEST_ES_LIMIT, __segmentlimit(es)); err |= __vmx_vmwrite(GUEST_CS_LIMIT, __segmentlimit(cs)); err |= __vmx_vmwrite(GUEST_SS_LIMIT, __segmentlimit(ss)); err |= __vmx_vmwrite(GUEST_DS_LIMIT, __segmentlimit(ds)); err |= __vmx_vmwrite(GUEST_FS_LIMIT, __segmentlimit(fs)); err |= __vmx_vmwrite(GUEST_GS_LIMIT, __segmentlimit(gs)); err |= __vmx_vmwrite(GUEST_LDTR_LIMIT, __segmentlimit(ldt)); err |= __vmx_vmwrite(GUEST_TR_LIMIT, __segmentlimit(tr)); err |= __vmx_vmwrite(GUEST_GDTR_LIMIT, gdtr.limit); err |= __vmx_vmwrite(GUEST_IDTR_LIMIT, idtr.limit); err |= __vmx_vmwrite(GUEST_ES_AR_BYTES, __accessright(es)); err |= __vmx_vmwrite(GUEST_CS_AR_BYTES, __accessright(cs)); err |= __vmx_vmwrite(GUEST_SS_AR_BYTES, __accessright(ss)); err |= __vmx_vmwrite(GUEST_DS_AR_BYTES, __accessright(ds)); err |= __vmx_vmwrite(GUEST_FS_AR_BYTES, __accessright(fs)); err |= __vmx_vmwrite(GUEST_GS_AR_BYTES, __accessright(gs)); err |= __vmx_vmwrite(GUEST_LDTR_AR_BYTES, __accessright(ldt)); err |= __vmx_vmwrite(GUEST_TR_AR_BYTES, __accessright(tr)); err |= __vmx_vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); err |= __vmx_vmwrite(GUEST_ACTIVITY_STATE, 0); err |= __vmx_vmwrite(GUEST_IA32_DEBUGCTL, __readmsr(MSR_IA32_DEBUGCTLMSR)); err |= __vmx_vmwrite(GUEST_SYSENTER_CS, __readmsr(MSR_IA32_SYSENTER_CS)); err |= __vmx_vmwrite(GUEST_CR0, cr0); err |= __vmx_vmwrite(GUEST_CR3, ksm.origin_cr3); err |= __vmx_vmwrite(GUEST_CR4, cr4); err |= __vmx_vmwrite(GUEST_ES_BASE, 0); err |= __vmx_vmwrite(GUEST_CS_BASE, 0); err |= __vmx_vmwrite(GUEST_SS_BASE, 0); err |= __vmx_vmwrite(GUEST_DS_BASE, 0); err |= __vmx_vmwrite(GUEST_FS_BASE, __readmsr(MSR_IA32_FS_BASE)); err |= __vmx_vmwrite(GUEST_GS_BASE, __readmsr(MSR_IA32_GS_BASE)); err |= __vmx_vmwrite(GUEST_LDTR_BASE, __segmentbase(gdtr.base, ldt)); err |= __vmx_vmwrite(GUEST_TR_BASE, __segmentbase(gdtr.base, tr)); err |= __vmx_vmwrite(GUEST_GDTR_BASE, gdtr.base); err |= __vmx_vmwrite(GUEST_IDTR_BASE, vcpu->idt.base); err |= __vmx_vmwrite(GUEST_DR7, __readdr(7)); err |= __vmx_vmwrite(GUEST_RSP, sp); err |= __vmx_vmwrite(GUEST_RIP, ip); err |= __vmx_vmwrite(GUEST_RFLAGS, __readeflags()); err |= __vmx_vmwrite(GUEST_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP)); err |= __vmx_vmwrite(GUEST_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP)); /* Host */ err |= __vmx_vmwrite(HOST_ES_SELECTOR, es & 0xf8); err |= __vmx_vmwrite(HOST_CS_SELECTOR, cs & 0xf8); err |= __vmx_vmwrite(HOST_SS_SELECTOR, ss & 0xf8); err |= __vmx_vmwrite(HOST_DS_SELECTOR, ds & 0xf8); err |= __vmx_vmwrite(HOST_FS_SELECTOR, fs & 0xf8); err |= __vmx_vmwrite(HOST_GS_SELECTOR, gs & 0xf8); err |= __vmx_vmwrite(HOST_TR_SELECTOR, tr & 0xf8); err |= __vmx_vmwrite(HOST_CR0, cr0); err |= __vmx_vmwrite(HOST_CR3, ksm.kernel_cr3); err |= __vmx_vmwrite(HOST_CR4, cr4); err |= __vmx_vmwrite(HOST_FS_BASE, __readmsr(MSR_IA32_FS_BASE)); err |= __vmx_vmwrite(HOST_GS_BASE, __readmsr(MSR_IA32_GS_BASE)); err |= __vmx_vmwrite(HOST_TR_BASE, __segmentbase(gdtr.base, tr)); err |= __vmx_vmwrite(HOST_GDTR_BASE, gdtr.base); err |= __vmx_vmwrite(HOST_IDTR_BASE, idtr.base); err |= __vmx_vmwrite(HOST_IA32_SYSENTER_CS, __readmsr(MSR_IA32_SYSENTER_CS)); err |= __vmx_vmwrite(HOST_IA32_SYSENTER_ESP, __readmsr(MSR_IA32_SYSENTER_ESP)); err |= __vmx_vmwrite(HOST_IA32_SYSENTER_EIP, __readmsr(MSR_IA32_SYSENTER_EIP)); err |= __vmx_vmwrite(HOST_RSP, stack_base); err |= __vmx_vmwrite(HOST_RIP, (uintptr_t)__vmx_entrypoint); return err == 0; }