/** * effects: Uninstall Vis Hypervisor */ static NTSTATUS NTAPI HvmLiberateCpu ( PVOID Param ) { //Finish NTSTATUS Status; ULONG64 Efer; PCPU Cpu; // called at DPC level if (KeGetCurrentIrql () != DISPATCH_LEVEL) return STATUS_UNSUCCESSFUL; Efer = MsrRead (MSR_EFER); Print(("Vis:HvmLiberateCpu(): Reading MSR_EFER on entry: 0x%X\n", Efer)); // cause VMM destruction RegSetCr3(VIS_EXIT_FN); Efer = MsrRead (MSR_EFER); Print(("Vis:HvmLiberateCpu(): Reading MSR_EFER on exit: 0x%X\n", Efer)); return STATUS_SUCCESS; }
/* * effects: This service introduced in VMX Preemption * Timer function to the VMCS. * returns: If VMX-Preemption Timer is not supported on the current platform, * returns HVSTATUS_UNSUPPORTED_FEATURE. */ HVSTATUS PtVmxSetTimerInterval( PCPU Cpu, ULONG32 Ticks, /* After how many ticks the VMX Timer will be expired, THIS VALUE IS FIXED TO BE 32 BITS LONG*/ BOOLEAN SaveTimerValueOnVMEXIT, NBP_TRAP_CALLBACK TrapCallback /* If this is null, we won't register a callback function*/ ) { ULONG32 Interceptions; ULONG32 Ratio; LARGE_INTEGER MsrValue,MsrValue1,MsrValue2; PNBP_TRAP Trap; NTSTATUS Status; //Step 0. Check if the current platform supports VMX-Preemption Timer if(!(Cpu->Vmx.FeaturesMSR.VmxPinBasedCTLs.HighPart & PIN_BASED_VMX_TIMER_MASK)) return HVSTATUS_UNSUPPORTED_FEATURE; //Step 1. Activate VMX-Preemption Timer in PIN_BASED_VM_EXEC_CONTROL Interceptions = VmxRead(PIN_BASED_VM_EXEC_CONTROL); VmxWrite(PIN_BASED_VM_EXEC_CONTROL, Interceptions|PIN_BASED_VMX_TIMER_MASK); // Activate VMX-preemption Timer //Step 2. Get the Ratio of TSC-VMX Timer Tick in IA32_VMX_MISC MSR MsrValue.QuadPart = MsrRead(MSR_IA32_VMX_MISC); Ratio = MsrValue.LowPart & (~0xffffffe0); //Step 3. Set the VMX-Preemption Timer Value VmxWrite(VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE, Ticks>>Ratio); //Step 4. Set whether saving VMX-Preemption Timer Value on VMEXIT if(SaveTimerValueOnVMEXIT) { //Save the value Interceptions = VmxRead(VM_EXIT_CONTROLS); VmxWrite(VM_EXIT_CONTROLS, Interceptions|VM_EXIT_SAVE_TIMER_VALUE_ON_EXIT); } //Step 5. Register a callback function if(TrapCallback) { Status = HvInitializeGeneralTrap( Cpu, EXIT_REASON_VMXTIMER_EXPIRED, FALSE, 0, // length of the instruction, 0 means length need to be get from vmcs later. TrapCallback, &Trap, LAB_TAG ); if (!NT_SUCCESS (Status)) { Print(("PtVmxSetTimerInterval(): Failed to register PtVmxSetTimerInterval Callback with status 0x%08hX\n", Status)); return Status; } MadDog_RegisterTrap (Cpu, Trap); } return HVSTATUS_SUCCESS; }
static BOOLEAN NTAPI VmxDispatchMsrRead ( PCPU Cpu, PGUEST_REGS GuestRegs, PNBP_TRAP Trap, BOOLEAN WillBeAlsoHandledByGuestHv, ... ) { LARGE_INTEGER MsrValue; ULONG32 ecx; ULONG inst_len; if (!Cpu || !GuestRegs) return TRUE; inst_len = VmxRead (VM_EXIT_INSTRUCTION_LEN); if (Trap->RipDelta == 0) Trap->RipDelta = inst_len; ecx = GuestRegs->ecx; switch (ecx) { case MSR_IA32_SYSENTER_CS: MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_CS); break; case MSR_IA32_SYSENTER_ESP: MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_ESP); break; case MSR_IA32_SYSENTER_EIP: MsrValue.QuadPart = VmxRead (GUEST_SYSENTER_EIP); Print(("VmxDispatchMsrRead(): Guest EIP: 0x%x read MSR_IA32_SYSENTER_EIP value: 0x%x \n", VmxRead(GUEST_RIP), MsrValue.QuadPart)); break; case MSR_GS_BASE: MsrValue.QuadPart = VmxRead (GUEST_GS_BASE); break; case MSR_FS_BASE: MsrValue.QuadPart = VmxRead (GUEST_FS_BASE); break; case MSR_EFER: MsrValue.QuadPart = Cpu->Vmx.GuestEFER; //_KdPrint(("Guestip 0x%llx MSR_EFER Read 0x%llx 0x%llx \n",VmxRead(GUEST_RIP),ecx,MsrValue.QuadPart)); break; default: if (ecx <= 0x1fff || (ecx >= 0xC0000000 && ecx <= 0xC0001fff)) { MsrValue.QuadPart = MsrRead (ecx); } } GuestRegs->eax = MsrValue.LowPart; GuestRegs->edx = MsrValue.HighPart; return TRUE; }
/** * This function is used to set value safely according to MSR register. * make the <Ctl> values legal. * e.g some Vmx Settings use MSR_IA32_VMX_PINBASED_CTLS & MSR_IA32_VMX_TRUE_PINBASED_CTLS. */ ULONG32 NTAPI PtVmxAdjustControls ( ULONG32 Ctl, ULONG32 Msr ) { LARGE_INTEGER MsrValue; MsrValue.QuadPart = MsrRead (Msr); Ctl &= MsrValue.HighPart; /* bit == 0 in high word ==> must be zero */ Ctl |= MsrValue.LowPart; /* bit == 1 in low word ==> must be one */ return Ctl; }