x86/vmx: improve vmread_safe()
authorSergey Dyasli <sergey.dyasli@citrix.com>
Thu, 9 Feb 2017 10:07:31 +0000 (11:07 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 9 Feb 2017 10:07:31 +0000 (11:07 +0100)
The original function doesn't distinguish between Valid and Invalid
VMfails.  Improved function returns error code depending on the outcome:

        VMsucceed: 0
      VMfailValid: VM Instruction Error Number
    VMfailInvalid: VMX_INSN_FAIL_INVALID (~0)

Existing users of __vmread_safe() are updated and double underscore
prefix is removed from the function's name because such prefixes are
reserved to a compiler.

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Kevin Tian <kevin.tian@intel.com>
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vvmx.c
xen/include/asm-x86/hvm/vmx/vmx.h

index 3fe1783edbf73a5324ab0bf4d04b1f3298bb2cd3..0b77dbc088837e7784f035413e9d3c6a46639203 100644 (file)
@@ -1711,7 +1711,7 @@ static inline unsigned long vmr(unsigned long field)
 {
     unsigned long val;
 
-    return __vmread_safe(field, &val) ? val : 0;
+    return vmread_safe(field, &val) ? 0 : val;
 }
 
 #define vmr16(fld) ({             \
index a3929b09b0ebda82c6253575fea5f95a4beb0570..9c61b5bbac55e17dd6d531fd75806bf27c5a7594 100644 (file)
@@ -932,7 +932,7 @@ static inline void shadow_to_vvmcs(const struct vcpu *v, unsigned int field)
 {
     unsigned long value;
 
-    if ( __vmread_safe(field, &value) )
+    if ( vmread_safe(field, &value) == 0 )
         set_vvmcs(v, field, value);
 }
 
index 9bfe71a064c701758b774ae87aa04a5362bbdefe..3e809d4417a4e5a84e9ddfb80f28b16a4c3c48c5 100644 (file)
@@ -401,32 +401,27 @@ static always_inline void __vmwrite(unsigned long field, unsigned long value)
         );
 }
 
-static inline bool_t __vmread_safe(unsigned long field, unsigned long *value)
+static inline enum vmx_insn_errno vmread_safe(unsigned long field,
+                                              unsigned long *value)
 {
-    bool_t okay;
+    unsigned long ret = 0;
+    bool fail_invalid, fail_valid;
 
-    asm volatile (
-#ifdef HAVE_GAS_VMX
-                   "vmread %2, %1\n\t"
-#else
-                   VMREAD_OPCODE MODRM_EAX_ECX
-#endif
-                   /* CF==1 or ZF==1 --> rc = 0 */
-#ifdef __GCC_ASM_FLAG_OUTPUTS__
-                   : "=@ccnbe" (okay),
-#else
-                   "setnbe %0"
-                   : "=qm" (okay),
-#endif
-#ifdef HAVE_GAS_VMX
-                     "=rm" (*value)
-                   : "r" (field));
-#else
-                     "=c" (*value)
-                   : "a" (field));
-#endif
+    asm volatile ( GAS_VMX_OP("vmread %[field], %[value]\n\t",
+                              VMREAD_OPCODE MODRM_EAX_ECX)
+                   ASM_FLAG_OUT(, "setc %[invalid]\n\t")
+                   ASM_FLAG_OUT(, "setz %[valid]\n\t")
+                   : ASM_FLAG_OUT("=@ccc", [invalid] "=rm") (fail_invalid),
+                     ASM_FLAG_OUT("=@ccz", [valid] "=rm") (fail_valid),
+                     [value] GAS_VMX_OP("=rm", "=c") (*value)
+                   : [field] GAS_VMX_OP("r", "a") (field));
+
+    if ( unlikely(fail_invalid) )
+        ret = VMX_INSN_FAIL_INVALID;
+    else if ( unlikely(fail_valid) )
+        __vmread(VM_INSTRUCTION_ERROR, &ret);
 
-    return okay;
+    return ret;
 }
 
 static inline enum vmx_insn_errno vmwrite_safe(unsigned long field,