VM Exits -2-

[0x00] Concept

VM Exits -1- 파트에 이어서 작성됩니다.

왜 여러가지 상태나 레지스터들을 저장하고 로드하는가 대해서 설명하는가를 이해하는 것이 좋습니다.(참고 : 링크)

  • Guest-State Area(게스트 상태 영역)
    • VM Exit : 프로세서의 상태를 저장
    • VM Entry : 프로세서의 상태(저장된 상태)를 로드
  • Host-State Area(호스트 상태 영역)
    • VM Exit : 프로세서의 상태(저장된 상태)를 로드
  • VMM 은 게스트 소프트웨어의 실행 시점을 직접 제어할 수 있습니다. 그 말은 실행 전에 호스트 상태 영역을 설정할 수 있다는 의미입니다.
  • VM Entry, Exit 가 발생할 때의 저장과 로드와는 별개의 의미로 VMM 에서 미리 설정을 하기 때문에(VM Entry 가 실패하는 경우 돌아올 RIP 저장 등) 필요하지 않은 것으로 이해했습니다.

[0x01] Saving Guest State

위에서 설명한 것과 같이 VM Exit 는 프로세서 상태의 특정 구성 요소들을 VMCS 의 게스트 상태 영역에 있는 필드에 저장합니다.

Intel 64 아키텍처를 지원하는 프로세서는 natural-width field(아키텍처에 따라 가변적인 필드) 에 해당하는 필드의 값은 VM Exit 전, 후의 프로세서 모드에 관계없이 저장됩니다.

[-] Saving Control Registers, Debug Registers, and MSRs

특정 Control Register, Debug Register, MSRGuest Register State 에 포함되며 아래와 같이 저장됩니다.

  • CR0, CR3, CR4, IA32_SYSENTER_CS, IA32_SYSENTER_ESP, EIP MSR 의 내용이 게스트 상태 영역에 저장됩니다.
  • IA32_SYSENTER_CS MSR 의 bits 63:32 는 저장되지 않으며, Intel 64 아키텍처를 지원하지 않는 경우 IA32_SYSENTER_ESP, EIP 의 bits 63:32 는 저장되지 않습니다.
  • VMExit_save debug controls 제어 비트가 1이면 DR7 의 값과 IA32_DEBUGCTL MSR 이 해당 필드에 저장됩니다.
  • VMExit_save IA32_PAT 제어 비트가 1이면 IA32_PAT MSR 의 내용이 필드에 저장됩니다.
  • VMExit_save IA32_EFER 제어 비트가 1이면 IA32_EFER MSR 의 내용이 필드에 저장됩니다.
  • VMEntry_load IA32_BNDCFGS 제어가 1로 설정 가능한 경우, 또는 VMExit_clear IA32_BNDCFGS 제어가 1으로의 설정을 지원하는 경우 IA32_BNDCFGS MSR 의 내용이 필드에 저장됩니다.
  • VMEntry_load IA32_RTIT_CTL제어가 1로 설정 가능한 경우, 또는 VMExit_clear IA32_RTIT_CTL제어가 1으로의 설정을 지원하는 경우 IA32_RTIT_CTL MSR 의 내용이 필드에 저장됩니다.
  • VMEntry_load CET제어가 1로 설정을 지원하는 경우 IA32_S_CET, IA32_INTERRUPT_SSP_TABLE_ADDR MSR 의 내용이 필드에 저장됩니다.
  • VMEntry_load guest IA32_LBR_CTL제어가 1로 설정 가능한 경우, 또는 VMExit_clear IA32_LBR_CTL제어가 1으로의 설정을 지원하는 경우 IA32_LBR_CTL MSR 의 내용이 필드에 저장됩니다.
  • VMEntry_load PKRS 제어가 1로 설정 가능한 경우 IA32_PKRS MSR 의 내용이 필드에 저장됩니다.
  • VMExit_save IA32_PERF_GLOBAL_CTL 제어 비트가 1이면 IA32_PERF_GLOBAL_CTL MSR 의 내용이 필드에 저장됩니다.
  • SMBASE 필드의 값은 SMM VM Exit 를 제외한 모든 VM Exit 후에 정의되지 않습니다.

[-] Saving Segment Registers and Descriptor-Table Registers

각 세그먼트 레지스터(CS, SS, DS, ES, FS, GS, LDTR, TR)에 대해 Base-Address, Segment-Limit, Access-Right 에 대해 저장되는 값은 각 레지스터가 VM Exit 발생하기 전에 Access-Right 필드의 bit 16(unusable)에 따라 결정됩니다.

  • 레지스터가 unusable 인 경우 Base-Address, Segment-Limit 필드와 Access-Right 필드의 bits 7:0, bits 15:12 값은 정의되지 않습니다. 다만 다음의 레지스터의 경우 예외가 존재합니다.
    • CS 의 경우 BaseAddress, Segment-Limit 필드가 저장됩니다. 또한 Access-Right 필드의 bits 15:13(L, D, G) 값이 저장됩니다.
    • SS 의 경우 Access-Right 필드의 bits 6:5(DPL, Descriptor Privilege Level) 이 저장되며 Intel 64 아키텍처를 지원하는 경우 Base-Address 필드에 대해 저장되는 값의 bits 63:32 는 항상 0 입니다.
    • DS, ES 의 경우 Intel 64 아키텍처를 지원하는 경우 Base Address 에 대해 저장되는 값의 bits 63:32 는 항상 0 입니다.
    • FS, GS 의 경우 Base-Address 필드를 저장합니다.
    • LDTR 의 경우 저장되는 Base Address 는 항상 정규 주소 입니다.
  • 레지스터가 unusable 이 아닌 경우, Base-Address, Segment-LimitAccess-Right 필드의 bits 7:0, bits 15:12 에 저장된 값은 VM Exit 가 발생하기 전에 레지스터에 있던 값입니다.
  • Access-Right 필드의 bits 31:17, bits 11:8은 항상 지워집니다. bit 16은 세그먼트를 사용할 수 없는 경우에만 1으로 설정됩니다.

GDTR, IDTR 레지스터의 경우 Base-Address, Segment-Limit 필드가 저장됩니다.

[-] Saving RIP, RSP, RFLAGS, and SSP

RIP, RSP, RFLAGS, SSP 레지스터의 내용은 아래와 같이 저장됩니다.

  • RIP 필드에 저장되는 값은 VM Exit 의 특성과 원인에 따라 결정됩니다.
    • Enclave 모드에서 VM Exit 가 발생한 경우 저장되는 값은 중단된 Enclave 스레드의 AEP(Asynchronous Exit Pointer) 입니다.
    • 무조건 VM Exit 가 발생하는 명령이나 VM-execution controls 를 통해 VM Exit 가 유발되는 명령을 실행하려는 시도로 인해 VM Exit 가 발생한 경우 저장된 값은 해당 명령을 참조합니다.(참조의 의미는 해당 명령이 실행된 IP 를 의미하는 것으로 보입니다.)
    • VM ExitINIT Signal, start-up IPI(SIPI), SMI 중 하나의 발생으로 인해 발생한 경우 저장되는 값은 이벤트가 발생하기 전에 RIP 값 입니다.
    • PR_interrupt-window exiting 제어 비트나 PR_NMI-window exiting 제어 비트가 1로 설정됨에 따라 VM Exit 가 발생하는 경우 저장되는 값은 VM Exit 가 발생하지 않은 경우의 RIP 값 입니다.(아마 정상적으로 실행됐을 때의 RIP 을 의미하는 것으로 보입니다.)
    • VM Exitexternal interrupt, NMI, hardware exception 으로 인한 경우 저장되는 값은 이벤트 처리에 따라 저장된 값의 반환 포인터 입니다.(trap 또는 interrupt gate 를 통해 이벤트가 전달되었다면 스택, 이벤트가 task-gate 를 통해 전달된 경우 이전 task-state segment)
    • VM ExitTriple-Fault 로 인한 경우 저장되는 값은 위의 이벤트 처리와 동일합니다.
    • VM Exitsoftware exception(INT3 또는 INTO 실행으로 인해) 또는 privileged software exception(INT1 실행으로 인해)으로 인한 경우 저장되는 값은 해당 예외를 일으킨 INT3, INTO, INT1 명령어를 참조합니다.
    • VM ExitIDT 에서 task-gate 가 발생시킨 CALL, IRET, JMP 의 실행이나 software interrupt(INT n), software exception(INT3, INTO), privileged software exception(INT 1) 으로 인해 발생한 경우, 저장되는 값은 task switch 를 발생시킨 명령을 참조합니다.(CALL, IRET, JMP, INT n, INT3, INTO, INT1)
    • VM Exitsoftware interrupt 또는 software exception 에 의한 직접 액세스를 제외하고 IDTtask-gate 로 인한 task switch 때문인 경우 저장되는 값은 정상적으로 완료됐을 때의 이전 task-statue segment 에 저장되었을 값입니다.
    • VM ExitVTPR(Virtual Task-Priority Register) 의 bits 7:4 값을 APIC Virtualization 과 연관된 VM-execution control fieldsTPR threshold 값 아래로 줄여 발생한 경우(ex. MOV to CR8) MOV to CR8 또는 WRMSR 명령을 참조합니다.
  • RSP 필드에 저장되는 값은 RSP 레지스터의 값이 저장됩니다.
  • RFLAGS 필드에는 bit 16(RF, Resume Flag)를 제외하고 RFLAGS 레지스터의 값이 저장됩니다. RFLAGS.RF 의 경우 아래와 같이 저장됩니다.
    • Enclave 모드에서 VM Exit 가 발생한 경우 저장되는 값은 0입니다.
    • VM ExitTriple-Fault 로 인해 발생한 경우 저장되는 값은 논리 프로세서가 Triple-Fault 가 발생하고 shutdown 상태로 전환된 경우 RF 에 있는 값입니다.
    • 조건 VM Exit 가 발생하는 명령이나 VM-execution controls 를 통해 VM Exit 가 유발되는 명령을 실행하려는 시도로 인해 VM Exit 가 발생한 경우 저장되는 값은 0 입니다.
    • 위의 내용과 생략한 APIC-access, task switch 등으로 인한 VM Exit 가 아닌 경우 원래의 값이 저장됩니다.
  • SSP 필드에 저장되는 값은 프로세서가 VMEntry_load CET 제어가 1 설정을 지원하는 경우에만 SSP 레지스터의 값이 저장됩니다.

[-] Saving Non-Register State

※ 참고 : 링크

Guest Non-Register State 에 저장되는 내용은 아래와 같습니다.

  • Activity-State Field 의 경우 VM Exit 전에 논리 프로세서의 Activity state 와 함께 저장됩니다.
  • Interruptibility-State FieldVM Exit 전에 논리 프로세서의 인터럽트가 발생할 가능성을 반영하기 위해 저장합니다.
  • Pending Debug Exception Field 는 다음을 제외한 모든 VM Exit 에 대해 0으로 저장됩니다.
    • INIT Signal, Machine-Check, SMI 로 인한 VM Exit 가 발생한 경우
    • Basic Exit ReasonTPR below threshold, virtualized EOI, APIC write, monitor trap flag 로 인한 VM Exit 입니다.
    • debug exception 으로 발생한 것이 아니고 debug exception 에 대한 MOV-SS 차단 중에 발생한 VM Exit 입니다.
  • Pending Debug Exception Field 가 0이 아닌 값으로 저장되는 경우의 저장되는 값에 대한 설명은 아래와 같습니다.
    • bits 3:0(B0-B3) 각각은 일치하는 중단점에 해당하는 경우 1로 설정됩니다. DR7 에서 해당 중단점이 활성화되지 않은 경우에도 마찬가지 일 수 있습니다.
    • VM ExitINIT Signal, Machine-Check, SMI 로 인해 발생했거나 Basic Exit ReasonTPR below threshold, monitor trap flag 인 경우가 있다고 가정합니다. 이러한 경우에 저장되는 값은 VM Exit 발생 시 보류 중인 debug exception 의 원인에 해당하는 비트로 설정됩니다.
      • bit 12(enable breakpoint) 는 아래의 경우에 1로 설정됩니다.
        • DR7 에서 활성화 된 일치하는 데이터 또는 I/O breakpoint 가 하나 이상 있는 경우
        • VM Entry 에 설정된 경우 유효한 보류 중인 debug exception 이 발생하고, 해당 예외가 전달되거나 손실되기 전에 VM Exit 가 발생하는 경우
        • VM Exit 직전에 XBEGIN 명령이 실행되고 RTM Transactional region 의 디버깅이 활성화 된 경우
        • 그 외의 경우에는 0으로 설정됩니다.
      • bit 14(BS) 는 다음의 경우에 해당하고 RFLAGS.TF = 1 인 경우 1로 설정됩니다.
        • IA32_DEBUGCTL.BTF= 0 이고 보류 중인 debug exception 의 원인이 Single Instruction 입니다.
        • IA32_DEBUGCTL.BTF = 1 이고 보류 중인 debug exception 의 원인이 Taken Branch 입니다.
      • bit 16(RTM)은 생략합니다. (Advanced Debugging of RTM transactional regions)
    • VM Exitdebug exception 이 아닌 다른 이유 때문이고 debug exceptionMOV-SS 차단되는 동안 발생했다고 가정합니다. 이러한 경우 저장되는 값은 VM Exit 시점에 보류 중인 debug exception 의 원인에 해당하는 비트를 설정합니다. VM Entry 직후에 VM Exit 가 발생하는 경우(VMX non-root operation 에서 실행된 명령이 없는 상태) 저장되는 값은 VM Entry 에 로드된 값과 일치할 수 있습니다.
  • VMExit_save VMX-preemption timer value 제어 비트가 1인 경우 타이머 값은 VMX-preemption timer-value field 에 저장됩니다. 이것은 VM Entry 에서 이 필드에서 로드된 이후부터 줄어듭니다. 타이머 만료로 인해 VM Exit 가 발생하면 0을 저장합니다.
  • 논리 프로세서가 Second_enable EPT 의 1로 설정을 지원하는 경우 값은 아래와 같이 4개의 PDPTE 필드에 저장됩니다.
    • Second_enable EPT 제어 비트가 1이고 논리 프로세서가 VM ExitPAE paging 을 사용 중이면 현재 사용 중인 PDPTE 의 값이 저장됩니다.

      • 각 필드(4개의 필드)의 bits 11:9는 정의되지 않았습니다.
      • 각 필드 중 하나의 필드에 저장된 값의 bit 0(present)이 0으로 설정된 경우 해당 필드의 bits 63:1 은 정의되지 않습니다. 이 값은 VM Entry 에 의해 로드된 값 또는 VMX non-root operation 에서 로드되었을 수 있는 값과 일치하지 않아도 됩니다.
      • 각 필드 중 하나의 필드에 저장된 값의 bit 0(present)이 1으로 설정된 경우 bits 63:12 에 저장된 값은 게스트 물리 주소 입니다.
    • Second_enable EPT 제어가 0이거나 PAE paging 을 사용하지 않는 경우 저장되는 값은 정의되지 않습니다.

[0x02] Saving MSRs

프로세서 상태가 게스트 상태 영역에 저장된 후 MSR 값은 VM-exit MSR-store area 에 저장될 수 있습니다.

특히 해당 영역의 각 엔트리(VM-exit MSR-store count 에 지정된 수 까지)는 bits31:0(RDMSR 을 통해 읽음)으로 인덱싱된 MSR 값을 비트에 저장하여 순서대로 처리됩니다. 아래와 같은 경우 처리가 실패합니다.

  • bits 31:8 의 값이 8이며 이는 Local APICx2APIC mode 에 있을 때 인덱싱된 MSRAPIC register 에 대한 접근을 허용하는 값을 의미합니다.
  • bits 31:0의 값은 SMM 에서만 읽을 수 있는 MSR 으로 표시되어 있고, VM ExitSMM 에서 발생하지 않습니다.(IA32_SMBASE MSRSMM 에서만 읽을 수 있습니다.)
  • bits 31:0의 값은 모델별 이유로 VM Exit 에 저장할 수 없는 MSR 으로 표시되어 있습니다. 프로세서는 RDMSR 에서 정상적으로 읽을 수 있는 경우에도 특정 MSR(bits 31:0 기반)이 VM Exit 발생 시 저장되는 것을 방지할 수 있습니다.
  • 엔트리의 bits 63:32 는 0이 아닌 값입니다.
  • bits 31:0 으로 인덱싱된 MSR 을 읽으려는 시도는 CPL = 0 상태에서 RDMSR 을 통해 실행되는 Genral-Protection Exception 을 발생 시킵니다.

해당 항목에 대한 처리가 실패하면 VMX Abort 가 발생됩니다.

[0x03] Loading Host State

프로세서의 상태는 VM Exit 에서 다음과 같은 방식으로 업데이트 합니다.

  • 일부 상태는 호스트 상태 영역에서 로드되거나 결정됩니다.
  • 일부 상태는 VM-exit controls 에 의해 결정됩니다.
  • 일부 상태는 모든 VM Exit 에서 동일한 방식으로 설정됩니다.
  • Page-Directory Pointer 는 특정 Control Register 의 값을 기반으로 로드됩니다.

이러한 로딩의 순서는 임의의 순서로 진행됩니다.

Intel 64 아키텍처를 지원하는 프로세서에서 로드된 각 64 bits 필드의 전체 값(ex. GDTRBase Address)은 VM Exit 전후의 논리 프로세서 모드와 관계없이 로드됩니다.

별도의 언급이 없는 이상 ~ 에서 로드되는 필드는 호스트 상태 영역을 의미합니다.

[-] Loading Host Control Registers, Debug Registers, MSRs

VM ExitControl Register, Debug Register, 일부 MSR 에 대한 새로운 값을 로드합니다.

  • CR0, CR3, CR4 는 아래의 경우를 제외하고 각 필드에서 로드됩니다.
    • 아래의 경우에 비트는 수정되지 않습니다.
      • CR0, ET, CD, NW 의 경우 bits 63:32, bits 28:19, bit 17, bits 15:6 및 VMX Operation 에서 고정된 모든 비트
      • CR3 의 경우 프로세서의 물리 주소 너비를 초과하는 비트 bits 63:52 및 bits 51:32 범위의 비트(0으로 지워짐)
      • CR4 의 경우 VMX Operation 에서 고정된 모든 비트
    • CR4.PAEVMExit_host address-space size 제어가 1인 경우 1로 설정됩니다.
    • CR4.PCIDEVMExit_host address-space size 제어가 0인 경우 0으로 설정됩니다.
    • DR70400h 로 설정됩니다.
  • MSR 의 경우 아래와 같이 설정됩니다.
    • IA32_DEBUGCTL MSR 은 0으로 지워집니다.
    • IA32_SYSENTER_CS MSRIA32_SYSENTER_CS 필드에서 로드됩니다. 해당 필드에는 32bits 만 존재하므로 bits 63:32 는 0으로 지워집니다.
    • IA32_SYSENTER_ESP, EIP MSRIA32_SYSENTER_ESP, EIP 에서 로드됩니다.
    • 다음 내용은 Intel 64 아키텍처를 지원하는 프로세서에서 수행됩니다.
      • FS, GS.base MSR 은 각 FS, GS 에 대한 Base-Address 필드에서 로드됩니다.
      • IA32_EFER MSRLMA, LME 비트는 VMExit_host address-space size 제어 설정으로 로드됩니다.
    • VMExit_load IA32_PERF_GLOBAL_CTRL 제어가 1이면 IA32_PERF_GLOBAL_CTRL MSRIA32_PERF_GLOBAL_CTRL 필드에서 로드됩니다. 예약된 비트의 값은 유지됩니다.
    • VMExit_load IA32_PAT 제어가 1이면 IA32_PAT MSRIA32_PAT 필드에서 로드됩니다. 예약된 비트의 값은 유지됩니다.
    • VMExit_load IA32_EFER 제어가 1이면 IA32_EFER MSRIA32_EFER 필드에서 로드됩니다. 예약된 비트의 값은 유지됩니다.
    • VMExit_clear IA32_BNDCFGS 제어가 1이면 IA32_BNDCFGS MSR 은 0으로 지워집니다. 그렇지 않으면 수정되지 않습니다.
    • VMExit_clear IA32_RTIT_CTL제어가 1이면 IA32_RTIT_CTL MSR 은 0으로 지워집니다. 그렇지 않으면 수정되지 않습니다.
    • VMExit_load CET 제어가 1이면 IA32_S_CET MSR, IA32_INTERRUPT_SSP_TABLE_ADDR MSR 이 각각 IA32_S_CET, IA32_INTERRUPT_SSP_TABLE_ADDR 필드에서 로드됩니다.
    • VMExit_load PKRS 제어가 1이면 IA32_PKRS MSRIA32_PKRS 필드에서 로드됩니다.

[-] Loading Host Segment and Descriptor-Table Registers

각 레지스터 CS, SS, DS, ES, FS, GS, TR 은 다음과 같이 로드됩니다.

  • SelectorSelector 필드에서 로드됩니다. Selector 가 0으로 로드되면 세그먼트는 unusable 속성이 됩니다. SSIntel 64 아키텍처를 지원하는 프로세서에서만 0으로 로드할 수 있으며 VM Exit 가 64-bit 모드인 경우에만 로드할 수 있습니다.
  • Base Address 는 아래와 같이 설정됩니다.
    • CS 의 경우 0으로 지워집니다.
    • SS, DS, ES 의 경우 unusable 상태이면 정의되지 않습니다. 그렇지 않으면 0으로 지워집니다.
    • FS, GS 의 경우 unusable 상태이고 VM Exit 가 64-bit 모드가 아니면 정의되지 않습니다. 그렇지 않으면 Base-Address 필드에서 로드됩니다.
    • TR 의 경우 호스트 상태 영역에서 로드됩니다.
  • Segment Limit 은 아래와 같이 설정됩니다.
    • CS 의 경우 FFFFFFFFh 으로 설정됩니다.
    • SS, DS, ES, GS 의 경우 unusable 상태이면 정의되지 않습니다. 그 외에는 FFFFFFFFh 으로 설정됩니다.
    • TR 의 경우 00000067h 으로 설정됩니다.
  • Segment Type, S(Descriptor Type) 은 아래와 같이 설정됩니다.(Access-Right Field)
    • CS 의 경우 S 는 1으로 설정되고, Segment Type 의 경우 11(execute/read, accessed, non-conforming code segment)으로 설정됩니다.
    • SS, DS, ES, FS, GS 의 경우 unusable 상태이면 정의되지 않습니다. 그렇지 않으면 S 는 1으로 설정되고 Segment Type 은 3으로 설정됩니다.(read/write, accessed, expand-up data segment)
    • TR 의 경우 S 는 0(system)으로 설정되고 Segment Type 은 11(busy 32-bit TSS)으로 설정됩니다.
  • DPL 은 아래와 같이 설정됩니다.(Access-Right Field)
    • CS, SS, TR 의 경우 0으로 설정됩니다. VM Exit 가 완료된 후에 CPL 은 0이 됩니다.
    • DS, ES, FS, GS 의 경우 unusable 상태이면 정의되지 않습니다. 그렇지 않으면 0으로 설정됩니다.
  • P(Segment Present) 는 아래와 같이 설정됩니다.(Access-Right Field)
    • CS,TR 의 경우 1로 설정됩니다.
    • SS, DS, ES, FS, GS 의 경우 unusable 이면 정의되지 않습니다. 그렇지 않으면 1으로 설정됩니다.
  • L(64-bit mode active) 은 아래와 같이 설정됩니다.(Access-Right Field), 부가 설명을 하면 bit 13인 해당 비트는 오직 CS 에서만 기능이 존재하며 그 외에는 예약된 비트로 사용됩니다.
    • VMExit_host address-space size 제어 비트로 로드됩니다. 이 제어의 값이 IA32_EFER.LMA 에도 로드되기 때문에 VM Exit 는 호환성 모드(IA32_EFER.LMA = 1, CS.L = 0 이 필요함)로 전환되지 않습니다.
  • D/B(Default operation size) 의 경우 아래와 같이 설정됩니다.(Access-Right Field)
    • CS 의 경우 VMExit_host address-space size 제어 값의 역으로(inverse) 로드됩니다. 예를 들어 host address-space size가 0이면 32-bit 게스트를 나타내며, 이러한 경우 CS.D/B = 1 으로 설정됩니다.
    • SS 의 경우 1로 설정됩니다.
    • DS, ES, FS, GS 의 경우 unusable 이면 정의되지 않습니다. 그렇지 않으면 1으로 설정됩니다.
    • TR 의 경우 0으로 설정됩니다.
  • G(Granularity) 의 경우 아래와 같이 설정됩니다.(Access-Right Field)
    • CS 의 경우 1로 설정됩니다.
    • SS, DS, ES, FS, GS 의 경우 unusable 이면 정의되지 않습니다. 그렇지 않으면 1로 설정됩니다.
    • TR 의 경우 0으로 설정됩니다.

호스트 상태 영역에는 LDTR 에 대한 Selector 필드가 없습니다. LDTR 은 모든 VM Exit 에서 다음과 같이 설정됩니다.

  • Selector0000h 로 지워지고 세그먼트는 unusable 상태로 표시되며 그렇지 않으면 정의되지 않습니다.

GDTR, IDTR 에 대한 Base address 는 각각의 Base-Address 필드에서 로드됩니다.

[-] Loading Host RIP, RSP, RFLAGS, and SSP

RIP, RSP 는 각각의 필드에서 로드됩니다. RFLAGS 는 항상 설정되는 bit 1 을 제외하고 모두 지워집니다.

VMExit_load CET 제어가 1인 경우 SSPSSP 필드에서 로드됩니다.

[-] Checking and Loading Host Page-Directory-Pointer-Table Entries

CR0.PG = 1, CR4.PAE = 1, IA32_EFER_LMA = 0 의 조건이 성립하면 논리 프로세서는 PAE Paging 을 사용합니다.

PAE Paging 이 사용 중일 때 CR3 의 물리 주소는 PDPTE 테이블을 참조합니다. 또한 MOV to CR3PDPTE 의 유효성을 검사하고 유효한 경우 프로세서로 로드합니다.

VM Exit 는 아래와 같은 경우 PAE Paging 을 사용하는 VMM 에 대한 것 입니다.

  1. CR4.PAEVMCS 의 호스트 상태 영역에 설정되어 있는 경우
  2. VMExit_host address-space size 제어가 0인 경우

이러한 VM ExitVMCS 의 호스트 상태 영역에서 CR3 필드가 참조하는 PDPTE 의 유효성을 확인할 수 있습니다.

또한 VM Exit 발생 전에 PAE Paging 이 사용되지 않았거나 VM Exit 의 결과로 CR3 값이 변경되는 경우 유효성을 확인해야 합니다.

PAE Paging 을 사용하지 않는 VMM 에 대한 VM ExitPDPTE 의 유효성 검사를 해서는 안 됩니다.

PAE Paging 이 사용 중일 때 CR3MOV to CR3 로 인해 로드되는 것과 동일하게 PDPTE 의 유효성을 검사해야 합니다. MOV to CR3 이 로드되는 PDPTE 로 인해 General-Protection Exception(#GP) 가 발생하는 경우(ex. 예약된 비트를 설정) VMX Abort 가 발생합니다.

PAE Paging 을 사용하는 VMM 에 대한 VM ExitVMX Abort 를 발생시키지 않는 경우, VM Exit 에 의해 로드되는 CR3 값을 사용하여 MOV to CR3 와 같이 PDPTE 가 로드됩니다.

[-] Updating Non-Register State

VM Exit 는 다음과 같이 프로세서의 Non-Register State 에 영향을 미칩니다.

  • 논리 프로세서는 VM Exit 후 항상 active 상태 입니다.
  • 이벤트 차단은 아래와 같이 영향을 받습니다.
    • VM ExitSTI 또는 MOV SS 에 의한 차단이 없습니다.(blocking by STI, MOV SS)
    • NMI 로 인해 VM Exit 가 직접 종료되면 blocking by NMI 가 발생합니다. 다른 VM Exit 는 영향을 미치지 않습니다.
    • VM Exit 후 보류 중인 debug exception 은 없습니다.

추후에 자세히 설명될 내용에서는 VMX 아키텍처 논리 프로세서의 TLBPaging-Structure Cache 정보를 관리하고 제어하는 방법을 설명하게 됩니다. 먼저 다음 항목은 VM Exit 가 캐시된 매핑을 무효화하는 방법을 자세히 설명합니다.

  • Second_enable VPID 제어 비트가 0인 경우 논리 프로세서는 VPID 0000h(모든 PCID에 대해)와 관련된 선형 매핑 및 결합된 매핑을 무효화 합니다. VPID 0000h 에 대한 결합된 매핑은 모든 EP4TA 값에 대해 무효화 됩니다.(EP4TAEPTP 필드의 bits 51:12)
  • 게스트 물리 매핑을 무효화 하는데 VM Exit 는 필요하지 않으며 Second_enable VPID 제어가 1인 경우 선형 매핑 또는 결합된 매핑을 무효화할 필요가 없습니다.

[-] Clearing Address-Range Monitoring

VMM  은 MONITOR  및 MWAIT 명령을 이용하여 지정된 주소 범위를 모니터링 할 수 있습니다. VM Exit 는 적용될 수 있는 모든 Address-range monitoring 을 지웁니다.

[0x04] Loading MSRs

VM ExitVM-exit MSR-load area 에서 MSR 을 로드할 수 있습니다.

해당 영역의 각 엔트리(VM-exit MSR-load count 값까지)은 WRMSR 에 의해 기록되는 bits 127:64 의 내용과 함께 bits 31:0으로 인덱싱 된 MSR 을 로드하여 순서대로 처리됩니다.

다음과 같은 경우 처리가 실패합니다.

  • bits 31:0 의 값이 C00000100h(IA32_FS_BASE MSR) 또는 C0000101h(IA32_GS_BASE MSR) 입니다.
  • bits 31:8 의 값이 000008h 이며, 이는 로컬 APICx2APIC mode 에 있을 때 인덱싱 된 MSRAPIC 레지스터에 대한 액세스를 허용하는 것을 의미합니다.
  • bits 31:0 의 값은 SMM 에서만 쓸 수 있는 MSR 을 나타내며 VM ExitSMM 에서 끝나지 않습니다. (IA32_SMM_MONITOR CTLSMM 에서만 쓸 수 있는 MSR)
  • bits 31:0 의 값은 모델별 이유로 VM Exit 에 로드할 수 없는 MSR 을 나타냅니다. 프로세서는 특정 MSR 이 일반적으로 WRMSR 에 의해 기록될 수 있는 경우에도 로드를 방지할 수 있습니다.
  • bits 63:32 가 0이 아닙니다.
  • 엔트리의 bits 31:0 으로 인덱싱된 MSR 에 bits 127:64 를 쓰려는 시도가 CPL = 0WRMSR 을 통해 실행되는 경우 #GP 를 발생시킵니다.

해당 처리가 실패하면 VMX Abort 가 발생합니다.

[0x05] VMX Aborts

VM Exit 중에 문제가 발생하게 되면 VMX Abort 가발생합니다. VMX Abort 는 아래에 설명된 대로 프로세서를 shutdown 상태로 전환합니다.

VMX Abortactive VMCSVMCS Region 에 있는 VMCS Data 를 변경하지 않습니다. 따라서 이러한 데이터의 내용은 VMX Abort 후에는 확실하지 않습니다.

VMX Abort 가 발생 시 프로세서는 잘못된 구성으로 인해 오류가 발생한 VMCSVMCS Region 필드의 Byte Offset4(VMX-abort indicator) 에 0이 다음의 값을 저장합니다.

  1. 게스트 MSR 을 저장하는 데 실패했습니다.
  2. PDPTE 에 대한 호스트 확인에 실패했습니다.
  3. current VMCS 가 손상되어(VMCS Region 에 쓰기를 통해) 프로세서가 VM Exit 를 제대로 완료할 수 없습니다.
  4. 호스트 MSR 을 로드하는 동안 오류가 발생했습니다.
  5. VM ExitMachine-Check Event 가 발생했습니다.
  6. VM Exit 전에 프로세서가 IA-32e mode 에 있었고 VMExit_host address-space size 제어가 0이었습니다.

이러한 원인 중 일부는 호스트 상태 영역에서 상태를 로드하는 동안의 오류에 해당합니다. 상태를 로드하는 것은 임의의 순서로 수행될 수 있으므로 VM Exit 는 여러 가지 이유로 인해 VMX Abort 가 발생할 수 있습니다. 때문에 여러가지 이유 중 VMX-abort indicator 에는 하나만 기록되므로 다른 문제가 없다는 것은 아닙니다.

VMX-abort indicator 는 하나의 논리 프로세서의 VMM 이 다른 논리 프로세서의 VMX Abort 를 진단할 수 있도록 합니다.

이러한 이유로 VMX root operation 에서 실행되는 VMM 은 사용하는 VMCSVMCS Region 에서 VMX-abort indicator 를 0으로 설정하는 것이 좋습니다.

VMX-abort indicator 를 저장한 후 VMX Abort 가 발생한 논리 프로세서의 동작은 SMX Operation 상태인지에 따라 달라집니다.

  • 만약 SMX Operation(Safer Mode Extension) 에 있다면 Intel TXT shutdown condition 이 발생합니다.

[0x06] Machine-Check Event During VM Exit

VM Exit 중에 Machine-Check Event 가 발생하면 다음 중 하나가 발생합니다.

  • Machine-Check EventVM Exit 전에 처리됩니다.
    • CR4.MCE = 0 인 경우 프로세서의 동작은 SMX Operation 상태인 경우 Intel TXT shutdown condition 이 발생하고, 아닌 경우 shutdown 상태로 전환됩니다.
    • CR4.MCE = 1 인 경우 machine-check exception(#MC) 가 생성됩니다.
      • Exception bitmap 의 bit 18(#MC)이 0이면 게스트 IDT 를 통해 예외가 전달됩니다.
      • Exception bitmap 의 bit 18이 1이면 VM Exit 가 발생합니다.
  • Machine-Check EventVM Exit 가 완료된 후 처리됩니다.
    • VM ExitCR4.MCE = 0 로 끝나는 경우 프로세서의 동작은 SMX Operation 상태인 경우 오류 코드 000Ch와 함께 Intel TXT shutdown condition 이 발생하고, 아닌 경우 shutdown 상태로 전환됩니다.
    • VM ExitCR4.MCE = 1 으로 끝나는 경우 호스트 IDT 를 통해 machine-check exception 이 전달됩니다.
  • VMX Abort 가 생성됩니다. 논리 프로세서는 VMX Abort 에서 정상적으로 수행되는 이벤트를 차단합니다. VMX-abort indicator 는 5(machine-check event during VM exit) 입니다.

호스트 상태가 로드된 후 Machine-Check Event 가 발생하는 경우 첫 번째 내용은 사용되지 않습니다. 두 번째 내용은 VM Entry 가 모든 호스트 상태를 로드할 수 있는 경우에만 사용됩니다.

[0x07] Conclusion

아직도 이해가 되지 않는 부분이나 용어들이 꽤 많이 있습니다.

구현은 하지 않고 계속 보고 있으니 인텔 메뉴얼에 매우 익숙해진다는 장점은 있습니다.

[0x08] Reference

  1. Intel 64 and IA-32 Architectures Software Developer’s Manual