您的位置:首页 > 其它

2.3 VMCS

2015-07-26 16:00 901 查看
VMM 和 Guest OS共享底层的处理器资源,因此硬件需要一个物理内存区域来自动保存或恢复彼此执行的上下文。这个区域称为虚拟机控制块(VMCS),包括客户机状态区(Guest State Area),主机状态区(Host State Area)和执行控制区. VM entry 时,硬件自动从客户机状态区加载 Guest OS 的上下文。并不需要软件来保存
VMM 的上下文.当VMM 开始运行,就不会受到Guest OS的干扰,只有 VMM 将工作彻底处理完毕才可能自行切换到 Guest OS。而 VMM 的下次运行必然是处理一个新的事件,因此每次 VM entry 时, VMM 都从一个通用事件处理函数开始执行;VM exit 时,硬件自动将 Guest OS 的上下文保存在客户机状态区,从主机状态区中加载 VMM 的通用事件处理函数的地址,VMM 开始执行。而执行控制区存放的则是可以操控 VM entry 和 exit 的标志位,例如标记哪些事件可以导致
VM exit,VM entry 时准备自动给 Guest OS 注入哪种中断等等。
2.3.1 VMCS总表
字段名采用vmcs_field 中的定义
类型
字段
含义
VM-Execution
控制字段

PIN_BASED_VM_EXEC_CONTROL
控制pin与INTR 和 NMI是否产生VM-Exit 与使能
CPU_BASED_VM_EXEC_CONTROL
处理器的指令是否引起VM-Exit, bit31控制是否启用
SECONDARY_VM_EXEC_CONTROL
SECONDARY_VM_EXEC_CONTROL
EPT, virtual APIC 等使能位; invpcid等指令是否产生vm-exit
EXCEPTION_BITMAP
每位对应一个异常,为一时发生该异常产生vm-exit
IO_BITMAP_A
IO_BITMAP_A_HIGH
IO_BITMAP_B
IO_BITMAP_B_HIGH
每位对应一个io port addr, 为一时访问该port产生vm-exit
TSC_OFFSET
TSC_OFFSET_HIGH
Use TSC offset时, non-root下执行rdtsc, rdtscp, rdmsr时反会该寄存器的值
CR0_GUEST_HOST_MASK
CR0_READ_SHADOW
CR4_READ_SHADOW
CR4_GUEST_HOST_MASK
Mask为为一属于host, 否则属于guest

属于Host: Guest读该位返回shadow的值,写该位时如果与shadow值不等,产生vm-exit.

属于Guest时,读写不产生vm-exit
CR3_TARGET_VALUE (0-3)
CR3_TARGET_COUNT
当Guest向CR3写时,不等于0 - 3中的值产生vm-exit
APIC_ACCESS_ADDR
APIC_ACCESS_ADDR_HIGH
当virtualize apic为1时, 指向4K apic-access page
VIRTUAL_APIC_PAGE_ADDR
VIRTUAL_APIC_PAGE_ADDR_HIGH
Use tpr shadow为1时,指向4K virtual apic-access page
TPR_THRESHOLD
Use tpr shadow为1时 bit[3:0] > VPTR[7:4]时产生vm-exit
EOI_EXIT_BITMAP (0-3)
EOI_EXIT_BITMAP(0-3)_HIGH
Virtual-interrupt delivery为1时,用于控制Eoi时
是否产生vm-exit
POSTED_INTR_DESC_ADDR
指向posted-interrupt-descriptor结构的地址
POSTED_INTR_NV
Process posted interrupts为1时允许处理器收到一个通知性的外部中断为不产生vm-exit
MSR_BITMAP
为1时,访问产生vm-exit
EPT_POINTER
EPT list的物理地址
VIRTUAL_PROCESSOR_ID
Enable VPID为1时,提供vpid值
PLE_GAP
PLE_WINDOW
设置pause-loop exiting的超时
PAGE_FAULT_ERROR_CODE_MASK
PAGE_FAULT_ERROR_CODE_MATCH
PAGE fault异常时 (PEFC & PFEC_MASK) == PFEC_MACH时产生vm-exit
Vm-ENTRY控制字段

VM_ENTRY_CONTROLS
控制VM-Entry进入的模式SMM, IA-32E,等
VM_ENTRY_EXCEPTION_ERROR_CODE
VM_ENTRY_INSTRUCTION_LEN
VM_ENTRY_INTR_INFO_FIELD
控制中断与异常注入
VM_ENTRY_MSR_LOAD_COUNT
VM_ENTRY_MSR_LOAD_ADDR
VM-Entry时加载load_addr提供的msr值
VM-EXIT控
制字段

VM_EXIT_CONTROLS
VM-Exit时寄存的保存控制
VM_EXIT_MSR_STORE_COUNT
VM_EXIT_MSR_LOAD_COUNT
VM-Exit时保存msr
Guest State字段
GUEST_CR0
GUEST_CR3
GUEST_CR4
GUEST_DR7
GUEST_RSP GUEST_RIP
GUEST_RFLAGS
GUEST_ES_BASE
GUEST_CS_BASE
GUEST_SS_BASE
GUEST_DS_BASE
GUEST_FS_BASE
GUEST_GS_BASE
GUEST_LDTR_BASE
GUEST_TR_BASE
GUEST_GDTR_BASE
GUEST_IDTR_BASE
GUEST_ES_LIMIT
GUEST_CS_LIMIT
GUEST_SS_LIMIT
GUEST_DS_LIMIT
GUEST_FS_LIMIT
GUEST_GS_LIMIT
GUEST_LDTR_LIMIT
GUEST_TR_LIMIT
GUEST_GDTR_LIMIT
GUEST_IDTR_LIMIT
GUEST_ES_AR_BYTES
GUEST_CS_AR_BYTES GUEST_SS_AR_BYTES
GUEST_DS_AR_BYTES GUEST_FS_AR_BYTES
GUEST_GS_AR_BYTES
GUEST_LDTR_AR_BYTES
GUEST_TR_AR_BYTES
GUEST_IA32_PAT
GUEST_IA32_PAT_HIGH
GUEST_IA32_EFER
GUEST_IA32_EFER_HIGH
GUEST_IA32_PERF_GLOBAL_CTRL =
GUEST_IA32_PERF_GLOBAL_CTRL_HIGH
GUEST_SYSENTER_ESP
GUEST_SYSENTER_EIP
GUEST_SYSENTER_CS
GUEST_INTERRUPTIBILITY_INFO
记录vcpu是否可以响应中断
GUEST_PENDING_DBG_EXCEPTION
记录与设置guest peding的 #DB异常
GUEST_PDPTR (0-3)
EPT时页目录指针
GUEST_BNDCFGS
GUEST_IA32_DEBUGCTL
GUEST_IA32_DEBUGCTL_HIGH
VMCS_LINK_POINTER
VMCS_LINK_POINTER_HIGH
SMM时使用
GUEST_INTR_STATUS
Virtual-interrupt delivery时,记录local apic的状态值
VMX_PREEMPTION_TIMER_VALUE
Preemption timer的值, 0时产生vm-exit
GUEST_ACTIVITY_STATE
指示虚拟处理器的状态 active, hlt, shutdown, wait-for-sipi
Host State
HOST_CR0
HOST_CR3
HOST_CR4
HOST_FS_BASE
HOST_GS_BASE
HOST_TR_BASE
HOST_GDTR_BASE
HOST_IDTR_BASE
HOST_ES_SELECTOR
HOST_CS_SELECTOR
HOST_SS_SELECTOR
HOST_DS_SELECTOR
HOST_FS_SELECTOR
HOST_GS_SELECTOR
HOST_TR_SELECTOR
HOST_IA32_SYSENTER_ESP
HOST_IA32_SYSENTER_EIP
HOST_IA32_SYSENTER_CS
HOST_IA32_PAT =
HOST_IA32_PAT_HIGH =
HOST_IA32_EFER =
HOST_IA32_EFER_HIGH =
HOST_IA32_PERF_GLOBAL_CTRL =
HOST_IA32_PERF_GLOBAL_CTRL_HIGH
HOST_RSP
HOST_RIP
VM-EXIT 信息字段
VM_EXIT_REASON
导致vm-exit的原因
GUEST_PHYSICAL_ADDRESS
导致vm-exit GPA值
EXIT_QUALIFICATION
提供进一步的vm-exit信息
GUEST_LINEAR_ADDRESS
导致vm-exit 线性地址
VM_EXIT_INTR_INFO
VM_EXIT_INTR_ERROR_CODE
外部中断信息
IDT_VECTORING_INFO_FIELD
IDT_VECTORING_ERROR_CODE
引起vm-exit的vector信息
VM_EXIT_INSTRUCTION_LEN
VMX_INSTRUCTION_INFO
VM_INSTRUCTION_ERROR
引起vm-exit的指令信息
底层访问代码如下:
static void vmcs_writel(unsigned long field, unsigned longvalue)
{
u8 error;

asm volatile(__ex(ASM_VMX_VMWRITE_RAX_RDX) "; setna %0"
: "=q"(error) :"a"(value), "d"(field) : "cc");
if (unlikely(error))
vmwrite_error(field,value);
}

//64位访问
static void vmcs_write64(unsigned long field, u64 value)
{
vmcs_writel(field,value);
#ifndef CONFIG_X86_64
asm volatile("");
vmcs_writel(field+1,value >> 32);
#endif
}
//32位访问
static void vmcs_write32(unsigned long field, u32 value)
{
vmcs_writel(field,value);
}
2.3.2 到2.3.4将分别讲解控制字段的设置代码,信息字段将在VM-Exit与VM-Entry中分析

2.3.2 KVM中VM-Execution控制字段的设置
Name
Function Flow
Set Bits
Description
Note
PIN_BASED_VM_EXEC_CONTROL
setup_vmcs_config
BIT0
BIT3
BIT6
BIT7
外部中断 VM-Exit
NMI时VM-Exit
启用 VMX preemtion timer
启用post-intrs处理虚拟中断
这些bit与MSR_IA32_VMX_PINBASED_CTLS能力取And
CPU_BASED_VM_EXEC_CONTROL
setup_vmcs_config
BIT3
BIT7
BIT9
BIT10
BIT11
BIT15 BIT16
BIT25
BIT21
BIT23
BIT27
Bit28
BIT31
Use TSC offset
Hlt产生vm-exit
inpLPG产生vm-exit
mwait产生vm-exit
RDPMC产生vm-exit
读写CR3时
Use Iobitmap
USE TPR SHADOW
读写DR寄存器
启用mtf调试功能
启用msr bitmap
启用second process base vm-execution
1. 64位CR8 读写产生Vm-Exit(bit[19:18]

2. 这些bit与MSR_IA32_VMX_PROCBASED_CTLS 取and
SECONDARY_VM_EXEC_CONTROL
setup_vmcs_config
BIT0
BIT1
BIT3
BIT4
BIT5
BIT6
BIT7
BIT8
BIT9
BIT10
BIT12
Enable apic-access page
Enable EPT
RDTSCP产生#UD异常
Enable x2APIC MSR
Enable VPID
Wbinvd产生vm-exit
Guest可以使用非分页模式
支持virtual-apic page虚拟寄存器
支持虚拟中断delivery
Pause timeout时vm-exit
Invpcid产生vm-exit
1. 这些bit与MSR_IA32_VMX_PROCBASED_CTLS2 and
EXCEPTION_BITMAP
update_exception_bitmap
#PF
#UD
#MC
#NM
#DB
当Guest模式发生变化时,update_exception_bitmap会调用来更新这些bit
IO_BITMAP
Vmx_init
memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE);

clear_bit(0x80, vmx_io_bitmap_a);
memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE);
TSC_OFFSET
kvm_arch_vcpu_load ==>kvm_x86_ops->compute_tsc_offse
vcpu->arch.last_guest_tsc - native_read_tsc
CR0_GUEST_HOST_MASK
CR0_READ_SHADOW
CR4_READ_SHADOW
CR4_GUEST_HOST_MASK
(1) vmx_cpu_reset:
vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu));

vmx_set_cr4(&vmx->vcpu, 0);

(2) kvm_arch_vcpu_ioctl_set_sregs==>kvm_x86_ops->set_cr0 cr4

(3)异常处理时
vmx_set_cr0
vmx_set_cr4
根据模式发生变化
CR3_TARGET_COUNT
vmx_vcpu_setup
0
非nested时为0
APIC_ACCESS_ADDR
vmcs_write64(APIC_ACCESS_ADDR, page_to_phys(vmx->vcpu.kvm->arch.apic_access_page));
VIRTUAL_APIC_PAGE_ADDR
Vmx_vcpu_reset
vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
__pa(vmx->vcpu.arch.apic->regs)
TPR_THRESHOLD
1. kvm_vcpu_ioctl_set_lapic ==》update_cr8_intercept

2.vmx_vcpu_reset 初始化为0
Local apic相关
EOI_EXIT_BITMAP
vcpu_enter_guest ==>vcpu_scan_ioapic==>
kvm_ioapic_scan_entry 取得
kvm_x86_ops->load_eoi_exitmap 设置
POSTED_INTR_NV
vmx_vcpu_setup
0xf2
POSTED_INTR_DESC_ADDR
__apic_accept_irq ==>vmx_deliver_posted_interrupt
vmx->pi_desc
MSR_BITMAP
变量地址初始化
vmx_set_msr_bitmap

vmx_init时初始化
msr_bitmap
初始化根据irqchip_in_kernel
apic_x2apic_mode
定义
VIRTUAL_PROCESSOR_ID
Vmx_vcpu_reset时初始化
vmx->vpid 由allocate_vpid动态分配
PLE_GAP
PLE_WINDOW
static int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;

static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
Vmx模块初始化定义
#define KVM_VMX_DEFAULT_PLE_GAP 128
#define KVM_VMX_DEFAULT_PLE_WINDOW 4096
PAGE_FAULT_ERROR_CODE_MASK
PAGE_FAULT_ERROR_CODE_MATCH
vmx_vcpu_setup
0
Page Fault固定产生vm-exit
Note1:表中的使能位为KVM最大支持的bits
Note2: Nested Case是指在虚拟机上再跑虚拟机;本文由于篇幅原因,只讨论真实机上直接运行虚拟机的case.

2.3.3 KVM中VM-Entry & VM-Exit 控制字段设置
Name
Function Flow
Set Bits
Description
Note
VM_ENTRY_CONTROLS
setup_vmcs_config
设置
vmx_vcpu_setup ==>vm_entry_controls_init
BIT1

BIT1
Vm-ENTRY时从 guest-state加载dr7 dbg_ctrl
Vm-ENTRY时从 guest-state加载 IA32_PAT
这些bit与MSR_IA32_VMX_ENTRY_CTLS and
VM_ENTRY_EXCEPTION_ERROR_CODE
VM_ENTRY_INSTRUCTION_LEN
VM_ENTRY_INTR_INFO_FIELD
vmx_queue_exception
动态注入
VM_ENTRY_MSR_LOAD_COUNT
VM_ENTRY_MSR_LOAD_ADDR
vmx_vcpu_reset==》setup_msrs
和模式切换时
根据vmx_msr_index 变量
Vmx_init==> for (i = 0; i < NR_VMX_MSR; ++i)
kvm_define_shared_msr(i, vmx_msr_index[i]);
VM_EXIT_CONTROLS
setup_vmcs_config
设置
vmx_vcpu_setup ==>vm_exit_controls_init
BIT15
BIT18
BIT19
VM-EXIT时处理器响应中断控制器

vm-exit时保存到guest_stateI232_PAT
Vm-exit时加载host-state IA32_PAT
VM_EXIT_MSR_STORE_COUNT
0
VM_EXIT_MSR_LOAD_COUNT
vmx_vcpu_reset==》setup_msrs
和模式切换时
VM_ENTRY_INTR_INFO_FIELD :
bit[7:0] vector
bit[10:8] event type
bit11 error code
bit31 valid

2.3.4 VM-Exit Info
(1) Exit Reason
bit[15:0] Exit 退出原因arch\x86\include\asm\vmx.h
#define EXIT_REASON_EXCEPTION_NMI 0
#define EXIT_REASON_EXTERNAL_INTERRUPT 1
#define EXIT_REASON_TRIPLE_FAULT 2
.......
#define EXIT_REASON_XSETBV 55
#define EXIT_REASON_APIC_WRITE 56
#define EXIT_REASON_INVPCID 58

同时arch\x86\kvm\vmx.c定义了每个Vm-exit推出原因的处理函数
static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu*vcpu) = {
[EXIT_REASON_EXCEPTION_NMI] = handle_exception,
[EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt,
[EXIT_REASON_TRIPLE_FAULT] = handle_triple_fault,
.......
[EXIT_REASON_MWAIT_INSTRUCTION] =handle_mwait,
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
[EXIT_REASON_INVEPT] = handle_invept,
}

bit[28] 为1表明Vm-exit时,存在pending MTF事件
bit[29]为1表明 vm-exit有root-operation环境中产生
bit[31]为1表明, VM-Entry中发生vm-exit

(2) EXIT_QUALIFICATION
记录退出原因的明细信息, KVM支持的类别如下
a) 指令引发的:invplg 保存操作数线性地址, mwait 则为0或1,其它指令记录内存操作数偏移

b) #DB 引发: bit[3:0]对应断点0-3,bit3 异常由访问DR造成, bit14表示单步调试

c) #PF引发: 引起异常的线性地址
d) 接收SIPI引发 bit[7:0]为向量号

e) 接收SMI引发: bit[2:0] io operand size, bit[3] io direction; bit[4] charoperation, bit[5] rep prefix; bit[6] 1 立即数, 0 DX寄存器。 bit[31:16] io port.

f) 任务切换引发bit[15:0] TSS selector, bit[31:30] 0 call , 1 iret, 2 jmp, 3 task gate.

g) 访问控制寄存器引发
bit[3:0]访问控制寄存器; bit[5:4] 访问类型;lmswoperand 指令操作数;
bit[11:8]记录使用的通用寄存器; bit[31:16]指令的源操作数值

h) mov-dr指令引发: bit[2:0] 调试寄存器,bit4 方向。 bit[11:8]记录通用寄存器

i) 访问 I/O 引发: bit[2:0] io operand size, bit[3] io direction; bit[4] charoperation, bit[5] rep prefix; bit[6] 1 立即数, 0 DX寄存器。 bit[31:16] io port.

j) 访问apic-accesspage引发 bit[11:0] apic-access page 内偏移; bit[15:12] type

k) eptviolation引发
bit0read, bit1 write, bit2 execute
bit3readable, bit4 wirtable, bit5 executable
bit7:存在guest-linear address;
bit81 gpa->hpa 0 guest paging-structure

l) eoi虚拟化引发, bit[7:0]中断向量号
m) apic-write引发bit[11:0] apic-access page 内偏移

(3) 向量信息
直接向量
vm-exit interrupt information
bit[7:0]异常或中断号,bit[10:8]中断或异常类别,bit11: error code, bit12 表示blocking by nmi被解除, bi31 valid

vm-exit interruption error code
vm-exit interrupt information bit11 为1时有效,记录错误码

间接向量信息:当一个向量事件delivery间产生一个异常,那么产生一个直接向量(后面产生的异常)和一个间接向量事件(原始事件)。
idt-vector information; idt-vector error code

(4) 指令信息
vm-exit instruction length 分为两类
a. 指令引起vm-exit
b. 向量引起vm-exit
vm-exit instruction information, 根据指令不同而区别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: