aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-09-09 10:23:32 +0200
committerJan Beulich <jbeulich@suse.com>2013-09-09 10:23:32 +0200
commitcfd54835e6e8a28c743dc7d67c662d151ab4923a (patch)
tree6a6b59ceee96950731f928c70c81581d4b1bf54d /xen/include/asm-x86
parentb0df10407df96fe25f3c1a2bffc4be0696d328b4 (diff)
downloadxen-cfd54835e6e8a28c743dc7d67c662d151ab4923a.tar.gz
xen-cfd54835e6e8a28c743dc7d67c662d151ab4923a.tar.bz2
xen-cfd54835e6e8a28c743dc7d67c662d151ab4923a.zip
VMX: use proper instruction mnemonics if assembler supports them
With the hex byte emission we were taking away a good part of flexibility from the compiler, as for simplicity reasons these were built using fixed operands. All half way modern build environments would allow using the mnemonics (but we can't disable the hex variants yet, since the binutils around at the time gcc 4.1 got released didn't support these yet). I didn't convert __vmread() yet because that would, just like for __vmread_safe(), imply converting to a macro so that the output operand can be the caller supplied variable rather than an intermediate one. As that would require touching all invocation points of __vmread() (of which there are quite a few), I'd first like to be certain the approach is acceptable; the main question being whether the now conditional code might be considered to cause future maintenance issues, and the second being that of parameter/argument ordering (here I made __vmread_safe() match __vmwrite(), but one could also take the position that read and write should use the inverse order of one another, in line with the actual instruction operands). Additionally I was quite puzzled to find that all the asm()-s involved here have memory clobbers - what are they needed for? Or can they be dropped at least in some cases? Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'xen/include/asm-x86')
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h90
1 files changed, 70 insertions, 20 deletions
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index a7b667e31e..9816ce4dce 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -282,27 +282,43 @@ extern uint8_t posted_intr_vector;
static inline void __vmptrld(u64 addr)
{
- asm volatile ( VMPTRLD_OPCODE
- MODRM_EAX_06
+ asm volatile (
+#ifdef HAVE_GAS_VMX
+ "vmptrld %0\n"
+#else
+ VMPTRLD_OPCODE MODRM_EAX_06
+#endif
/* CF==1 or ZF==1 --> crash (ud2) */
UNLIKELY_START(be, vmptrld)
"\tud2\n"
UNLIKELY_END_SECTION
:
+#ifdef HAVE_GAS_VMX
+ : "m" (addr)
+#else
: "a" (&addr)
+#endif
: "memory");
}
static inline void __vmpclear(u64 addr)
{
- asm volatile ( VMCLEAR_OPCODE
- MODRM_EAX_06
+ asm volatile (
+#ifdef HAVE_GAS_VMX
+ "vmclear %0\n"
+#else
+ VMCLEAR_OPCODE MODRM_EAX_06
+#endif
/* CF==1 or ZF==1 --> crash (ud2) */
UNLIKELY_START(be, vmclear)
"\tud2\n"
UNLIKELY_END_SECTION
:
+#ifdef HAVE_GAS_VMX
+ : "m" (addr)
+#else
: "a" (&addr)
+#endif
: "memory");
}
@@ -325,33 +341,50 @@ static inline unsigned long __vmread(unsigned long field)
static inline void __vmwrite(unsigned long field, unsigned long value)
{
- asm volatile ( VMWRITE_OPCODE
- MODRM_EAX_ECX
+ asm volatile (
+#ifdef HAVE_GAS_VMX
+ "vmwrite %1, %0\n"
+#else
+ VMWRITE_OPCODE MODRM_EAX_ECX
+#endif
/* CF==1 or ZF==1 --> crash (ud2) */
UNLIKELY_START(be, vmwrite)
"\tud2\n"
UNLIKELY_END_SECTION
:
+#ifdef HAVE_GAS_VMX
+ : "r" (field) , "rm" (value)
+#else
: "a" (field) , "c" (value)
+#endif
: "memory");
}
-static inline unsigned long __vmread_safe(unsigned long field, int *error)
+static inline bool_t __vmread_safe(unsigned long field, unsigned long *value)
{
- unsigned long ecx;
+ bool_t okay;
- asm volatile ( VMREAD_OPCODE
- MODRM_EAX_ECX
- /* CF==1 or ZF==1 --> rc = -1 */
- "setna %b0 ; neg %0"
- : "=q" (*error), "=c" (ecx)
- : "0" (0), "a" (field)
+ 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 */
+ "setnbe %0"
+#ifdef HAVE_GAS_VMX
+ : "=qm" (okay), "=rm" (*value)
+ : "r" (field)
+#else
+ : "=qm" (okay), "=c" (*value)
+ : "a" (field)
+#endif
: "memory");
- return ecx;
+ return okay;
}
-static inline void __invept(int type, u64 eptp, u64 gpa)
+static inline void __invept(unsigned long type, u64 eptp, u64 gpa)
{
struct {
u64 eptp, gpa;
@@ -365,18 +398,26 @@ static inline void __invept(int type, u64 eptp, u64 gpa)
!cpu_has_vmx_ept_invept_single_context )
type = INVEPT_ALL_CONTEXT;
- asm volatile ( INVEPT_OPCODE
- MODRM_EAX_08
+ asm volatile (
+#ifdef HAVE_GAS_EPT
+ "invept %0, %1\n"
+#else
+ INVEPT_OPCODE MODRM_EAX_08
+#endif
/* CF==1 or ZF==1 --> crash (ud2) */
UNLIKELY_START(be, invept)
"\tud2\n"
UNLIKELY_END_SECTION
:
+#ifdef HAVE_GAS_EPT
+ : "m" (operand), "r" (type)
+#else
: "a" (&operand), "c" (type)
+#endif
: "memory" );
}
-static inline void __invvpid(int type, u16 vpid, u64 gva)
+static inline void __invvpid(unsigned long type, u16 vpid, u64 gva)
{
struct {
u64 vpid:16;
@@ -385,7 +426,12 @@ static inline void __invvpid(int type, u16 vpid, u64 gva)
} __attribute__ ((packed)) operand = {vpid, 0, gva};
/* Fix up #UD exceptions which occur when TLBs are flushed before VMXON. */
- asm volatile ( "1: " INVVPID_OPCODE MODRM_EAX_08
+ asm volatile ( "1: "
+#ifdef HAVE_GAS_EPT
+ "invvpid %0, %1\n"
+#else
+ INVVPID_OPCODE MODRM_EAX_08
+#endif
/* CF==1 or ZF==1 --> crash (ud2) */
UNLIKELY_START(be, invvpid)
"\tud2\n"
@@ -393,7 +439,11 @@ static inline void __invvpid(int type, u16 vpid, u64 gva)
"2:"
_ASM_EXTABLE(1b, 2b)
:
+#ifdef HAVE_GAS_EPT
+ : "m" (operand), "r" (type)
+#else
: "a" (&operand), "c" (type)
+#endif
: "memory" );
}