Pre-VMX Operation

Before we define and enable VMX operation there are some pre-VMX operation requirements that need to be satisfied before using vmxon. If we don’t adhere to the restrictions of pre-VMX operation setup it will result in a failure when using vmxon. These restrictions are placed on the processors registers CR0 and CR4.

  • They’re required to be set to specific values (fixed bit values) prior to entering VMX operation and the use of an unsupported value will result in a failure, and if you attempt to change the fixed values while in VMX operation you’ll be met with a GP (general-protection fault.)

  • VMX is only supported in paged protected mode unless your processor supports unrestricted guest operation (which means your guest can run in unpaged protected mode or in real-address mode.) If you clear the PE or PG bits in CR0 you won’t be able to enter VMX operation.

The architecture provides us with 4 MSRs (listed below) that identify how many bits in the two control registers are fixed.

  • IA32_VMX_CR0_FIXED0
  • IA32_VMX_CR0_FIXED1
  • IA32_VMX_CR4_FIXED0
  • IA32_VMX_CR4_FIXED1

Use __readcr4 to get the control value of CR4 for the logical processor and set the vmx_enable bit, then write the control value back.

int enable_vmx_operation( void )
{
  union __cr4_t cr4 = { 0 };
  union __ia32_feature_control_msr_t feature_msr = { 0 };
  cr4.control = __readcr4();
  cr4.bits.vmx_enable = 1;
  __writecr4( cr4.control );
  //
  // Allow general use of VMXON...
  //
}
  • The vmxon instruction is controlled by an MSR, specifically IA32_FEATURE_CONTROL
  • The system will only support VMX operation if the lock bit, and bit 1 or bit 2 (or both) are set.

Assuming the lock bit was not set, we’re going to set this bit to allow for vmxon to be used outside of safer mode extension operation. If vmxon is used while this bit is clear the processor will generate a GP (general protection fault.)

int enable_vmx_operation( void )
{
  union __cr4_t cr4 = { 0 };
  union __ia32_feature_control_msr_t feature_msr = { 0 };
  cr4.control = __readcr4();
  cr4.bits.vmx_enable = 1;
  __writecr4( cr4.control );
  feature_msr.control = __readmsr( IA32_FEATURE_CONTROL );
    
  if ( feature_msr.bits.lock == 0 ) {
    feature_msr.bits.vmxon_outside_smx = 1;
    feature_msr.bits.lock = 1;
    
    __writemsr( IA32_FEATURE_CONTROL, feature_msr.control );
    return TRUE;
  }
  return FALSE;
}

https://howtohypervise.blogspot.com/2018/09/how-does-control-register-exiting-work.html


🌱 Back to Garden