mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/vvmx: correct nested shadow VMCS handling
Currently xen always sets the shadow VMCS-indicator bit on nested vmptrld and always clears it on nested vmclear. This behavior is wrong when the guest loads a shadow VMCS: shadow bit will be lost on nested vmclear. Fix this by checking if the guest has provided a shadow VMCS. Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com> Acked-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
1 parent
7ecd11c90a
commit
dc05c0ceeb
2 files changed
+19
-4
No files matched your search
@@ -1119,10 +1119,19 @@ static bool_t nvmx_vpid_enabled(const struct vcpu *v)
|
||||
|
||||
static void nvmx_set_vmcs_pointer(struct vcpu *v, struct vmcs_struct *vvmcs)
|
||||
{
|
||||
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
|
||||
paddr_t vvmcs_maddr = v->arch.hvm_vmx.vmcs_shadow_maddr;
|
||||
|
||||
__vmpclear(vvmcs_maddr);
|
||||
vvmcs->vmcs_revision_id |= VMCS_RID_TYPE_MASK;
|
||||
if ( !nvmx->shadow_vmcs )
|
||||
{
|
||||
/*
|
||||
* We must set the shadow VMCS-indicator in order for the next vmentry
|
||||
* to succeed with a newly set up link pointer in vmcs01.
|
||||
* Note: guest can see that this bit was set.
|
||||
*/
|
||||
vvmcs->vmcs_revision_id |= VMCS_RID_TYPE_MASK;
|
||||
}
|
||||
__vmwrite(VMCS_LINK_POINTER, vvmcs_maddr);
|
||||
__vmwrite(VMREAD_BITMAP, page_to_maddr(v->arch.hvm_vmx.vmread_bitmap));
|
||||
__vmwrite(VMWRITE_BITMAP, page_to_maddr(v->arch.hvm_vmx.vmwrite_bitmap));
|
||||
@@ -1130,10 +1139,13 @@ static void nvmx_set_vmcs_pointer(struct vcpu *v, struct vmcs_struct *vvmcs)
|
||||
|
||||
static void nvmx_clear_vmcs_pointer(struct vcpu *v, struct vmcs_struct *vvmcs)
|
||||
{
|
||||
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
|
||||
paddr_t vvmcs_maddr = v->arch.hvm_vmx.vmcs_shadow_maddr;
|
||||
|
||||
__vmpclear(vvmcs_maddr);
|
||||
vvmcs->vmcs_revision_id &= ~VMCS_RID_TYPE_MASK;
|
||||
if ( !nvmx->shadow_vmcs )
|
||||
vvmcs->vmcs_revision_id &= ~VMCS_RID_TYPE_MASK;
|
||||
nvmx->shadow_vmcs = false;
|
||||
__vmwrite(VMCS_LINK_POINTER, ~0ul);
|
||||
__vmwrite(VMREAD_BITMAP, 0);
|
||||
__vmwrite(VMWRITE_BITMAP, 0);
|
||||
@@ -1674,12 +1686,14 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs)
|
||||
{
|
||||
if ( writable )
|
||||
{
|
||||
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
|
||||
struct vmcs_struct *vvmcs = vvmcx;
|
||||
|
||||
nvmx->shadow_vmcs =
|
||||
vvmcs->vmcs_revision_id & ~VMX_BASIC_REVISION_MASK;
|
||||
if ( ((vvmcs->vmcs_revision_id ^ vmx_basic_msr) &
|
||||
VMX_BASIC_REVISION_MASK) ||
|
||||
(!cpu_has_vmx_vmcs_shadowing &&
|
||||
(vvmcs->vmcs_revision_id & ~VMX_BASIC_REVISION_MASK)) )
|
||||
(!cpu_has_vmx_vmcs_shadowing && nvmx->shadow_vmcs) )
|
||||
{
|
||||
hvm_unmap_guest_frame(vvmcx, 1);
|
||||
vmfail(regs, VMX_INSN_VMPTRLD_INCORRECT_VMCS_ID);
|
||||
|
||||
@@ -51,6 +51,7 @@ struct nestedvmx {
|
||||
} ept;
|
||||
uint32_t guest_vpid;
|
||||
struct list_head launched_list;
|
||||
bool shadow_vmcs;
|
||||
};
|
||||
|
||||
#define vcpu_2_nvmx(v) (vcpu_nestedhvm(v).u.nvmx)
|
||||
|
||||