diff options
-rw-r--r-- | Config.mk | 21 | ||||
-rw-r--r-- | xen/arch/x86/Rules.mk | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 7 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vvmx.c | 8 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vmx/vmx.h | 90 |
5 files changed, 99 insertions, 29 deletions
@@ -4,6 +4,12 @@ ifeq ($(filter /%,$(XEN_ROOT)),) $(error XEN_ROOT must be absolute) endif +# Convenient variables +comma := , +squote := ' +empty := +space := $(empty) $(empty) + # fallback for older make realpath = $(wildcard $(foreach file,$(1),$(shell cd -P $(dir $(file)) && echo "$$PWD/$(notdir $(file))"))) @@ -128,6 +134,21 @@ endef check-$(gcc) = $(call cc-ver-check,CC,0x040100,"Xen requires at least gcc-4.1") $(eval $(check-y)) +# as-insn: Check whether assembler supports an instruction. +# Usage: cflags-y += $(call as-insn "insn",option-yes,option-no) +as-insn = $(if $(shell echo 'void _(void) { asm volatile ( $(2) ); }' \ + | $(1) -c -x c -o /dev/null - 2>&1),$(4),$(3)) + +# as-insn-check: Add an option to compilation flags, but only if insn is +# supported by assembler. +# Usage: $(call as-insn-check CFLAGS,CC,"nop",-DHAVE_GAS_NOP) +as-insn-check = $(eval $(call as-insn-check-closure,$(1),$(2),$(3),$(4))) +define as-insn-check-closure + ifeq ($$(call as-insn,$$($(2)),$(3),y,n),y) + $(1) += $(4) + endif +endef + define buildmakevars2shellvars export PREFIX="$(PREFIX)"; \ export XEN_SCRIPT_DIR="$(XEN_SCRIPT_DIR)"; \ diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 04c1a90477..eb11b5bffb 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -28,6 +28,8 @@ CFLAGS += -msoft-float $(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS)) $(call cc-option-add,CFLAGS,CC,-Wnested-externs) +$(call as-insn-check,CFLAGS,CC,"vmcall",-DHAVE_GAS_VMX) +$(call as-insn-check,CFLAGS,CC,"invept (%rax)$$(comma)%rax",-DHAVE_GAS_EPT) ifeq ($(supervisor_mode_kernel),y) CFLAGS += -DCONFIG_X86_SUPERVISOR_MODE_KERNEL=1 diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 31347bb014..0b40b546f6 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -1292,12 +1292,11 @@ void vmx_do_resume(struct vcpu *v) reset_stack_and_jump(vmx_asm_do_vmentry); } -static unsigned long vmr(unsigned long field) +static inline unsigned long vmr(unsigned long field) { - int rc; unsigned long val; - val = __vmread_safe(field, &rc); - return rc ? 0 : val; + + return __vmread_safe(field, &val) ? val : 0; } static void vmx_dump_sel(char *name, uint32_t selector) diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index cecc72f053..5ef5ad7385 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -963,13 +963,11 @@ fallback: vvmcs_to_shadow(vvmcs, field[i]); } -static void shadow_to_vvmcs(void *vvmcs, unsigned int field) +static inline void shadow_to_vvmcs(void *vvmcs, unsigned int field) { - u64 value; - int rc; + unsigned long value; - value = __vmread_safe(field, &rc); - if ( !rc ) + if ( __vmread_safe(field, &value) ) __set_vvmcs(vvmcs, field, value); } 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" ); } |