VMCS Data

[0x00] Concept

이전에는 Intel 에서 제공하는 가상화 확장인 VMX 를 확인하였고, 이에 따라 논리 프로세서를 가상화하는 방법에 대해 다뤘습니다.

이로 인해 논리 프로세서들은 VMXON 명령을 통해 VMX Operation 을 활성화 할 수 있었습니다.

이번 포스트에서는 개념적으로 조금 더 접근합니다. VMCS Region 에 대해 이전 챕터에서 확인하였고 실제 VMCS Data 에는 어떠한 것들이 포함되는지 확인합니다.

매우 많은 내용들이 포함되어 있으며, Intel SDM 을 번역하며 이해하기 어려웠던 내용들을 정리하고, 이를 구조화 하였습니다.

조금 길지만, Intel SDM Vol.3C 31-6 에 있는 VMM 에서 Guest VM 을 설정하고 시작하는데 필요한 최소 단계에 대한 내용입니다.(마찬가지로 2022.04 개정판에서는 삭제되어 있습니다.)

[0x01] VMCS Data

우선은 이전 파트에서 지나쳤던 VMCS Data 의 구조에 대해서 살펴 보겠습니다.

Intel SDM 에서 VMCS Data 구조에 대한 내용은 매우 긴 분량을 차지합니다. 우선 크게 다섯 가지로 나눌 수 있습니다.

  • Guest-state area
    • 프로세서의 상태는 VM Exit 에 의해 Guest-state area 에 저장되고, VM Entry 에 의해 Guest-state area 에서 로드 됩니다.
  • Host-state area
    • 프로세서의 상태는 VM Exit 에 의해 Host-state area 에서 로드 됩니다.
  • VM-execution Control Fields
    • 해당 필드는 VMX Non-root Operation 에서 프로세서 행위를 제어합니다. VM Exit 의 원인을 부분적으로 결정합니다.
  • VM-exit, VM-entry Control Fields
    • 해당 필드는 VM Exit , VM Entry를 제어합니다.
  • VM-exit Information Fields
    • 해당 필드는 VM Exit 에 대한 정보를 수신하고 원인과 특성을 설명합니다. 일부 프로세서에서 해당 필드는 읽기 전용입니다.(IA32_VMX_MISC 를 통해 읽기 전용인지 확인 가능)

위에서 VM-execution, exit, entry fields 를 집합적으로 VMX Control 이라고 하는 경우도 있습니다.

각 필드들에는 지원되는지를 확인하기 위해 특정 MSR 을 이용합니다. 해당 내용은 아래와 같습니다.

#define IA32_VMX_MISC_MSR                  0x485
typedef struct _IA32_VMX_MISC
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 VMXPreemptionTSCRelationship : 5; // 00-04  
			ULONG64 StoreEferLmaOnVmEntryControl : 1; // 05
			/*
			* Bits 8:6 report, as a bitmap, the activity states supported by the implementation:
			* Bit 6 reports (if set) the support for activity state 1 (HLT).
            * Bit 7 reports (if set) the support for activity state 2 (shutdown).
            * Bit 8 reports (if set) the support for activity state 3 (wait-for-SIPI).
			* If an activity state is not supported, the implementation causes a VM entry to fail if it attempts to establish that activity state. 
			* All implementations support VM entry to activity state 0 (active).
			*/
			ULONG64 SupportedActivityState : 3;          // 06-08
			ULONG64 Reserved_1 : 5;                      // 09-13
			ULONG64 SupportProcessorTrace : 1;           // 14
			ULONG64 SupportReadSMBASEMsr : 1;            // 15
			ULONG64 Cr3TargetCount : 9;                  // 16-24
			ULONG64 MaxNumberOfMSR : 3;                  // 25-27
			ULONG64 CanSMMMonitorCtlBit2 : 1;            // 28
			ULONG64 SupportVMWriteVmExitInfo : 1;        // 29
			ULONG64 ZeroInstructionVMEntryInjection : 1; // 30
			ULONG64 Reserved_2 : 1;                      // 31
			ULONG64 MsegIdentifier : 32;                 // 32-63
		};
	};
}IA32_VMX_MISC,* PIA32_VMX_MISC;

[0x02] Guest-State Area

위에서 설명한 것과 같이 Guest-state area 에는 VM Exit 발생 시 프로세서의 특정 상태들이 저장되고 VM Entry 에 의해 해당 영역에서 프로세서의 상태들이 로드 됩니다.

총 두 가지로 Guest Register StateGuest Non-Register State 로 나눠집니다.

[-] Guest Register State

해당 프로세서의 레지스터 상태 값이 존재하며 아래와 같은 레지스터 값이 존재합니다.

  • Control Register(64 bits or 32 bits)
    • CR0
    • CR3
    • CR4
  • Debug Register(64 bits or 32 bits)
    • DR7
  • RSP, RIP, RFLAGS(64 bits or 32 bits)
  • CS, SS, DS, ES, FS, GS, LDTR, TR
    • Selector(16 bits), Base Address(64 bits), Segment Limit(32 bits), Access rights(32 bits)
    • 기본적으로 x64 Segment Register 를 따른다.
    • Selector 외에도 Segment Descriptor 까지 필요, Segment RegisterDescriptor Cache 와 선택자가 참조하는 메모리(GDT, LDT)에 있는 Segment Descriptor 와 일치하지 않을 수 있기 때문에 VMCS에 포함
  • GDTR, IDTR
    • Base Address(64 bits or 32 bits)
    • Limit(32 bits)
  • MSR
    • IA32_DEBUGCTL(64 bits)
    • IA32_SYSENTER_CS(32 bits)
    • IA32_SYSENTER_ESP, EIP (64 bits or 32 bits)
    • 그 외 각 VMX Control 필드에서 해당하는 비트가 1로 설정 가능한 경우(자세한 VMX Control 내용 생략)
      • IA32_PERF_GLOBAL_CTRL, IA32_PAT, IA32_EFER, IA32_BNDCFGS, IA32_RTIT_CTL, IA32_LBR_CTL, IA32_S_CET, IA32_INTERRUPT_SSP_TABLE_ADDR, IA32_PKRS
      • ex : IA32_PERF_GLOBAL_CTRL : VM-entry Controlload IA32_PERF_GLOBAL_CTRL
  • Shadow-Stack Pointer Register SSP(64 bits or 32 bits)
    • VM-entry controlload CET state 가 설정된 경우
  • Register SMBASE(32 bits)
    • 해당 레지스터는 논리 프로세서의 SMRAM 이미지의 기본 주소를 포함
    • SMRAMSystem Management Mode(SMM) 에서 생성되는 메모리 영역(System Management RAM)

[-] Guest Non-Register State

Guest Register State 외에도 프로세서 레지스터에 해당하지 않는 게스트 상태의 특성을 지닌 필드가 존재합니다.

  • Activity State(32 bits)
    • 논리 프로세서의 활동 상태를 식별
    • 논리 프로세서가 명령을 정상적으로 실행하고 있을 때 Active 상태
    • 특정 명령을 실행하고 특정 이벤트가 발생하면 논리 프로세서가 명령 실행을 중단하는 비활성화 상태로 전환될 수 있음
    • 아래와 같이 활동 상태가 정의
      • Active : 논리 프로세서가 정상적으로 명령을 실행 중입니다.
      • HLT : 논리 프로세서가 HLT 명령을 실행했기 때문에 비활성화 되었습니다.
      • Shutdown : 논리 프로세서가 Triple Fault 또는 심각한 오류가 발생했기 때문에 비활성화 되었습니다.
      • Wait-for-SIPI : 논리 프로세서가 (SIPI(Startup-IPI) 를 기다리고 있기 때문에 비활성화 상태 입니다.
    • 지원되는 활동 상태는 MSR IA32_VMX_MISC 를 읽어야 합니다. (bit 6 - 8)
  • Interruptibility State(32 bits)
    • IA-32 아키텍처에는 일정 시간 동안 특정 이벤트를 차단할 수 있는 기능이 포함되어 있습니다.
    • 해당 필드에는 이러한 차단 정보가 포함됩니다.
      typedef struct _INTERRUPTIBILITY_STATE
      {
      	union
      	{
      		ULONG All;
      		struct
      		{
      			ULONG BlockSTI : 1;              // 00
      			ULONG BlockMOVSS : 1;            // 01
      			ULONG BlockSMI : 1;              // 02
      			ULONG BlockNMI : 1;              // 03
      			ULONG EnclaveInterruption : 1;   // 04
      			ULONG Reserved : 27;             // 05-31
      		}Fields;
      	};
      }INTERRUPTIBILITY_STATE, * PINTERRUPTIBILITY_STATE;
    
  • Pending Debug Exception(64 bits or 32 bits)
    • IA-32 프로세서는 하나 이상의 디버그 예외를 인식할 수 있습니다. 해당 필드는 이러한 예외에 대한 정보가 포함됩니다.
      typedef struct _PENDING_DEBUG_EXCEPTION
      {
      	union
      	{
      		ULONG64 All;
      		struct
      		{
      			ULONG64 B0 : 1;                 // 00
      			ULONG64 B1 : 1;                 // 01
      			ULONG64 B2 : 1;                 // 02
      			ULONG64 B3 : 1;                 // 03
      			ULONG64 Reserved_1 : 8;         // 04-11
      			ULONG64 EnableBreakpoint : 1;   // 12
      			ULONG64 Reserved_2 : 1;         // 13
      			ULONG64 BS : 1;                 // 14
      			ULONG64 Reserved_3 : 1;         // 15
      			ULONG64 RTM : 1;                // 16 (Restricted Transactional Memory)
      			ULONG64 Reserved_4 : 47;        // 17-63
      		}Fields;
      	};
      }PENDING_DEBUG_EXCEPTION, * PPENDING_DEBUG_EXCEPTION;
    
  • VMCS Link Pointer(64 bits)
    • VM-execution controlVMCS Shadowing 비트가 1이면, VMREADVMWRITE 명령은 이 포인터가 참조하는 VMCS 에 액세스합니다. 그렇지 않으면 VMMVM Entry 실패를 피하기 위해 이 필드를 FFFFFFFF'FFFFFFFF 으로 설정해야 합니다.
  • VMX-Preemption Timer Value(32 bits)
    • 이 필드는 VM-execution controlactivate VMX-preemption timer 가 1로 설정이 가능한 프로세서에서만 지원 됩니다.
  • Page-Directory-Pointer-Table Entries(PDPTEs; 64 bits each)
    • 4 개의 필드로 구성(PDPTE0 ~ 3)되며, VM-execution controlEnable EPT 가 1로 설정이 가능한 프로세서에서만 지원됩니다. PAE 페이징이 사용 중일 때 CR3 에서 참조하는 PDPTE에 해당합니다.
  • Guest Interrupt Status(16 bits)
    • 이 필드는 VM-execution controlVirtual-Interrupt Delivery 가 1로 설정 가능한 프로세서에서만 지원됩니다.
    • Requesting Virtual Interrupt(RVI)
      • 이것은 Guest Interrupt Status 의 하위 바이트 입니다. 프로세서는 이 값을 서비스 중 가장 높은 우선 순위의 가상 인터럽트의 벡터로 취급합니다. (0인 경우 이러한 인터럽트가 존재하지 않음을 의미합니다.)
    • Servicing Virtual Interrupt(SVI)
      • 이것은 Guest Interrupt Status 의 상위 바이트 입니다. 프로세서는 이 값을 서비스 중 가장 높은 우선 순위의 가상 인터럽트의 벡터로 취급합니다. (0인 경우 이러한 인터럽트가 존재하지 않음을 의미합니다.)
  • PML Index(16 bits)
    • 이 필드는 VM-execution controlEnable PML 가 1로 설정 가능한 프로세서에서만 지원됩니다. 이 필드에는 페이지 수정 로그에 있는 다음 Entry의 논리적 인덱스가 포함됩니다.
    • 페이지 수정 로그는 512개의 Entry 로 구성되기 때문에 PML Index 는 일반적으로 0-511 범위의 값 입니다.

[0x03] Host-State Area

해당 영역에는 앞서 설명한 것과 같이 모든 VM Exit 에 대해 해당 영역에서 프로세서 상태를 로드 합니다.

Host-State Area 의 모든 필드는 프로세서 레지스터에 해당합니다.

[-] Processor Register

  • Control Register(64 bits each or 32 bits)
    • CR0, CR3, CR4
  • RSP and RIP(64 bits each or 32 bits)
  • Selector Fields(16 bits each) (For Segment Register)
    • CS, SS, DS, ES, FS, GS, TR
    • LDTR Selector에 대한 필드는 Host-State Area 에는 존재하지 않습니다.
  • Base-address Fields(64 bits each) (For Segment Register)
    • FS, GS, TR, GDTR, IDTR
  • MSR
    • IA32_SYSENTER_CS(32 bits)
    • IA32_SYSENTER_ESP, EIP(64 bits or 32 bits)
    • VM-exit control 내 각 해당하는 비트가 1로 설정을 지원하는 경우
      • IA32_PERF_GLOBAL_CTRL, IA32_PAT, IA32_EFER, IA32_S_CET, IA32_INTERRUPT_SSP_TABLE_ADDR, IA32_PKRS
  • Shadow-Stack Pointer Register SSP(64 bits)
    • VM-exit controlload CET state 가 1로 설정을 지원하는 경우에만 지원됩니다.

[0x04] VM-Execution Control Fields

VMX-execution control 필드는 VMX Non-root operation 을 제어 합니다.

[-] Pin-Based VM-Execution Controls

Intel PIN 기반의 제어는 비동기 이벤트(ex. Interrupt)의 처리를 제어하는 32비트의 벡터를 구성합니다.

해당 필드의 다른 모든 비트는 예약되어 있으며, 일부는 0이고 일부는 1입니다. VMM 은 이러한 예약된 비트를 설정하는 방법을 결정하기 위해 MSR IA32_VMX_PINBASED_CTLS(0x481) , MSR IA32_VMX_TRUE_PINBASED_CTLS(0x48D) 를 참조해야 합니다.

IA32_VMX_PINBASED_CTLS 의 경우에는 bit 1, 2, 4 비트가 항상 1로 설정되어야 했습니다.

이러한 비트의 0으로의 설정을 지원하는 논리 프로세서는 IA32_VMX_TRUE_PINBASED_CTLS 를 지원하며, VMM은 이 MSR을 참조하여 해당 비트를 0으로의 설정에 대한 지원 여부를 확인해야 합니다.

추가로, 현재 지속적으로 등장하는 MSR 의 경우, VMX 와 연관이 있는 MSR 은 0x480부터 일반적으로 시작됩니다.

대부분 기능에 대한 보고 레지스터라고 설명되며, 이는 필요한 비트 설정등이나 기능 활성 가능 여부 등을 나타냅니다.

우선 실제로 구현할 때, 참조해야 하는 부분은 IA32_VMX_BASIC 을 읽어 참조해야 합니다. 해당 MSR 에서 bit 55 에 있는 VmxControlsIA32_TRUE_PINBASED_CTLS 에 대한 지원 여부를 포함합니다.

IA32_VMX_BASIC.VmxControls == 1 인 경우에는 IA32_TRUE_PINBASED_CTLS 를 지원함을 의미합니다.

#define IA32_VMX_PINBASED_CTLS_MSR         0x481
#define IA32_VMX_TRUE_PINBASED_CTLS_MSR    0x48D
typedef struct _IA32_VMX_PINBASED_CTLS
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 ExternalInterruptExiting : 1;        // 00
			ULONG64 Reserved_1 : 2;                      // 01-02
			ULONG64 NMIExiting : 1;                      // 03
			ULONG64 Reserved_2 : 1;                      // 04
			ULONG64 VirtualNMIs : 1;                     // 05
			ULONG64 Activate_VMX_PreemptionTimer : 1;    // 06
			ULONG64 ProcessPostedInterrupts : 1;         // 07
			ULONG64 Reserved_3 : 56;                     // 08-63
		}Fields;
	};
}IA32_VMX_PINBASED_CTLS, * PIA32_VMX_PINBASED_CTLS;

[-] Processor-Based VM-Execution Controls

프로세서 기반의 제어는 주로 특정 명령어의 실행으로 인해 발생하는 동기 이벤트를 제어하는 세 가지 벡터로 구성됩니다.

Primary Processor-Based VM-Execution Controls(32 bits), Secondary Processor-Based VM-Execution Controls(32 bits), Tertiary Processor-Based VM-Execution Controls(64 bits) 입니다.

아래부터는 Primary, Secondary, Tertiary Control 으로 표현하겠습니다.

이 필드 또한 Pin-Based 와 동일하게 다른 모든 비트는 예약되어 있고 0이거나 1입니다. 해당 필드는 예약된 비트를 설정하는 방법을 결정하기 위해 MSR IA32_VMX_PROCBASED_CTLS(0x482)MSR IA32_VMX_TRUE_PROCBASED_CTLS(0x48E) 를 참조해야 합니다. (마찬가지로 IA32_VMX_BASIC.Fields.VmxControls 에 따라 MSR IA32_VMX_TRUE_PROCBASED_CTLS 지원 여부가 결정됨)

MSR IA32_VMX_PROCBASED_CTLS 는 1, 4, 5, 6, 8, 13, 14, 15, 16, 26 비트에 대해 항상 1로 설정되어야 한다고 보고되었습니다.(보고 레지스터 이기 때문)

이러한 비트의 0으로의 설정을 지원하는 논리 프로세서는 IA32_VMX_TRUE_PROCBASED_CTLS 를 지원하며, VMM은 이 MSR을 참조하여 해당 비트를 0으로의 설정에 대한 지원 여부를 확인해야 합니다.

Bit 31 은 Secondary Control 이 사용되는지 여부를 결정합니다. 해당 비트가 0인 경우 VM EntryVM Non-root operation 은 모든 Secondary Processor-Based VM-execution Control 이 0인 것 처럼 동작합니다.

Primary Control 의 Bit 31 이 0에 대한 설정만 지원하는 프로세서는 Secondary Control 을 지원하지 않습니다.

아래는 Primary 에 대한 필드 설명입니다.

#define IA32_VMX_PROCBASED_CTLS_MSR        0x482
#define IA32_VMX_TRUE_PROCBASED_CTLS_MSR   0x48E
typedef struct _IA32_VMX_PROCBASED_CTLS
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 Reserved_1 : 2;                     // 00-01
			ULONG64 InterruptWindowExiting : 1;         // 02
			ULONG64 UseTSCOffsetting : 1;               // 03
			ULONG64 Reserved_2 : 3;                     // 04-06
			ULONG64 HLT_Exiting : 1;                    // 07
			ULONG64 Reserved_3 : 1;                     // 08
			ULONG64 INVLPG_Exiting : 1;                 // 09
			ULONG64 MWAIT_Exiting : 1;                  // 10
			ULONG64 RDPMC_Exiting : 1;                  // 11
			ULONG64 RDTSC_Exiting : 1;                  // 12
			ULONG64 Reserved_4 : 2;                     // 13-14
			ULONG64 CR3Load_Exiting : 1;                // 15
			ULONG64 CR3Store_Exiting : 1;               // 16
			ULONG64 Activate_TertiaryControls : 1;      // 17
			ULONG64 Reserved_5 : 1;                     // 18
			ULONG64 CR8Load_Exiting : 1;                // 19
			ULONG64 CR8Stor_Exiting : 1;                // 20
			ULONG64 UseTPRShadow : 1;                   // 21
			ULONG64 NMIWindow_Exiting : 1;              // 22
			ULONG64 MOV_DR_Exiting : 1;                 // 23
			ULONG64 Unconditional_IO_Exiting : 1;       // 24
			ULONG64 Use_IO_Bitmaps : 1;                 // 25
			ULONG64 Reserved_6 : 1;                     // 26
			ULONG64 MonitorTrapFlag : 1;                // 27
			ULONG64 UseMSRBitmaps : 1;                  // 28
			ULONG64 MONITOR_Exiting : 1;                // 29
			ULONG64 PAUSE_Exiting : 1;                  // 30
			ULONG64 Activate_SecondaryControls : 1;     // 31
			ULONG64 Reserved_7 : 32;                    // 32-63
		}Fields;
	};
}IA32_VMX_PROCBASED_CTLS, * PIA32_VMX_PROCBASED_CTLS;

Secondary Control 의 경우 MSR IA32_VMX_PROCBASED_CTLS2 를 참조하여 1로 설정할 수 있는 비트를 결정해야 합니다. 0으로 설정할 수 있는 비트에 대한 MSR 은 존재하지 않습니다.

아래는 Secondary Control 에 대한 필드입니다.

#define IA32_VMX_PROCBASED_CTLS2 0x48B
typedef struct _IA32_VMX_PROCBASED_CTLS2
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 VirtualizeAPIC_Access : 1;            // 00
			ULONG64 EnableEPT : 1;                        // 01
			ULONG64 DescriptorTable_Exiting : 1;          // 02
			ULONG64 EnableRDTSCP : 1;                     // 03
			ULONG64 Virtualize_x2APICMode : 1;            // 04
			ULONG64 EnableVPID : 1;                       // 05
			ULONG64 WBINVD_Exiting : 1;                   // 06
			ULONG64 UnrestrictedGuest : 1;                // 07
			ULONG64 APICRegister_Virtualization : 1;      // 08
			ULONG64 VirtualInterruptDelivery : 1;         // 09
			ULONG64 PAUSE_Loop_Exiting : 1;               // 10
			ULONG64 RDRAND_Exiting : 1;                   // 11
			ULONG64 EnableINVPCID : 1;                    // 12
			ULONG64 EnableVMFunction : 1;                 // 13
			ULONG64 VMCSShadowing : 1;                    // 14
			ULONG64 EnableENCLS_Exiting : 1;              // 15
			ULONG64 RDSEED_Exiting : 1;                   // 16
			ULONG64 EnablePML : 1;                        // 17   Page-Modification Logging
			ULONG64 EPT_Violation_VE : 1;                 // 18
			ULONG64 ConcealVMX_FromPT : 1;                // 19
			ULONG64 EnableXSAVES_XRSTORS : 1;             // 20
			ULONG64 Reserved_1 : 1;                       // 21
			ULONG64 ModeBasedExecuteControlForEPT : 1;    // 22
			ULONG64 SubPageWritePermissionsForEPT : 1;    // 23
			ULONG64 IntelPT_UsesGuestPhysicalAddress : 1; // 24
			ULONG64 UseTSCScaling : 1;                    // 25
			ULONG64 EnableUserWaitAndPause : 1;           // 26
			ULONG64 EnablePCONFIG : 1;                    // 27
			ULONG64 EnableENCLV_Exiting : 1;              // 28
			ULONG64 Reserved_2 : 35;                      // 29-63
		}Fields;
	};
}IA32_VMX_PROCBASED_CTLS2, * PIA32_VMX_PROCBASED_CTLS2;

개정된 Intel SDM 에는 Primary Control 필드에서 bit 17에 대한 값이 추가되었습니다.

해당 Bit 17은 Tertiary Control 이 사용되는지에 대한 여부를 나타냅니다. 해당 비트가 0이면 VM EntryVMX Non-root operation 은 모든 Tertiary Control 이 0인 것 처럼 동작합니다.

VMMMSR IA32_VMX_PROCBASED_CTLS3 를 참조하여 1로 설정할 수 있는 비트를 결정해야 합니다.

Tertiary Control 필드는 아래와 같습니다.

#define IA32_VMX_PROCBASED_CTLS3_MSR 0x492
typedef struct _IA32_VMX_PROCBASED_CTLS3
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 LOADIWKEY_Exiting : 1;               // 00
			ULONG64 EnableHLAT : 1;                      // 01
			ULONG64 EPTPagingWriteControl : 1;           // 02
			ULONG64 GuestPagingVerification : 1;         // 03
			ULONG64 Reserved : 60;                       // 04-63
		}Fields;
	};

}IA32_VMX_PROCBASED_CTLS3, * PIA32_VMX_PROCBASED_CTLS3;

[-] Exception Bitmap

Exception Bitmap 은 각 예외에 대해 하나의 비트를 포함하는 32bit 필드 입니다. 예외가 발생하면 해당 벡터를 사용하여 이 필드에서 비트를 선택합니다.

비트가 1이면 예외로 인해 VM Exit 가 발생합니다. 비트가 0이면 예외 벡터에 해당하는 Descriptor 를 사용하여 IDT 를 통해 예외가 정상적으로 전달됩니다.

Page Fault (벡터 14의 예외)로 인해 VM Exit 가 발생했는지 여부는 Exception Bitmap 의 Bit 14와 VMCS의 페이지 폴트 및 두 개의 32bit 필드에 의해 생성된 오류 코드에 의해 결정됩니다.

[-] I/O-Bitmap Addresses

VM-execution control 필드에는 I/O Bitmap A,B(각 4kb)의 64bit 물리 주소가 포함됩니다. 각 I/O Bitmap 에는 I/O Port에 대해 하나의 비트를 포함합니다.

  • I/O Bitmap A 범위 : 0000h - 7FFFh
  • I/O Bitmap B 범위 : 8000h - FFFFh

논리 프로세서는 Use I/O Bitmaps 필드가 1인 경우에만 이러한 Bitmap 을 사용합니다.(IA32_VMX_PROCBASED_CTLS 내 bit 25)

Bitmap을 사용하는 경우 해당 주소는 4kb 로 정렬되어야 합니다.

[-] Time-Stamp Counter Offset And Multiplier

VM-execution control 필드에는 64bit TSC Offset이 포함됩니다.

만약 RDTSC Exiting 필드(IA32_VMX_PROCBASED_CTL 내 bit 12) 값이 0이고, Use TSC Offsetting 필드(IA32_VMX_PROCBASED_CTL 내 bit 5) 값이 1인 경우 이 필드(TSC-Offset)는 RDTSC , RDTSCP 명령의 실행을 제어합니다.

또한 IA32_TIME_STAMP_COUNTER MSR 에서 읽는 RDMSR 명령의 실행을 제어합니다. 이 모든 것에 대해 TSC Offset 값이 TSC 값에 추가되고 합계가 EDX:EAX 의 게스트 소프트웨어로 반환됩니다.

use TSC scaling 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 25) 값을 1으로의 설정을 지원하는 프로세서는 64bit TSC-Multiplier 필드도 지원합니다.

만약 RDSTSC Exiting 필드가 0이고, Use TSC Offsetting 필드가 1인 경우 이 필드(TSC-Multiplier)는 위에서 식별된 RDTSC, RDTSCP, RDMSR 명령어의 실행에도 영향을 미칩니다.

특히 TSC의 값은 오프셋 값을 추가하기 전에 먼저 TSC-Multiplier 를 곱합니다.

[-] Guest/Host Masks and Read Shadows for CR0 and CR4

VM-execution control 필드에는 Guest/Host Mask와 CR0 및 CR4 에 대한 Read Shadow 가 포함됩니다.

이러한 필드는 해당 레지스터(CLTS, LMSW, MOV CR 및 SMSW 포함)에 접근하는 명령의 실행을 제어합니다.

일반적으로 Guest/Host Mask 에서 1로 설정된 비트는 Host 가 Owned 비트에 해당합니다.

  • Guest가 CLTS, LMSW, MOV CR 을 사용하여 해당 Read Shadow 의 비트와 다른 값을 설정하려고 시도하면 VM Exit 가 발생합니다.
  • Guest가 MOV CR, SMSW 을 사용하면 Read Shadow 에서 이러한 비트에 대한 값을 반환합니다.

Guest/Host Mask 에서 0으로 설정된 비트는 Guest Owned 비트에 해당합니다. Guest가 수정을 시도하면 성공하고 Guest는 Control Register 자체에서 이러한 비트에 대한 반환 값을 읽습니다.

64bit 또는 32bit 일 수 있습니다.

[-] CR3-Target Controls

VM-execution control 필드에는 4개의 CR3-Target 값과 CR3-Target 개수 세트가 포함됩니다. CR3-Target 값은 64bit or 32 bits이며, CR3-Target 개수는 32bit 입니다.

VMX Non-root operation 에서 CR3로 값을 복사하는 명령(MOV to CR3)을 실행해도 소스 피연산자가 이러한 값 중 하나와 일치하는 경우 VM Exit 가 발생하지 않습니다.

CR3-Target 개수가 n인 경우, 처음 n개의 CR3-Target 값만 고려됩니다. CR3-Target 개수가 0인 경우 MOV to CR3 가 발생하면 항상 VM Exit 가 발생합니다.

CR3-Target 값에 대해 쓸 수 있는 값에는 제한이 없습니다. CR3-Target 개수가 4보다 크면 VM Entry 가 실패합니다.

VMM 은 지원되는 값의 개수를 결정하기 위해 MSR IA32_VMX_MISC 를 읽어야 합니다.(bit 16-24)

[-] Controls for APIC Virtualization

VMM 이 논리 프로세서의 로컬 APIC 레지스터에 접근하는 세 가지 메커니즘이 있습니다.

  • 로컬 APICxAPIC 모드인 경우 IA32_APIC_BASE MSR 의 물리 주소가 참조하는 4kb 페이지의 주소에 대한 메모리 매핑 액세스를 수행할 수 있습니다.
  • 로컬 APICx2APIC 모드인 경우 RDMSR, WRMSR 을 사용하여 로컬 APIC 레지스터에 접근할 수 있습니다.
  • 64bit 모드에서는 MOV CR8 명령을 실행하여 로컬 APICTPR(Task-Priority Register) 에 접근할 수 있습니다.

이러한 접근을 제어하는 필드는 5가지로 Processor-Based VM-execution control 에 있습니다.(Primary&Secondary Control)

use TPR shadow, virtualize APIC accesses, virtualize x2APIC mode virtual-interrupt delivery, APICregister virtualization 필드 입니다.

이러한 5가지 필드는 다음의 필드와 상호작용합니다.

  • APIC-access address(64 bits)
    • 이 필드는 4kb 크기의 APIC-access 페이지의 물리 주소를 포함합니다.
    • 만약 virtualize APIC accesses(IA32_VMX_PROCBASED_CTLS2 내 bit 0) 값이 1인 경우, 이 페이지에 접근하면 VM Exit가 발생하거나 프로세서에 의해 해당 페이지가 가상화될 수 있습니다.
    • APIC-access 주소는 virtualize APIC accesses 를 1로 설정할 수 있는 프로세서에만 존재합니다.
  • Virtual-APIC Address(64 bits)
    • 이 필드는 4kb 크기의 Virtual-APIC 페이지의 물리 주소를 포함합니다.
    • 프로세서는 Virtual-APIC 페이지를 사용하여 APIC 레지스터에 대한 특정 액세스를 가상화하고 가상 인터럽트를 관리합니다.
    • 앞에서 설명한 설정에 따라 다음 작업으로 Virtual-APIC 페이지에 접근할 수 있습니다.
      • MOV CR8 명령어
      • virtualize APIC accesses 필드가 1인 경우 APIC-access 페이지에 액세스 합니다.
      • ECX 값이 800h-8ffh 범위에 있고 virtualize x2APIC mode(IA32_VMX_PROCBASED_CTLS2 내 bit 4)가 1인 경우 RDMSR, WRMSR 명령어.
        • 만약 use TPR shadow(IA32_VMX_PROCBASED_CTLS 내 bit 21) 값이 1인 경우, VM EntryVirtual-APIC 의 주소가 4kb로 정렬되도록 합니다.
        • Virtual-APIC 의 주소는 use TPR shadow 필드를 1로 설정 가능한 프로세서에만 존재합니다.
  • TPR threshold(32 bits)
    • 이 필드의 bit 3:0VTPR(Virtual Task-Priority Register)bit 7:4 가 떨어질 수 없는 임계 값을 결정합니다.
    • 만약 virtual-interrupt delivery 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 9) 값이 0이면, 해당 비트의 값을 TPR threshold 아래로 줄이는 작업(ex. MOV to CR8) 후에 VM Exit 가 발생합니다.
    • TPR thresholduse TPR shadow 필드를 1로 설정 가능한 프로세서에서만 존재합니다.
  • EOI-exit bitmap(4 fields, 64 bits each)
    • 이 필드는 virtual-interrupt delivery 필드를 1로 설정 가능한 프로세서에서만 지원됩니다. APICEOI(End Of Interrupt) Register 에 대한 가상화된 write 로 인해 VM Exit 가 발생하는 것을 결정하는데 사용합니다.
    • EOI_EXIT0 : 0-63까지의 벡터에 대한 비트를 포함합니다.
    • EOI_EXIT1 : 64-127까지의 벡터에 대한 비트를 포함합니다.
    • EOI_EXIT2 : 128-191까지의 벡터에 대한 비트를 포함합니다.
    • EOI_EXIT3 : 192-255까지의 벡터에 대한 비트를 포함합니다.
  • Posted-Interrupt Notification Vecotr(16 bits)
    • 이 필드는 process posted interrupts 필드(IA32_VMX_PINBASED_CTLS 내 bit 7) 값을 1로 설정 가능을 지원하는 프로세서에서만 지원됩니다.
    • 하위 8bit에는 가상 인터럽트가 게시(post)되었음을 논리 프로세서에게 알리는데 사용되는 인터럽트가 포함되어 있습니다.
  • Posted-Interrupt Descriptor Address(64 bits)
    • 이 필드는 process posted interrupts 필드 값을 1로 설정 가능을 지원하는 프로세서에서만 지원됩니다.
    • 64-byte로 정렬되있는 Posted-Interrupt 에 대한 설명자의 물리 주소 입니다.

[-] MSR-Bitmap Address

use MSR bitmaps 필드(IA32_VMX_PROCBASED_CTLS 내 bit 28) 값을 1로 설정 가능한 프로세서에만 존재합니다.

VM-execution control 필드에는 크기가 각 1kb인 4개의 연속되는 MSR Bitmap 의 64-bit 물리 주소가 포함됩니다.

4개의 연속되는 물리주소는 각 Read(RDMSR), Write(WRMSR) 에 대한 분류로 2가지로 나뉩니다.

  • Read bitmap for low, high MSRs (MSR-Bitmap Base Address, Base Address + 1024)
    • low msr(00000000h - 00001FFFh), high msr(C0000000h - C0001FFFh) 범위의 각 MSR 주소에 대한 하나의 비트가 포함됩니다.
    • 이 비트는 해당 MSR에 적용된 RDMSR 의 실행이 VM Exit 를 발생시키는지에 대한 여부를 결정합니다.
  • Write bitmap for low, high MSRs(BaseAddress + 2048, BaseAddress + 3072)
    • low msr(00000000h - 00001FFFh), high msr(C0000000h - C0001FFFh) 범위의 각 MSR 주소에 대한 하나의 비트가 포함됩니다.
    • 이 비트는 해당 MSR에 적용된 WRMSR 의 실행이 VM Exit 를 발생시키는지에 대한 여부를 결정합니다.

논리 프로세서는 use MSR bitmaps 필드가 1인 경우에만 이러한 비트맵을 사용합니다. 비트맵이 사용되는 경우 RCX 값이 해당 범위에 없는 경우 RDMSR, WRMSR 을 실행하면 VM Exit 가 발생합니다.

위의 설명에 있듯이 비트맵이 사용되는 경우 해당 주소는 4kb 로 정렬되어야 합니다.

[-] Executive-VMCS Pointer

Executive-VMCS PointerSystem Management Interrupt(SMI)System Management Mode(SMM) 의 이중 모니터 처리에 사용되는 64bit 필드입니다.

[-] Extended-Page-Table Pointer (EPTP)

EPTPEPT PML4 테이블의 기본 주소와 기타 EPT 의 구성 정보가 포함됩니다. 해당 내용은 이후에 가상화에서의 페이징과 관련한 내용에서 자세하게 다룹니다.

EPTPenable EPT 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 1) 값을 1로 설정을 지원하는 프로세서에만 존재합니다.

  • Bit 0:2 까지는 EPT Paging-Structure 에 대한 메모리 유형을 결정하는데 사용됩니다. VMM 은 지원되는 메모리 유형을 결정하기 위해 MSR IA32_VMX_EPT_VPID_CAP 을 읽어야 합니다.
  • Bit 6EPT 에 대한 접근과 Dirty Flag 지원에 대한 필드 입니다. 다만 모든 프로세서에서 이를 지원하는 것은 아닙니다. 때문에 VMM 은 마찬가지로 MSR IA32_VMX_EPT_VPID_CAP 을 읽어야 합니다.
  • Bit 7Shadow-stack page 의 접근 권한을 적용하는 것에 대한 필드입니다. 마찬가지로 MSR IA32_VMX_EPT_VPID_CAP 을 읽어 지원 여부를 확인해야 합니다.
  • Bit 12부터 N-1 까지는 4kb로 정렬된 EPT PML4 Table 의 물리 주소 비트 입니다. 여기서 N 은 논리 프로세서가 지원하는 물리 주소의 너비 입니다. VMMCPUID 실행에 EAX 값을 8000'0008h 로 실행하여 프로세서의 물리 주소 너비를 확인할 수 있습니다. 물리 주소의 너비는 EAX 의 bit 7:0 에서 반환됩니다.

typedef struct _EXTENDED_PAGE_TABLE_POINTER
{
	union
	{
		ULONG64 Features;
		struct
		{
			/*
			* EPT paging-structure memory type (see Section 28.3.7): 0 = Uncacheable (UC) 6 = Write-back (WB) Other values are reserved.
			*/
			ULONG64 EPTPagingStructureMemoryType : 3;               // 00-02
			/*
			* This value is 1 less than the EPT page-walk length (see Section 28.3.2)
			*/
			ULONG64 EPTPageWalkLength : 3;                          // 03-05
			/*
			*  Setting this control to 1 enables accessed and dirty flags for EPT (see Section 28.3.5)
			*/
			ULONG64 EnableAccessAndDirtyFlags : 1;                  // 06
			/*
			*  Setting this control to 1 enables enforcement of access rights for supervisor shadow-stack pages (see Section 28.3.3.2)
			*/
			ULONG64 EnableAccessForSupervisorShadowStackPage : 1;   // 07
			ULONG64 Reserved_1 : 4;                                 // 08-11
			/*
			*  Bits N–1:12 of the physical address of the 4-KByte aligned EPT PML4 table
			*/
			ULONG64 PageFrameNumber : 36;                           // 12-47
			ULONG64 Reserved_2 : 16;                                // 48-63
		}Fields;
	};
}EPTP, * PEPTP;

[-] Virtual-Processor Identifier(VPID)

가상 프로세서 식별자라고 불리는 VPID 는 16bit 의 필드 입니다. enable VPID 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 5) 값의 설정을 1로 지원하는 프로세서에만 존재합니다.

[-] Controls for PAUSE-Loop Exiting

PAUSE-loop exiting 필드(IA32_VMX_PROCBASED_CTLS2 bit 10) 값의 설정을 1로 지원하는 프로세서에서 존재하며, 32 bit의 필드가 포함됩니다.

[-] VM-Function Controls

VM-Function ControlVMX non-root operation 에서 VMFUNC 명령의 사용을 제어하는 64bit의 벡터를 구성합니다.

해당 필드는 activate secondary controls 필드(IA32_VMX_PROCBASED_CTLS 내 bit 31) 값과 enable VM functions 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 13) 값을 1로 설정 가능한 프로세서 에서만 지원됩니다.

VMM 은 비트를 결정하기 위해 MSR IA32_VMX_VMFUNC(0x491) 을 참조해야 합니다.

#define IA32_VMX_VMFUNC_MSR 0x491
typedef struct _IA32_VMX_VMFUNC
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 EPTPSwitching : 1;     // 00
			ULONG64 Reserved : 63;         // 01-63
		}Fields;
	};
}IA32_VMX_VMFUNC;

[-] VMCS Shadowing Bitmap Addresses

VMCS Shadowing 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 14) 값을 1로 설정을 지원하는 프로세서에서 VM-execution control 필드에는 VMREAD Bitmap, VMWRITE Bitmap 의 각 64bit 물리 주소가 포함됩니다.

[-] ENCLS-Exiting Bitmap

ENCLS-Exiting Bitmap 은 64bit 필드 입니다. enable ENCLS Exiting 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 15) 값이 1인 경우 EAX 값에 이 비트가 1이면 ENCLS 를 실행하면 VM Exit 가 발생합니다.

[-] ENCLV-Exiting Bitmap

ENCLS-Exiting Bitmap 설명과 동일합니다. neable ENCLV exiting 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 28) 값이 1인 경우 EAX 값에 해당 비트가 1인 상태에서 ENCLV 가 실행되면 VM Exit 가 발생합니다.

[-] PCONFIG-Exiting Bitmap

64bit 필드이며, Enable PCONFIG 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 27) 값이 1인 경우 EAX 값에 해당하는 비트가 1인 상태에서 PCONFIG 명령을 실행하면 VM Exit 가 발생합니다.

[-] Control Field for Page-Modification Logging

Page-Modification Logging 주소는 64bit 필드 입니다. 페이지 수정 로그의 4kb로 정렬된 주소 입니다. 페이지 수정 로그는 512개의 64bit 엔트리로 구성됩니다.

Enable PML 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 17) 값이 1인 경우 VM EntryPage-Modification Logging 주소가 4kb 로 정렬되도록 합니다. 마찬가지로 1로의 설정을 지원하는 프로세서에만 지원됩니다.

[-] Control for Virtualization Exceptions

EPT-violation #VE 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 18) 값의 1로 설정을 지원하는 프로세서에서 VM-execution control 필드에는 다음 필드가 포함됩니다.

  • Virtualization-exception information address(64 bits)
    • 이 필드는 Virtualization-exception 정보 영역의 물리 주소가 포함됩니다.
    • 논리 프로세서에서 가상화 예외가 발생하면 가상화 예외 정보 주소에 가상화 예외 정보를 저장합니다.
  • EPTP Index(16 bits)
    • EPT Violation 으로 인해 가상화 예외가 발생하면 프로세서는 이 필드의 값을 가상화 예외 정보 영역에 저장합니다. EPTP-Switching 은 이 필드를 업데이트 합니다.

[-] XSS-Exiting Bitmap

enable XSAVES/XRSTORS 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 20) 값을 1로 설정 가능한 프로세서에서 VM-execution control 필드에는 64bit의 XSS-Exiting Bitmap 이 포함됩니다.

만약 enable XAVES/XRSTORS 필드가 1인 경우 XSAVES, XRSTORS 의 실행은 이 비트맵을 참조합니다.

[-] Sub-Page-Permission-Table Pointer(SPPTP)

sub-page write-permission feature of EPT 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 23) 값이 활성화된 경우 EPT 쓰기 권한은 128-byte 단위로 결정될 수 있습니다. 이러한 권한은 메모리의 하위 페이지 권한 구조 계층을 사용하여 결정됩니다.

sub-page write-permission feature of EPT 필드 값을 1로 설정 가능한 프로세서에서만 존재합니다.

// Sub-Page-Permission-Table Pointer
typedef struct _SPPT_POINTER
{
	union
	{
		ULONG64 Featurs;
		struct
		{
			ULONG64 Reserved_1 : 12;               // 00-11
			ULONG64 SPPTablePyhsicalAddress : 36;  // 12-47
			ULONG64 Reserved_2 : 16;               // 48-63
		}Fields;
	};
}SPPTP, * PSPPTP;

Enable HLAT 필드(IA32_VMX_PROCBASED_CTLS3 내 bit 1) 값이 1로 설정된 경우 두 개의 필드(PWT, PCD)가 사용되어 HLAT 페이징을 활성화 합니다.

Hypervisor-Managed Linear-Address Translation Pointer(HLAT Pointer 또는 HLATP) 는 선형 주소 변환에 사용되는 첫 번째 페이징 구조를 찾고 접근하기 위해 HLAT 페이징에서 사용됩니다.

// Hypervisor-Managed Linear-Address Translation Pointer
typedef struct _HLAT_POINTER
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 Reserved_1 : 3;                  // 00-02
			/*
			* Page-level write-through; indirectly determines the memory type used to access the first HLAT paging structure during linear-address translation
			*/
			ULONG64 PWT : 1;                         // 03
			/*
			* Page-level cache disable; indirectly determines the memory type used to access the first HLAT paging structure during linear-address translation.
			*/
			ULONG64 PCD : 1;                         // 04
			ULONG64 Reserved_2 : 7;                  // 05-11
			/*
			*  Guest-physical address (4KB-aligned) of the first HLAT paging structure during linear-address translation.
			*/
			ULONG64 GuestPhysicalAddress : 36;       // 12-47
			ULONG64 Reserved_3 : 16;                 // 48-63
		}Fields;
	};
}HLATP, * PHLATP;

[0x05] VM-Exit Control Fields

VM-Exit Control 필드는 VM Exit 동작을 제어 합니다.

VM-Exit ControlVM Exit 의 기본 동작을 제어하는 두 개의 벡터로 구성됩니다. 각각 Primary VM-exit controls(32 bits) , Secondary VM-exit controls(64 bits) 입니다.

이후에는 Primary, Secondary Exit Control 으로 작성됩니다.

[-] Primary VM-Exit Controls

이 필드의 다른 모든 비트는 예약되어 있으며 일부는 0이고 일부는 1 입니다. VMM 은 예약된 비트를 설정하는 방법을 결정하기 위해 MSR IA32_VMX_EXIT_CTLS(0x483), MSR IA32_VMX_TRUE_EXIT_CTLS(0x48F) 를 참조해야 합니다.

MSR IA32_VMX_EXIT_CTLS는 bit 0-8, 10-11, 13-14, 16, 17 에 대해 항상 1로 설정되어야 한다고 보고되었습니다.

이러한 비트의 0으로의 설정을 지원하는 논리 프로세서는 IA32_VMX_TRUE_EXIT_CTLS를 지원하며, VMM은 이 MSR을 참조하여 해당 비트를 0으로의 설정에 대한 지원 여부를 확인해야 합니다.

#define IA32_VMX_EXIT_CTLS_MSR             0x483
#define IA32_VMX_TRUE_EXIT_CTLS_MSR        0x48F
typedef struct _IA32_VMX_EXIT_CTLS
{
	union
	{
		ULONG64 Features;
		struct
		{
			ULONG64 Reserved_1 : 2;                     // 00-01
			/*
			* This control determines whether DR7 and the IA32_DEBUGCTL MSR are saved on VM exit. 
			* The first processors to support the virtual-machine extensions supported only the 1-setting of this control.
			*/
			ULONG64 SaveDebugControls : 1;              // 02
			ULONG64 Reserved_2 : 6;                     // 03-08
			/*
			* On processors that support Intel 64 architecture, this control determines whether a logical processor is in 64-bit mode after the next VM exit. 
			* Its value is loaded into CS.L, IA32_EFER.LME, and IA32_EFER.LMA on every VM exit.
			* This control must be 0 on processors that do not support Intel 64 architecture.
			*/
			ULONG64 HostAddressSpaceSize : 1;           // 09
			ULONG64 Reserved_3 : 2;                     // 10-11
			/*
			* This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit.
			*/
			ULONG64 Load_IA32_PERF_GLOBAL_CTRL : 1;     // 12
			ULONG64 Reserved_4 : 2;                     // 13-14
			/*
			* This control affects VM exits due to external interrupts:
			* - If such a VM exit occurs and this control is 1, the logical processor acknowledges the interrupt controller, acquiring the interrupt's vector. 
			    The vector is stored in the VM-exit interruption-information field, which is marked valid. 
			* - If such a VM exit occurs and this control is 0, the interrupt is not acknowledged and the VM-exit interruption-information field is marked invalid.
			*/
			ULONG64 AcknowledgeInterruptOnExit : 1;     // 15
			ULONG64 Reserved_5 : 2;                     // 16-17
			/*
			*  This control determines whether the IA32_PAT MSR is saved on VM exit.
			*/
			ULONG64 Save_IA32_PAT : 1;                  // 18
			/*
			*  This control determines whether the IA32_PAT MSR is loaded on VM exit.
			*/
			ULONG64 Load_IA32_PAT : 1;                  // 19
			/*
			*  This control determines whether the IA32_EFER MSR is saved on VM exit.
			*/
			ULONG64 Save_IA32_EFER : 1;                 // 20
			/*
			*  This control determines whether the IA32_EFER MSR is loaded on VM exit.
			*/
			ULONG64 Load_IA32_EFER : 1;                 // 21
			/*
			* This control determines whether the value of the VMX-preemption timer is saved on VM exit
			*/
			ULONG64 Save_VMX_PreemptionTimerValue : 1;  // 22
			/*
			* This control determines whether the IA32_BNDCFGS MSR is cleared on VM exit.
			*/
			ULONG64 Clear_IA32_BNDCFGS : 1;             // 23
			/*
			* If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM exit or a VMCS packet on an SMM VM exit (see Chapter 32).
			*/
			ULONG64 Conceal_VMXfromPT : 1;              // 24
			/*
			* This control determines whether the IA32_RTIT_CTL MSR is cleared on VM exit.
			*/
			ULONG64 Clear_IA32_RTIT_CTL : 1;            // 25
			/*
			*  This control determines whether the IA32_LBR_CTL MSR is cleared on VM exit
			*/
			ULONG64 Clear_IA32_LBR_CTL : 1;             // 26
			ULONG64 Reserved_6 : 1;                     // 27
			/*
			* This control determines whether CET-related MSRs and SPP are loaded on VM exit.
			*/
			ULONG64 Load_CETState : 1;                  // 28
			/*
			*  This control determines whether the IA32_PKRS MSR is loaded on VM exit
			*/
			ULONG64 Load_PKRS : 1;                      // 29
			/*
			* This control determines whether the IA32_PERF_GLOBAL_CTL MSR is saved on VM exit.
			*/
			ULONG64 Save_IA32_PERF_GLOBAL_CTL : 1;      // 30
			/*
			* This control determines whether the secondary VM-exit controls are used. If this control is 0, the logical processor operates as if all the secondary VM-exit controls were also 0.
			*/
			ULONG64 Activate_SecondaryControls : 1;     // 31
			ULONG64 Reserved_7 : 32;                    // 32-63
		}Fields;
	};

}IA32_VMX_EXIT_CTLS, * PIA32_VMX_EXIT_CTLS;

현재는 Secondary Exit Control 이 정의되지 않아 해당 부분은 0으로 예약되어 있습니다.

[-] VM-Exit Controls for MSRs

VMMVM Exit 발생 시 저장하고 로드할 MSR 목록을 지정할 수 있습니다. 다음 필드는 MSRVM Exit 에 의해 저장되는 방식을 결정합니다.

  • VM-exit MSR-store(load) count(32 bits)
    • 이 필드는 VM Exit 에서 저장, 로드할 MSR 의 개수를 지정합니다. 해당 개수는 512개를 초과하지 않는 것이 좋습니다. 그렇지 않으면 예측할 수 없는 문제가 발생할 수 있습니다.
  • VM-exit MSR-store(load) address(64 bits)
    • 이 필드는 VM-exit MSR-store(load) Area 의 물리 주소를 포함합니다.
    • 이 영역은 엔트리 당 16-byte 의 엔트리 테이블로, 엔트리 수는 VM-exit MSR-store(load) count 로 지정됩니다.

// MSR store & load entry
typedef struct _MSR_ENTRY
{
	union
	{
		ULONG64 Header;
		struct
		{
			ULONG64 MSRIndex : 32;     // 00-31
			ULONG64 Reserved : 32;     // 32-64
		}Fields;
	};
	
	union
	{
		ULONG64 MSRData;
		struct
		{
			ULONG64 Reserved : 64;     // 00-63
		}Fields;
	};
}MSR_ENTRY, *PMSR_ENTRY;

typedef struct _VMX_VMEXIT_MSR_TABLE
{
	MSR_ENTRY* MSREntry;   // safe limit count 512
}VMX_VMEXIT_MSR_TABLE, * PVMX_VMEXIT_MSR_TABLE;

[0x06] VM-Entry Control Fields

VM-Entry Control 필드는 VM Entry 동작을 제어합니다.

VM-Entry ControlVM Entry의 기본 동작을 제어하는 32bit인 하나의 벡터로 구성됩니다.

[-] VM-Entry Controls

이 필드의 다른 모든 비트는 예약되어 있으며 일부는 0이고 일부는 1 입니다. VMM 은 예약된 비트를 설정하는 방법을 결정하기 위해 MSR IA32_VMX_ENTRY_CTLS(0x484), MSR IA32_VMX_TRUE_ENTRY_CTLS(0x490) 를 참조해야 합니다.

MSR IA32_VMX_ENTRY_CTLS는 bit 0-8, 12 에 대해 항상 1로 설정되어야 한다고 보고되었습니다.

이러한 비트의 0으로의 설정을 지원하는 논리 프로세서는 IA32_VMX_TRUE_ENTRY_CTLS를 지원하며, VMM은 이 MSR을 참조하여 해당 비트를 0으로의 설정에 대한 지원 여부를 확인해야 합니다.

#define IA32_VMX_ENTRY_CTLS_MSR            0x484
#define IA32_VMX_TRUE_ENTRY_CTLS_MSR       0x490
typedef struct _IA32_VMX_ENTRY_CTLS
{
	union 
	{
		ULONG64 Features;
		struct
		{
			ULONG64 Reserved_1 : 2;                     // 00-01
			/*
			* This control determines whether DR7 and the IA32_DEBUGCTL MSR are loaded on VM entry. 
			* The first processors to support the virtual-machine extensions supported only the 1-setting of this control.
			*/
			ULONG64 LoadDebugControls : 1;              // 02
			ULONG64 Reserved_2 : 6;                     // 03-08
			/*
			* On processors that support Intel 64 architecture, this control determines whether the logical processor is in IA-32e mode after VM entry. 
			* Its value is loaded into IA32_EFER.LMA as part of VM entry. (This control must be 0 on processors that do not support Intel 64 architecture.)
			*/
			ULONG64 IA32eModeGuest : 1;                 // 09
			/*
			*  This control determines whether the logical processor is in system-management mode (SMM) after VM entry. This control must be 0 for any VM entry from outside SMM.
			*/
			ULONG64 EntryToSMM : 1;                     // 10
			/*
			* If set to 1, the default treatment of SMIs and SMM is in effect after the VM entry (see Section 31.15.7). This control must be 0 for any VM entry from outside SMM
			*/
			ULONG64 DeactivateDualMonitorTreatment : 1; // 11
			ULONG64 Reserved_3 : 1;                     // 12
			/*
			* This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry.
			*/
			ULONG64 Load_IA32_PERF_GLOBAL_CTRL : 1;     // 13
			/*
			* This control determines whether the IA32_PAT MSR is loaded on VM entry.
			*/
			ULONG64 Load_IA32_PAT : 1;                  // 14
			/*
			* This control determines whether the IA32_EFER MSR is loaded on VM entry.
			*/
			ULONG64 Load_IA32_EFER : 1;                 // 15
			/*
			* This control determines whether the IA32_BNDCFGS MSR is loaded on VM entry.
			*/
			ULONG64 Load_IA32_BNDCFGS : 1;              // 16
			/*
			* If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM entry or a VMCS packet on a VM entry that returns from SMM (see Chapter 32).
			*/
			ULONG64 Conceal_VMXfromPT : 1;              // 17
			/*
			* This control determines whether the IA32_RTIT_CTL MSR is loaded on VM entry.
			*/
			ULONG64 Load_IA32_RTIT_CTL : 1;             // 18
			ULONG64 Reserved_4 : 1;                     // 19
			/*
			* This control determines whether CET-related MSRs and SPP are loaded on VM entry.
			*/
			ULONG64 Load_CETState : 1;                  // 20
			/*
			* This control determines whether the IA32_LBR_CTL MSR is loaded on VM entry
			*/
			ULONG64 Load_Guest_IA32_LBR_CTL : 1;        // 21
			/*
			* This control determines whether the IA32_PKRS MSR is loaded on VM entry.
			*/
			ULONG64 Load_PKRS : 1;                      // 22
			ULONG64 Reserved_5 : 10;                    // 23-31
			/*
			* It's actually 32 bits, but for unity, it's aligned to 64 bits.
			*/
			ULONG64 Reserved_6 : 32;                    // 32-63

		}Fields;
	};
}IA32_VMX_ENTRY_CTLS, * PIA32_VMX_ENTRY_CTLS;

[-] VM-Entry Conrols for MSRs

VMMVM Entry 에 로드 할 MSR 목록을 지정할 수 있습니다.

  • VM-entry MSR-load count(32 bits)
    • 이 필드는 VM Entry 에서 저장, 로드할 MSR 의 개수를 지정합니다. 해당 개수는 512개를 초과하지 않는 것이 좋습니다. 그렇지 않으면 예측할 수 없는 문제가 발생할 수 있습니다.
  • VM-entry MSR-load Address(64 bits)
    • 이 필드는 VM-entry MSR-load Area 의 물리 주소를 포함합니다.
    • 이 영역은 엔트리 당 16-byte 의 엔트리 테이블로, 엔트리 수는 VM-entry MSR-load count 로 지정됩니다.

[-] VM-Entry Controls for Event Injection

VM EntryIDT(모든 게스트 상태 및 MSR이 로드된 후) 를 통해 이벤트를 전달하여 종료되도록 구성할 수 있습니다.

이러한 과정을 이벤트 주입이라고 하며 다음 세 가지 VM-entry control fields 에 의해 제어됩니다.

  • VM-entry interruption-information field(32 bits)
    • 주입 할 이벤트에 대한 세부 정보를 제공합니다.
typedef struct _VMX_VMENTRY_INTERRUPT_INFORMATION
{
	union
	{
		ULONG64 Features;
		struct
		{
			/*
			* Vector of interrupt or exception
			*/
			ULONG64 Vector : 8;              // 00-07
			/*
			* Interruption type:
			* 0: External interrupt
			* 1: Reserved
			* 2: Non-maskable interrupt (NMI)
			* 3: Hardware exception (e.g,. #PF)
			* 4: Software interrupt (INT n)
			* 5: Privileged software exception (INT1)
			* 6: Software exception (INT3 or INTO)
			* 7: Other event
			*/
			ULONG64 InterruptType : 3;       // 08-10
			/*
			*  Deliver error code (0 = do not deliver; 1 = deliver)
			*/
			ULONG64 DeliverErrorCode : 1;    // 11
			ULONG64 Reserved_1 : 19;         // 12-30
			ULONG64 Valid : 1;               // 31
			/*
			* It's actually 32 bits, but for unity, it's aligned to 64 bits.
			*/
			ULONG64 Reserved_2 : 32;         // 32-63
		}Fields;
	};
}VMX_VMENTRY_INTERRUPT_INFORMATION, * PVMX_VMENTRY_INTERRUPT_INFORMATION;
  • VM-entry exception error code(32 bits)
    • 이 필드는 interruption information 필드 내 Valid 비트와 delivererror-code 비트가 모두 설정된 경우에만 사용됩니다.
  • VM-entry instruction length(32 bits)
    • 인터럽트, 예외 유형의 이벤트 주입인 경우 이 필드는 스택에 푸시되는 RIP 값을 결정하는데 사용됩니다.

VM ExitVM-entry interruption-information 필드에서 Valid 비트를 지웁니다.

[0x07] VM-Exit Information Fields

해당 필드는 가장 최근의 VM Exit 가 발생한 것에 대한 정보가 포함된 필드 입니다. 일부 프로세서에서는 VMWRITE 를 이용하여 이러한 필드에 쓰기를 시도하는 경우 실패합니다.

[-] Basic VM-Exit Information

다음의 VM-exit information 필드는 VM Exit 에 대한 기본 정보를 제공합니다.

  • Exit Reason(32 bits)
    • 이 필드는 VM Exit 이유를 인코딩하며, 아래의 구조로 구성되어 있습니다.

      typedef struct _VMX_VMEXIT_REASON
      {
      	union
      	{
      		ULONG Features;
      		struct
      		{
      			/*
      			* Basic Exit Reason
      			*/
      			ULONG BasicExitReason : 16;              // 00-15
      			/*
      			* Always cleared to 0
      			*/
      			ULONG AlwaysZero : 1;                    // 16
      			ULONG Reserved_1 : 10;                   // 17-26
      			/*
      			* A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode
      			*/
      			ULONG bEnclaveMOde : 1;                  // 27
      			/*
      			* Pending MTF VM exit
      			*/
      			ULONG PendingMTF : 1;                    // 28
      			/*
      			* VM exit from VMX root operation
      			*/
      			ULONG ExitFromRootOperation : 1;         // 29
      			ULONG Reserved_2 : 1;                    // 30
      			/*
      			* VM-entry failure (0 = true VM exit; 1 = VM-entry failure)
      			*/
      			ULONG VMEntryFailure : 1;                // 31
      		}Fields;
      	};
      }VMX_VMEXIT_REASON, * PVMX_VMEXIT_REASON;
    
  • Exit qualification(64 bits or 32 bits)
    • 이 필드에는 다음으로 인한 VM Exit 원인에 대한 추가 정보가 포함됩니다. 필드의 형식은 원인에 따라 다릅니다.
      debug exceptions
      page-fault exceptions
      startup IPIs(SIPIs)
      task switchs
      INVEPT, INVLPG, INVVPID
      LGDT, LIDT, LLDT, LTR, SGDT, SIDT, SLDT, STR
      VMCLEAR, VMPTRLD, VMPTRST, VMREAD, VMWRITE, VMXON
      XRSTORS, XSAVES
      Control Register Accesses
      MOV DR
      I/O Instruction
      MWAIT
    
  • Guest-linear address(64 bits or 32 bits)
    • 이 필드는 아래의 경우에 사용됩니다.
      • LMSW 을 메모리 피연산자와 사용하여 VM Exit 가 발생한 경우
      • INS 또는 OUTS 실행 시도로 인해 VM Exit 가 발생한 경우
      • I/O 명령어가 폐기된 이후에 도착한 SMI(System Management Interrupt) 로 인해 VM Exit 가 발생한 경우
      • EPT Violation 으로 인한 VM Exit 발생
  • Guest-physical address(64 bits)
    • 이 필드는 EPT ViolationEPT Misconfiguration 으로 인해 VM Exit 가 발생하는 경우 사용됩니다.

[-] Information for VM Exits Due to Vectored Events

벡터 이벤트로 인해 VM Exit 에 대한 이벤트별 다음과 같은 정보가 제공됩니다.

Exceptions(INT3, INT0, INT1, BOUND, UD0, UD1, UD2 포함)
VM-Exit Control 내 "acknowledge interrupt on exit" 비트가 1인 동안 발생하는 외부 인터럽트
Non-maskable 인터럽트(NMIs)
  • VM-exit interruption information(32 bits)
    • 이 필드는 VM Exit 를 발생시키는 이벤트와 관련된 기본 정보를 수신합니다.

      typedef struct _VMX_VMEXIT_INTERRUPT_INFORMATION
      {
      	union 
      	{
      		ULONG64 Features;
      		struct
      		{
      			/*
      			* Vector of interrupt or exception
      			*/
      			ULONG64 Vector : 8;              // 00-07
      			/*
      			* Interruption type:
      			* 0: External interrupt
      			* 1: Not used
      			* 2: Non-maskable interrupt (NMI)
      			* 3: Hardware exception 
      			* 4: Software interrupt 
      			* 5: Privileged software exception 
      			* 6: Software exception
      			* 7: Other event
      			*/
      			ULONG64 InterruptType : 3;       // 08-10
      			/*
      			*  Error code valid (0 = invalid; 1 = valid)
      			*/
      			ULONG64 ErrorCode : 1;           // 11
      			/*
      			* NMI unblocking due to IRET
      			*/
      			ULONG64 UnblockNMI_IRET : 1;     // 12
      			ULONG64 Reserved_1 : 19;         // 13-30
      			ULONG64 Valid : 1;               // 31
      			/*
      			* It's actually 32 bits, but for unity, it's aligned to 64 bits.
      			*/
      			ULONG64 Reserved_2 : 32;         // 32-63
      		}Fields;
      	};
      }VMX_VMEXIT_INTERRUPT_INFORMATION, * PVMX_VMEXIT_INTERRUPT_INFORMATION;
    
  • VM-exit interruption error code(32 bits)
    • 스택에 오류 코드를 전달했을 때 하드웨어 예외로 인한 VM Exit 일 경우 이 필드는 해당 오류 코드를 수신합니다.

[-] Information for VM Exits That Occur During Event Delivery

VMX Non-root operation 에서 이벤트 전달 중 발생하는 VM Exit 에 대한 추가 정보를 제공합니다. 이 정보는 다음 필드를 통해 전달됩니다.

  • IDT-vectoring information(32 bits)
    • 이 필드는 VM Exit 가 발생할 때 전달되고 있던 이벤트와 관련된 기본 정보를 수신합니다. 대부분의 인터럽트 정보는 유사합니다.

  • IDT-vectoring error code(32 bits)
    • 스택에 오류 코드를 전달했을 때 하드웨어 예외 전달 중에 발생하는 VM Exit 의 경우 이 필드는 해당 오류 코드를 수신합니다.

[-] Information for VM Exits Due to Instruction Execution

다음 필드는 VMX Non-root operation 에서 특정 명령을 실행하려는 시도로 인해 VM Exit 가 발생하는 경우에 사용 되는 정보 입니다.

  • VM-exit instruction length(32 bits)
    • 특정 명령 실행으로 인한 VM Exit 발생의 경우 이 필드는 VM Exit 로 이어진 명령어의 길이를 바이트 단위로 수신합니다.
  • VM-exit instruction information(32 bits)
    • 이 필드는 아래의 명령 실행 시도로 인한 VM Exit 발생 시 사용됩니다.
      INS, OUTS
      INVEPT, INVVPID
      LIDT, LGDT, LLDT, LTR
      SIDT, SGDT, SLDT, STR
      VMCLEAR, VMPTRLD, VMPTRSR, VMREAD, VMWRITE, VMXON
    
  • I/O RCX, RSI, RDI, RIP(each 64 bits)
    • 각 64bit인 해당 필드들은 I/O 명령 폐기 이후 도착하는 SMI 로 인해 VM Exit 가 발생한 경우 사용됩니다.
    • I/O 명령이 시작 되기 전의 RCX, RSI, RDI, RIP(I/O 명령을 처리한 RIP) 값입니다.

[-] VM-Instruction Error Fields

32bit 로 이루어진 이 필드는 가장 최근에 발생한 VM Exit 에 대한 정보를 제공하지 않습니다. 대신 VMX 명령 중 하나를 오류 없이 실행할 때 발생하는 오류에 대한 정보를 제공합니다.

[0x08] VMCS Types : Ordinary and Shadow

모든 VMCS 는 일반적인 VMCSShadow VMCS 로 나눠집니다. VMCS TypeVMCS Regionshadow-VMCS indicator 필드(VMCS Region 내 bit 31) 값에 의해 결정 됩니다.

해당 값이 0인 경우 Ordinary VMCS 이고, 1인 경우 Shadow VMCS 를 나타냅니다.

Shadow VMCSVMCS Shadowing 필드(IA32_VMX_PROCBASED_CTLS2 내 bit 14) 값을 1로 설정을 지원하는 프로세서 에서만 지원됩니다.

Shadow VMCSOrdinary VMCS 와 두 가지 면에서 다릅니다.

  1. Ordinary VMCSVM Entry 를 사용할 수 있지만 Shadow VMCS 는 사용할 수 없습니다. 현재 VMCSShadow VMCS 일 때 VM Entry 를 시도하면 실패합니다.
  2. VMREAD, VMWRITE 명령어는 VMX Non-root operation 에서 Shadow VMCS 에 접근하기 위해 사용할 수 있지만 Ordinary VMCS 에는 접근할 수 없습니다. 이는 아래와 같은 이유 때문입니다.
    1. 만약 VMCS shadowing 비트가 0인 경우, VMX Non-root operation 에서 VMREAD, VMWRITE 명령을 실행하면 항상 VM Exit 가 발생합니다.
    2. 만약 VMCS shadowing 비트가 1인 경우, VMX Non-root operation 에서 VMREAD, VMWRITE 명령을 실행하면 VMCS Link Pointer 가 참조하는 VMCS 에 접근할 수 있습니다.
    3. 만약 VMCS shadowing 비트가 1인 경우, VM EntryVMCS Link Pointer 가 참조하는 모든 VMCSShadow VMCS 임을 보장합니다.

VMX Root operation 에서 VMREAD, VMWRITE 명령어를 사용하여 두 가지 유형의 VMCS 에 모두 액세스 할 수 있습니다.

VMMActive 상태의 VMCSVMCS Region 에 있는 shadow-VMCS indicator 를 수정해서는 안됩니다. 그렇게 되면 VMCS 가 손상될 수 있습니다.

shadow-VMCS indicator 를 수정하기 전에 VMMVMCS 의 활성 여부에 대해 확인하기 위해 VMCLEAR 를 실행해야 합니다.

[0x09] Remarks

매우 많은 내용의 VMCS Data 에 대해 알아보았습니다. 실제로 구현에 따라 사용되지 않는 데이터도 매우 많을 것으로 보입니다.

우선 위의 내용들을 토대로 프로그래밍을 하기 전에, 마지막으로 관련된 데이터를 사용할 때 VMM 이 준수해야 하는 여러가지 지침에 대해 알아보겠습니다.

기본적으로 VMCS 활성화 여부에 대한 지침이 존재합니다. 이는 이전 챕터에서도 작성하였기 때문에 넘어가겠습니다.

[-] VMREAD, VMWRITE, and Encodings of VMCS Fields

VMCS 의 모든 필드는 32 bit의 값의 인코딩 값과 연관되어 있습니다. VMM 은 해당 필드를 읽거나 쓰기를 원할 때 VMREAD, VMWRITE 명령에 대한 피연산자로 인코딩 된 값을 제공해야 합니다.

이러한 명령어는 64bit 모드에서 인코딩 비트를 bit 32 이상으로 설정하여 전달하면 실패합니다.

VMCS 구성요서의 32bit 인코딩 구조는 주로 VMCS 에서 너비와 기능에 따라 결정됩니다.

typedef struct _VMCS_COMPONENT_ENCODING
{
	union 
	{
		ULONG Features;
		struct
		{
			/*
			*  Access type (0 = full; 1 = high); must be full for 16-bit, 32-bit, and natural-width fields
			*/
			ULONG AccessType : 1;          // 00
			/*
			*  Index
			*/
			ULONG Index : 9;               // 01-09
			/*
			* Type: 
			* 0: control
			* 1: VM-exit information
			* 2: guest state
			* 3: host state
			*/
			ULONG Type : 2;                // 10-11
			ULONG Reserved_1 : 1;          // 12
			/*
			* Width: 
			* 0: 16-bit
			* 1: 64-bit
			* 2: 32-bit
			* 3: natural-width
			*/
			ULONG Width : 2;               // 13-14
			ULONG Reserved_2 : 17;         // 15-31
		}Fields;
	};
}VMCS_COMPONENT_ENCODING, * PVMCS_COMPONENT_ENCODING;

각 필드에 대한 자세한 설명은 아래와 같습니다.

  • Field Width(bits 14:13)
    • 필드의 너비를 나타냅니다. nature-width 는 프로세서에 따라 64bit or 32 bits 인 필드입니다.
  • Field Type(bits 11:10)
    • VMX Control, VM-Exit information, Guest-State, Host-State 으로 선택할 수 있습니다.
  • Index(Bits 9:1)
    • 필드 너비와 유형이 동일한 구성 요소를 구별합니다.

때문에 지금까지 학습한 VMCS Data 들에 필드들에 크기에 대한 내용이 필수적으로 있었던 것 입니다.

이어지는 내용에서는 원하는 필드의 값에 대해 VMREAD, VMWRITE 를 하기 위해 사용되는 인코딩 된 값을 확인할 수 있습니다.

예를 들어 GuestCR4 를 읽는다고 가정해보겠습니다.

  1. 먼저 Guest State 에서 정보를 읽어야 하기 때문에 bit 11 이 1으로 설정됩니다.
  2. CR4 의 경우 32 bit가 될 수도 있고 64 bit가 될 수 있기 때문에 nature width 로 설정해야 합니다. bit14:13 은 모두 1로 설정됩니다.
  3. 여기서 인덱스를 찾아야 하는데 이 부분은 Intel SDM 에 문서화가 잘되어 있습니다.(Appendix B Field Encoding in VMCS)
  4. Guest CR4 의 인덱스 값은 0000’0010b 로 값이 4입니다.

위의 과정을 거치면 명령에 전달되는 인코딩 값은 0x6804h 가 됩니다.

[-] Initializing a VMCS

VMMVM EntryVMCS 를 사용하기 전에 VMCS 의 필드를 초기화 해야 합니다. (VMWRITE 사용)

논리 프로세서가 사용하지 않을 필드를 초기화할 필요는 업습니다. 예를 들어 use MSR bitmaps 필드가 0인 경우 VM-execution control 필드에 포함되어 있는 MSR-bitmap address 를 초기화할 필요가 없습니다.

프로세서는 VMWRITE 로 수정 불가능한 일부 VMCS 정보에 대해 유지하고 관리합니다. 여기에는 VMCSLaunch State 가 포함됩니다.

이러한 정보는 VMCS RegionVMCS Data 부분에 저장될 수 있습니다. 이 정보의 포맷은 구현에 따라 다르기 때문에 VMMVMCS Region 으로 사용할 메모리 영역을 처음 할당 할 때 프로세서가 메모리 영역의 내용에서 이 정보를 결정하는 방법을 알 수 있는 방법이 없습니다.

추가적으로 다른 기능 외에도 VMCLEAR 명령어는 피연산자가 참조하는 VMCS Region 의 구현 관련 정보를 초기화 합니다. 구현별 동작의 불확실성을 피하기 위해 VMM은 처음으로 VMPTRLD와 함께 해당 VMCS 를 활성화하기 전에 VMCS Region 에서 VMCLEAR 를 실행해야 합니다.

  • VMCLEAR → VMPTRLD

아래의 VMM 사용법은 이러한 제한 사항과 일치합니다.

  • VMCLEAR 는 처음 VM Entry 로 전환되기 전에 VMCS 에 대해 실행되어야 합니다.
  • VMLAUNCH 는 해당 VMCS 에 대해 VMCLEAR 가 실행된 후 VMCS를 사용하는 첫 번째 VM Entry 에 사용해야 합니다.
  • VMRESUMEVMCS 를 사용하는 모든 후속 VM Entry 에 사용해야 합니다.(VMCS에 대해 VMCLEAR 가 실행될 때 까지)

[0x0A] Conclusion

이로써 VMCS Data 에 대한 내용을 모두 살펴봤습니다.

실제로 Intel SDM 을 정독하며 알게 된 내용이 매우 많았습니다. 목표로 하는 바는 하이퍼바이저를 만드는 것 입니다. 여러 튜토리얼들과 오픈소스를 참조하였으나, 이해가 되지 않는 부분이 많았습니다.

매우 많은 양에 겁 먹을 필요 없습니다. 꽤 많은 오픈소스가 존재하고 이를 이용하여 비교하며 중요한 내용에 대해 이해하면 됩니다.

[0x0B] Reference

  1. Intel 64 and IA-32 Architectures Software Developer’s Manual
  2. Hypervisor From Scratch
  3. Tandasat DdiMon
  4. Gbps Gbhv