VT-x
Mode
https://scrapbox.io/files/67754eb96af49af34f9b5c57.png
VMX Root (Host)
vmxonでVMX Root Modeへ移行
vmxoffでNon-VMX Modeへ移行
VMX Non-Root (Guest)
vmlaunch, vmresumeでVMX Non-Root Modeへ移行
VMCSに設定したExit ReasonでVMExitする Flow
1. 各種Flagを確認し, vmxonを実行
CPUID :
Processor Info and Feature Bits (0x0001)のVMX Bit (1 << 5)をCheck
MSR :
VMXON outside SMXを確認
MSR : IA32_FEATURE_CONTROL (0x003a)
LOCK_BIT (1 << 0)
0だった場合 : Unsupported
VMX_OUTSIDE_SMX (1 << 2)を立てる
MSRへ書き込む
CR :
vmxonが依存するCR0/CR4のBitを確認する
CR0 :
MSR : IA32_VMX_CR0_FIXED0 (0x0486)
設定が必要なBitを表す
MSR : IA32_VMX_CR0_FIXED1 (0x0487)
設定*可能*なBitを表す
0 Bit (設定不可能なもの)を設定しようとした場合, #GP (13)が発生
Example
code:pseudo.cpp
void enable_vmx_control_registers(const vmx_control_registers &crs)
{
uint32_t target_cr0 = (_read_cr0() | crs.cr0_fixed_0) & crs.cr0_fixed_1;
uint32_t target_cr4 = (_read_cr4() | crs.cr4_fixed_0) & crs.cr4_fixed_1;
_write_cr0(target_cr0);
_write_cr4(target_cr4);
}
CR4 :
MSR : IA32_VMX_CR4_FIXED0 (0x0488)
CR0と同様
MSR : IA32_VMX_CR4_FIXED1 (0x0489)
CR0と同様
vmxon
VMXON RegionをAllocate
Revision IDを設定
VMXON Regionへの*物理アドレス*を引数にvmxonを実行する
仮想アドレスではない!
Asmから呼び出す場合はPointerを渡す (というより, Pointerしか渡せない)
code:pseudo.s
_vmxon:
ret
code:pseudo.cpp
void vmxon(vmxon_region ®ion)
{
auto region_vaddr = std::addressof(region);
auto region_paddr = vaddr_to_paddr(region_vaddr);
_vmxon(®ion_paddr);
}
2. VMCS
構造
code:cpp
struct vmxon_region
{
uint32_t revision_id;
} __attribute__((packed));
static_assert(PAGE_SIZE == sizeof(vmxon_region))
要件
The VMXON pointer must be 4-KByte aligned (bits 11:0 must be zero).
The VMXON pointer must not set any bits beyond the processor’s physical-address width.
Page-Size Alignmentされている必要がある
Reference
Intel SDM