[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86/vvmx: Improvements to INVEPT instruction handling



 * Latch current once at the start.
 * Avoid the memory operand read for INVEPT_ALL_CONTEXT.  Experimentally, this
   is how hardware behaves, and avoids an unnecessary pagewalk.
 * Reject Reg/Reg encodings of the instruction.
 * Audit eptp against maxphysaddr.
 * Introduce and use VMX_INSN_INVALID_INV_OPERAND to correct the vmfail
   semantics.
 * Add extra newlines for clarity

Also, introduce some TODOs for further checks which should be performed.
These checks are hard to perform at the moment, as there is no easy way to see
which MSR values where given to the guest.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Jun Nakajima <jun.nakajima@xxxxxxxxx>
CC: Kevin Tian <kevin.tian@xxxxxxxxx>

This patch conflicts textually but not functionally with Sergey's "x86/vmx:
introduce vmwrite_safe()".

The MSR checks will be resolved once the MSR Levelling work is started and the
configuration can be read out of the MSR policy block.
---
 xen/arch/x86/hvm/vmx/vvmx.c        | 43 ++++++++++++++++++++++++++++++++------
 xen/include/asm-x86/hvm/vmx/vmcs.h |  1 +
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 9caebe5..dfcc8a7 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1770,33 +1770,64 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs)
 
 int nvmx_handle_invept(struct cpu_user_regs *regs)
 {
+    struct vcpu *curr = current;
+    struct domain *currd = curr->domain;
     struct vmx_inst_decoded decode;
-    unsigned long eptp;
     int ret;
 
-    if ( (ret = decode_vmx_inst(regs, &decode, &eptp, 0)) != X86EMUL_OKAY )
+    if ( (ret = decode_vmx_inst(regs, &decode, NULL, 0)) != X86EMUL_OKAY )
         return ret;
 
+    /* TODO - reject instruction completely if not configured. */
+
+    /* Instruction must have a memory operand. */
+    if ( decode.type != VMX_INST_MEMREG_TYPE_MEMORY )
+    {
+        hvm_inject_hw_exception(TRAP_invalid_op, 0);
+        return X86EMUL_EXCEPTION;
+    }
+
     switch ( reg_read(regs, decode.reg2) )
     {
     case INVEPT_SINGLE_CONTEXT:
     {
-        struct p2m_domain *p2m = p2m_get_nestedp2m(current, eptp);
+        struct p2m_domain *p2m;
+        pagefault_info_t pfinfo;
+        unsigned long eptp;
+
+        /* TODO - reject SINGLE_CONTEXT if not configured. */
+
+        ret = hvm_copy_from_guest_linear(&eptp, decode.mem, 8, 0, &pfinfo);
+        if ( ret == HVMCOPY_bad_gva_to_gfn )
+            hvm_inject_page_fault(pfinfo.ec, pfinfo.linear);
+        if ( ret != HVMCOPY_okay )
+            return X86EMUL_EXCEPTION;
+
+        if ( eptp >> currd->arch.cpuid->extd.maxphysaddr )
+            goto reject;
+
+        /* TODO - audit lower eptp metadata against configuration. */
+
+        p2m = p2m_get_nestedp2m(curr, eptp);
         if ( p2m )
         {
-            p2m_flush(current, p2m);
+            p2m_flush(curr, p2m);
             ept_sync_domain(p2m);
         }
         break;
     }
+
     case INVEPT_ALL_CONTEXT:
-        p2m_flush_nestedp2m(current->domain);
+        p2m_flush_nestedp2m(curr->domain);
         __invept(INVEPT_ALL_CONTEXT, 0, 0);
         break;
+
+    reject:
     default:
-        vmfail_invalid(regs);
+        vmfail(regs, VMX_INSN_INVALID_INV_OPERAND);
         return X86EMUL_OKAY;
     }
+
     vmsucceed(regs);
     return X86EMUL_OKAY;
 }
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h 
b/xen/include/asm-x86/hvm/vmx/vmcs.h
index d71de04..309eaf0 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -526,6 +526,7 @@ enum vmx_insn_errno
     VMX_INSN_VMPTRLD_INVALID_PHYADDR       = 9,
     VMX_INSN_UNSUPPORTED_VMCS_COMPONENT    = 12,
     VMX_INSN_VMXON_IN_VMX_ROOT             = 15,
+    VMX_INSN_INVALID_INV_OPERAND           = 28,
 };
 
 void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr, int type);
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.