6. VM-entry控制类字段
0 概述
VM-entry区域的控制字段包括下面这些
(1) VM-entry control字段
(2) VM-entry MSR-load count字段
(3) VM-entry MSR-load address字段
(4) VM-entry interruption-information字段
(5) VM-entry exception error code字段
(6) VM-entry instruction length字段
这些字段用来控制在VM-entry时处理器的行为. 在VM-entry时, 处理器检查这些字段. 如果检查不通过, 产生VMfailValid失败, 在VM-instruction error字段(!!!)中保存错误号, 接着执行VMLAUNCH或VMRESUME指令下面的指令.
3 事件注入控制字段
事件注入是虚拟化平台中最关键的特性之一, 是实现虚拟化管理的重要手段. 允许在VM-entry完成后, 执行任何guest指令前(!!!), 处理器执行由VMM设置的注入事件. 这个事件可以是一个中断(!!!)或异常(!!!), 甚至pending MTF VM-exit事件(!!!), 它们被称为"向量化事件(!!!)", 而含有注入事件的VM-entry被称为"向量化的VM-entry".
事件注入机制由如下三个字段实现
(1) VM-entry interruption-information字段
(2) VM-entry exception error code字段
(3) VM-entry instruction length字段
VMM通过设置这三个字段来配置向量化事件.
如果一个VM-exit是由于向量化事件而引起的, 那么VM-exit interruption information和VM-exit interruption error code字段会记录这个向量化事件的信息.
如果INT3或INTO指令产生的软件异常引发VM-exit, 或者由软件异常, 软件中断, 特权级软件中断delivery期间出错而引发VM-exit, VM-exit instruction length字段会记录引发VM-exit指令的长度.
VMM可以直接复制VM-exit interruption information, VM-exit interruption error code及VM-exit instruction length字段的值到VM-entry interruption-information, VM-entry exception error code及VM-entry instruction length字段来完成设置. VMM也可以主动设置这几个字段来注入一个向量化事件给guest执行.
3.1 VM-entry interruption-information字段
这个字段是32位宽, 用来设置注入事件的明细信息. 包括: 中断或异常的向量号, 事件类型, 错误码的delivery标志位及有效标志位. 结构如图3-7.
bit 7:0设置中断或异常的向量号, 当事件类型是NMI时, 向量号必须为2. 事件类型为other时, 向量号必须为0值.
bit 11为1时, 指示有错误码需要提交. 在注入事件delivery时, 错误码会被压入栈中. 这个位只有在注入硬件异常事件时才能被置为1, 否则会产生VMfailValid失败. 能产生错误码的硬件异常是: #DF, #TS, #NP, #SS, #GP, #PF及#AC这7类. 注入其余异常不能将此位置1.
bit 31是有效位, 为1时指示VM-entry interruption information字段有效, 为0时无效. bits 10:8 设置事件类型, 包括7个事件类型, 如表3-10所示.
表中列出了可以注入的7种事件类型, 对应VM-entry interruption information字段的bits 10:8位, 类型值1保留.
3.1.1 外部中断(类型0)
外部中断不能使用0-15号向量, 也不应该使用16-31号向量, 应使用32~255号向量. 这个时间类型被期望用来注入一个中断控制器(local APIC, IO APIC或者8259A)获得的中断请求.
3.1.2 NMI(类型2)
NMI必须使用2号向量. 当NMI成功deliver执行后, 处理器的"blocking by NMI"状态有效, 表示存在NMI阻塞状态, 直到IRET指令执行后解除这个阻塞(见3.8.6节).
当"virtual-NMIs"为1时, 表示注入的是一个virtual-NMI事件, virtual-NMI delivery后, 就存在virtual-NMI阻塞状态, 直到IRET指令执行后解除virtual-NMI阻塞.
当注入一个virtual-NMI, 而"NMI-window exiting"为1, 并且"blocking by NMI"为0时, 则在VM-entry完成后直接产生VM-exit.
3.1.3 硬件异常(类型3)
硬件异常是指除了#BP(INT3指令)与#OF异常(INTO指令)以外的所有异常, 它们属于fault或abort类型异常. 也包括由BOUND指令产生的#BR异常及由UD指令产生的#UD异常. 所有类型的#DB异常(也包括了trap类型)也属于硬件异常. 硬件异常的向量号必须是0~31(!!!).
尽管在64位模式下BOUND指令无效, 但允许注入#BR异常(!!!).
3.1.4 软件异常(类型6)
软件异常指由NIT3与INTO指令产生的#BP与#OF异常, 对应的向量号必须为3与4. 它们属于trap类型. 尽管在64位模式下INTO指令无效, 但允许注入#OF异常.
3.1.5 软件中断(类型4)
软件中断指由INT指令执行的中断. 软件中断在delivery期间需要进行权限的检查. 对于一个non-conforming代码段, CPL≤Gate的DPL值, 并且CPL≥Code段的DPL值. 如果在delivery期间法还是能权限不符合会产生#GP异常. 如果exception bitmap字段的bit 13位1, #GP异常会导致VM-exit. 因此将在VM-exit interruption information字段中记录中断的向量号和时间类型等. 在VM-exit interruption error code字段记录#GP异常错误码.
注入由INT3或INTO指令产生的软件异常和软件中断一样, 在delivery期间同样修安排进行权限的检查, 处理手法与软件中断一样.
3.1.6 特权级软件中断(类型5)
这类事件只能在注入时使用, 不可能在执行中遇到. 也就是说: 在执行过程中不可能产生这类中断(!!!), 只能通过注入事件的方式(!!!)产生. 除了无需进行权限检查外, 其余的处理手法与软件中断是一致的. 这也就是这类事件的特权由来.
3.1.7 其他事件(类型7)
这类事件目前使用在MTF(Monitor Trap Flag)功能上. 当事件类型为7时, 向量号必须为0. 否则在VM-entry时会产生VMfailValid失败. 注入这个类型事件时, 将pending一个MTF VM-exit事件. 当VM-entry完成后会产生MTF VM-exit(参见4.15.3节).
注意: 这个MTF VM-exit事件不受"monitor trap flag"控制位的影响(另见3.5.2.1节), 但必须在支持"monitor trap flag"功能时才能注入MTF VM-exit.
3.2 VM-entry exception error code字段
这个32位的字段只有在VM-entry interruption information字段的bit 31及bit 11为1时才有效, 提供一个异常错误码在注入事件delivery期间压入栈中.
只有#DF, #TS, #NP, #SS, #GP, #PF及#AC异常才会产生错误码. 因此, 注入这几个硬件异常时需要提供错误码. 对于其他硬件异常或其他类型的事件, 这个字段会被忽略.
3.3 VM-entry instruction length字段
这个字段是32位宽. 在事件注入中, 它被期望VM-exit由下面的向量化事件引起时使用:
(1) 由于执行INT3或INTO指令产生的软件异常而引起VM-exit.
(2) 在软件异常, 软件中断或特权级软件中断delivery期间产生了异常而导致VM-exit发生, 或者由于IDT描述符使用了task-gate尝试任务切换而导致VM-exit发生.
如果由这些向量化事件引起VM-exit, 在VM-exitinstruction length字段中会记录这些指令的长度.
当注入事件属于软件异常(类型6), 软件中断(类型4)以及特权级软件中断(类型5)时, 必须在这个字段中提供指令长度. 指令长度在1~15之间, 为0会产生VMfailValid失败.