Wednesday, June 17, 2009

VMCS Guest State Area

The VMCS has an area for guest register state and guest non-register state. The guest register state contains fields for control registers(CR0,CR3,CR4), segment registers(cs,ds etc) , segment selectors, segment attributes(also called ARBytes),segment-limits, debug-register(dr7) etc.

The guest non-register state has the following fields:

(a) VMCS GUEST ACTIVITY STATE: This is a 32 bit field that describes the state of the guest. Intel manual defines only the first four bits in this field. The others are marked as reserved. The four bits are as given under:
(i) Bit 0 - If this bit is 1 , the guest is in Active State .
(ii) Bit 1 - If this bit is 1 , the guest is in HLT state.
(iii) Bit 2 - If this bit is 1 , the guest is in Shutdown state.
(iv) Bit 3 - If this bit is 1 , the guest is in Wait-for-SIPI state.

Here is a scenario how the vmcs might indicate a guest in halt state:

The guest executes HLT and the execution of HLT does not cause a vmexit(assume proc_based_ctl[hlt] is 0). At this point the guest is in HLT state. Now an interrupt arrives and the processing of the interrupt causes a vmexit(assume pin_based_ctl for intr is 1). The vmexit causes the processor to update the GUEST ACTIVITY STATE in the VMCS as HLT. A subsequent VMRESUME will read this field from the vmcs and launch the guest in HLT state.

(b) VMCS GUEST INTR INFO : The INTR INFO describes the interruptibility state of the guest. Four bits are defined in this field.
(i) Bit 0 - Guest has STI blocking active
(ii) Bit 1 - Guest has MOV-SS/POP-SS active
(iii) Bit 2 - Blocking by SMI
(iv) Bit 3 - Blocking by NMI

Here is a scenario where the vmcs might indicate STI blocking:

Guest executes STI. Following STI, guest executes HLT which vmexits (assume proc_based_ctl[hlt] is 1). The vmexit due to hlt will cause the processor to update the interruptibility-info with STI blocking. A subsequent VMRESUME will put the guest back in STI blocking state. In this case, during a vmresume, the processor also checks the EFLAGS.IF = 1 and will fail VMEntry if it detects the following condition:

if(sti_blocking==TRUE && EFLAGS.IF==0) {
fail_vmentry();
}

(c)Pending Debug Exceptions Field: This field in the VMCS indicates if there are any debug exceptions that are pending in the guest. The meaningful bits in this field are:

Bit 12 -> Enabled Breakpoint
Bit 14 -> Single Step
Bits 3-0 -> Correspond to B0,B1,B2,B3 (meaningful only if bit 12 is 1).

Here is a scenario how the guest may end up with a single-step exception pending during a vmexit:

pushfd ; push flags
or dword [esp], 0x100 ; set eflags.TF
popfd ; pop flags now eflags.TF=1
mov ss, ax ; will delay recognition of single step until the end of the next instruction
vmcall ; cause vmexit

In the above code, at the time of vmexit , single-step is pending (it is delayed because of mov-ss blocking). This vmexit will cause the processor to record a single-step pending in the debug-exceptions field of the vmcs. Incidentally, the above vmexit will also cause the processor to record mov-ss blocking in the interruptibility field.

1 comment:

  1. Hello,
    I have a couple of questions: after I execute vmptrld guest_vmcs_ptr and I use the vmwrite instruction to set some fields of the vmcs, where are this values being written? In memory right? So if I vmread the same field, I should get the same value I wrote into that field.

    I mean it is not clear for me yet where the vmcs lies before and after vmptrld and vmxon. I believe that the values of the vmcs are loaded from memory to the respective registers each time there's a switch between root and non-root mode. Please tell if I'm wrong.

    ReplyDelete