Beispiel #1
0
_Use_decl_annotations_ EXTERN_C static bool VminitpInitializeVMCS(
    PER_PROCESSOR_DATA *ProcessorData) {
  // Write a VMCS revision identifier
  IA32_VMX_BASIC_MSR vmxBasicMsr = {__readmsr(IA32_VMX_BASIC)};
  ProcessorData->VmcsRegion->RevisionIdentifier =
      vmxBasicMsr.Fields.RevisionIdentifier;

  auto vmcsRegionPA = MmGetPhysicalAddress(ProcessorData->VmcsRegion);

  // It stores the value FFFFFFFF_FFFFFFFFH if there is no current VMCS
  if (__vmx_vmclear(
          reinterpret_cast<unsigned long long *>(&vmcsRegionPA.QuadPart))) {
    return false;
  }

  // Software makes a VMCS current by executing VMPTRLD with the address
  // of the VMCS; that address is loaded into the current-VMCS pointer.
  if (__vmx_vmptrld(
          reinterpret_cast<unsigned long long *>(&vmcsRegionPA.QuadPart))) {
    return false;
  }

  // The launch state of current VMCS is "clear"
  return true;
}
Beispiel #2
0
NTSTATUS ControlAreaInitializeProcessor(LONG ProcessorNumber)
{
	//
	// Allocate host stack region
	// 16 pages available for use
	//
	SIZE_T stackSize = 16 * PAGE_SIZE;
	PUCHAR stackBase = ExAllocatePoolWithTag(NonPagedPool, stackSize, 'KSTK');

	if (!stackBase)
		return STATUS_NO_MEMORY;

	RtlSecureZeroMemory((PVOID)stackBase, stackSize);

	//
	// Set up CPU control structure
	//
	PVIRT_CPU cpu		= (PVIRT_CPU)(stackBase + stackSize - 8 - sizeof(VIRT_CPU));
	cpu->HostStackBase	= stackBase;
	cpu->Self			= cpu;

	CpuControlArea[ProcessorNumber] = cpu;

	//
	// Allocate all VMX regions
	//
	if (!NT_SUCCESS(AllocateVmxProcessorData(&cpu->VmxonVa, &cpu->VmxonPa, &cpu->VmxonSize)))
		return STATUS_NO_MEMORY;

	if (!NT_SUCCESS(AllocateVmxProcessorData(&cpu->VmcsVa, &cpu->VmcsPa, &cpu->VmcsSize)))
		return STATUS_NO_MEMORY;

	if (!NT_SUCCESS(AllocateVmxProcessorData(&cpu->MSRBitmapVa, &cpu->MSRBitmapPa, &cpu->MSRBitmapSize)))
		return STATUS_NO_MEMORY;

	// Bitmap needs to be zeroed
	RtlSecureZeroMemory(cpu->MSRBitmapVa, cpu->MSRBitmapSize);

	__try
	{
		if (__vmx_on(PA_PTR_INT64(cpu->VmxonPa)) > 0)
			return STATUS_UNSUCCESSFUL;

		if (__vmx_vmclear(PA_PTR_INT64(cpu->VmcsPa)) > 0)
			return STATUS_UNSUCCESSFUL;

		if (__vmx_vmptrld(PA_PTR_INT64(cpu->VmcsPa)) > 0)
			return STATUS_UNSUCCESSFUL;
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		// Rare case (or if physical address is invalid)
		return GetExceptionCode();
	}

	return STATUS_SUCCESS;
}
Beispiel #3
0
static bool init_vmcs(struct vmcs *vmcs)
{
	u64 vmx = __readmsr(MSR_IA32_VMX_BASIC);
	vmcs->revision_id = (u32)vmx;

	uintptr_t pa = __pa(vmcs);
	if (__vmx_vmclear(&pa))
		return false;

	return __vmx_vmptrld(&pa) == 0;
}
Beispiel #4
0
// See: VMM SETUP & TEAR DOWN
_Use_decl_annotations_ static bool VmpInitializeVMCS(
    ProcessorData *processor_data) {
  // Write a VMCS revision identifier
  const Ia32VmxBasicMsr vmx_basic_msr = {UtilReadMsr64(Msr::kIa32VmxBasic)};
  processor_data->vmcs_region->revision_identifier =
      vmx_basic_msr.fields.revision_identifier;

  auto vmcs_region_pa = UtilPaFromVa(processor_data->vmcs_region);
  if (__vmx_vmclear(&vmcs_region_pa)) {
    return false;
  }
  if (__vmx_vmptrld(&vmcs_region_pa)) {
    return false;
  }

  // The launch state of current VMCS is "clear"
  return true;
}
Beispiel #5
0
/// <summary>
/// Switch CPU to root mode
/// </summary>
/// <param name="Vcpu">Virtual CPU data</param>
/// <returns>TRUE on success</returns>
BOOLEAN VmxEnterRoot( IN PVCPU Vcpu )
{
    PKSPECIAL_REGISTERS Registers = &Vcpu->HostState.SpecialRegisters;
    PIA32_VMX_BASIC_MSR pBasic = (PIA32_VMX_BASIC_MSR)&Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_BASIC )];

    // Ensure the the VMCS can fit into a single page
    if (pBasic->Fields.RegionSize > PAGE_SIZE)
    {
        DPRINT( "HyperBone: CPU %d: %s: VMCS region doesn't fit into one page\n", CPU_IDX, __FUNCTION__ );
        return FALSE;
    }

    // Ensure that the VMCS is supported in writeback memory
    if (pBasic->Fields.MemoryType != VMX_MEM_TYPE_WRITEBACK)
    {
        DPRINT( "HyperBone: CPU %d: %s: Unsupported memory type\n", CPU_IDX, __FUNCTION__ );
        return FALSE;
    }

    // Ensure that true MSRs can be used for capabilities
    if (pBasic->Fields.VmxCapabilityHint == 0)
    {
        DPRINT( "HyperBone: CPU %d: %s: No true MSR support\n", CPU_IDX, __FUNCTION__ );
        return FALSE;
    }

    // Capture the revision ID for the VMXON and VMCS region
    Vcpu->VMXON->RevisionId = pBasic->Fields.RevisionIdentifier;
    Vcpu->VMCS->RevisionId  = pBasic->Fields.RevisionIdentifier;

    // Update CR0 with the must-be-zero and must-be-one requirements
    Registers->Cr0 &= Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_CR0_FIXED1 )].LowPart;
    Registers->Cr0 |= Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_CR0_FIXED0 )].LowPart;

    // Do the same for CR4
    Registers->Cr4 &= Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_CR4_FIXED1 )].LowPart;
    Registers->Cr4 |= Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_CR4_FIXED0 )].LowPart;

    // Update host CR0 and CR4 based on the requirements above
    __writecr0( Registers->Cr0 );
    __writecr4( Registers->Cr4 );

    // Enable VMX Root Mode
    PHYSICAL_ADDRESS phys = MmGetPhysicalAddress( Vcpu->VMXON );
    int res = __vmx_on( (PULONG64)&phys );
    if (res)
    {
        DPRINT( "HyperBone: CPU %d: %s: __vmx_on failed with status %d\n", CPU_IDX, __FUNCTION__, res );
        return FALSE;
    }

    // Clear the state of the VMCS, setting it to Inactive
    phys = MmGetPhysicalAddress( Vcpu->VMCS );
    if (__vmx_vmclear( (PULONG64)&phys ))
    {
        DPRINT( "HyperBone: CPU %d: %s: __vmx_vmclear failed\n", CPU_IDX, __FUNCTION__ );
        return FALSE;
    }

    // Load the VMCS, setting its state to Active
    if (__vmx_vmptrld( (PULONG64)&phys ))
    {
        DPRINT( "HyperBone: CPU %d: %s: __vmx_vmptrld failed\n", CPU_IDX, __FUNCTION__ );
        return FALSE;
    }

    // VMX Root Mode is enabled, with an active VMCS.
    return TRUE;
}