首页 > 其他分享 >HyperPlatform

HyperPlatform

时间:2023-02-12 22:03:01浏览次数:38  
标签:cr0 return cr4 region HyperPlatform data processor

之前也写过一个vt的框架,但是比较简单,写的比较乱迁移什么的比较麻烦,于是阅读下HyperPlatform的源码学习下。
本文只对主体框架分析。
vt的流程大概如下
1:检测是否支持VT。
2:vmxon。
3:vmclear.
4:vmptrload。
5:vmcs。
6:vmlaunch
7:vmclear
8:vmoff

VmInitialization

首先是关键的VMinit
检测vt是否已被占用

Use_decl_annotations_ static bool VmpIsHyperPlatformInstalled() {
  PAGED_CODE()

  int cpu_info[4] = {};
  __cpuid(cpu_info, 1);
  const CpuFeaturesEcx cpu_features = {static_cast<ULONG32>(cpu_info[2])};
  if (!cpu_features.fields.not_used) {
    return false;
  }

  __cpuid(cpu_info, kHyperVCpuidInterface);
  return cpu_info[0] == 'PpyH';
}

检测是否支持VT

// Checks if the system supports virtualization
_Use_decl_annotations_ static bool VmpIsVmxAvailable() {
  PAGED_CODE()

  // See: DISCOVERING SUPPORT FOR VMX
  // If CPUID.1:ECX.VMX[bit 5]=1, then VMX operation is supported.
  int cpu_info[4] = {};
  __cpuid(cpu_info, 1);
  const CpuFeaturesEcx cpu_features = {static_cast<ULONG32>(cpu_info[2])};
  if (!cpu_features.fields.vmx) {
    HYPERPLATFORM_LOG_ERROR("VMX features are not supported.");
    return false;
  }
......
  Ia32FeatureControlMsr vmx_feature_control = {
      UtilReadMsr64(Msr::kIa32FeatureControl)};
  if (!vmx_feature_control.fields.enable_vmxon) {
    HYPERPLATFORM_LOG_ERROR("VMX features are not enabled.");
    return false;
  }
......
  return true;
}

检查都通过后进入正题调用VmpStartVm

VmpStartVm

VmpInitializeVm

分配VMXON内存

  processor_data->vmxon_region =
      static_cast<VmControlStructure *>(ExAllocatePoolZero(
          NonPagedPool, kVmxMaxVmcsSize, kHyperPlatformCommonPoolTag));
  if (!processor_data->vmxon_region) {
    VmpFreeProcessorData(processor_data);
    return;
  }
  RtlZeroMemory(processor_data->vmxon_region, kVmxMaxVmcsSize);

分配VMCS内存

  processor_data->vmcs_region =
      static_cast<VmControlStructure *>(ExAllocatePoolZero(
          NonPagedPool, kVmxMaxVmcsSize, kHyperPlatformCommonPoolTag));
  if (!processor_data->vmcs_region) {
    VmpFreeProcessorData(processor_data);
    return;
  }
  RtlZeroMemory(processor_data->vmcs_region, kVmxMaxVmcsSize);

分配VMM stack内存

processor_data->vmm_stack_limit =
      UtilAllocateContiguousMemory(KERNEL_STACK_SIZE);
  if (!processor_data->vmm_stack_limit) {
    VmpFreeProcessorData(processor_data);
    return;
  }
  RtlZeroMemory(processor_data->vmm_stack_limit, KERNEL_STACK_SIZE);

VmpEnterVmxMode

对应VMXON,修正cr0和cr4寄存器的值,在上面申请的VMXON内存中写入版本号,然后执行vmxon。

_Use_decl_annotations_ static bool VmpEnterVmxMode(
    ProcessorData *processor_data) {
  PAGED_CODE()

  // Apply FIXED bits
  // See: VMX-FIXED BITS IN CR0

  //        IA32_VMX_CRx_FIXED0 IA32_VMX_CRx_FIXED1 Meaning
  // Values 1                   *                   bit of CRx is fixed to 1
  // Values 0                   1                   bit of CRx is flexible
  // Values *                   0                   bit of CRx is fixed to 0
  const Cr0 cr0_fixed0 = {UtilReadMsr(Msr::kIa32VmxCr0Fixed0)};
  const Cr0 cr0_fixed1 = {UtilReadMsr(Msr::kIa32VmxCr0Fixed1)};
  Cr0 cr0 = {__readcr0()};
  Cr0 cr0_original = cr0;
  cr0.all &= cr0_fixed1.all;
  cr0.all |= cr0_fixed0.all;
  __writecr0(cr0.all);

  HYPERPLATFORM_LOG_DEBUG("IA32_VMX_CR0_FIXED0   = %08Ix", cr0_fixed0.all);
  HYPERPLATFORM_LOG_DEBUG("IA32_VMX_CR0_FIXED1   = %08Ix", cr0_fixed1.all);
  HYPERPLATFORM_LOG_DEBUG("Original CR0          = %08Ix", cr0_original.all);
  HYPERPLATFORM_LOG_DEBUG("Fixed CR0             = %08Ix", cr0.all);

  // See: VMX-FIXED BITS IN CR4
  const Cr4 cr4_fixed0 = {UtilReadMsr(Msr::kIa32VmxCr4Fixed0)};
  const Cr4 cr4_fixed1 = {UtilReadMsr(Msr::kIa32VmxCr4Fixed1)};
  Cr4 cr4 = {__readcr4()};
  Cr4 cr4_original = cr4;
  cr4.all &= cr4_fixed1.all;
  cr4.all |= cr4_fixed0.all;
  __writecr4(cr4.all);

  HYPERPLATFORM_LOG_DEBUG("IA32_VMX_CR4_FIXED0   = %08Ix", cr4_fixed0.all);
  HYPERPLATFORM_LOG_DEBUG("IA32_VMX_CR4_FIXED1   = %08Ix", cr4_fixed1.all);
  HYPERPLATFORM_LOG_DEBUG("Original CR4          = %08Ix", cr4_original.all);
  HYPERPLATFORM_LOG_DEBUG("Fixed CR4             = %08Ix", cr4.all);

  // Write a VMCS revision identifier
  const Ia32VmxBasicMsr vmx_basic_msr = {UtilReadMsr64(Msr::kIa32VmxBasic)};
  processor_data->vmxon_region->revision_identifier =
      vmx_basic_msr.fields.revision_identifier;

  auto vmxon_region_pa = UtilPaFromVa(processor_data->vmxon_region);
  if (__vmx_on(&vmxon_region_pa)) {
    return false;
  }

  // See: Guidelines for Use of the INVVPID Instruction, and Guidelines for Use
  // of the INVEPT Instruction
  UtilInveptGlobal();
  UtilInvvpidAllContext();
  return true;
}

VmpInitializeVmcs

对应vmclear和vmptrload。向上面申请的VMCS内存区写入版本号,然后执行__vmx_vmclear和__vmx_vmptrld。

_Use_decl_annotations_ static bool VmpInitializeVmcs(
    ProcessorData *processor_data) {
  PAGED_CODE()

  // 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;
}

VmpSetupVmcs

对应VMCS。

标签:cr0,return,cr4,region,HyperPlatform,data,processor
From: https://www.cnblogs.com/awesome-red/p/17114766.html

相关文章