From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: xen-devel <xen-devel@lists.xenproject.org>,
Keir Fraser <keir@xen.org>, Eddie Dong <eddie.dong@intel.com>,
Jun Nakajima <jun.nakajima@intel.com>
Subject: Re: [PATCH 3/4] VMX: use proper instruction mnemonics if assembler supports them
Date: Sat, 24 Aug 2013 23:18:48 +0100 [thread overview]
Message-ID: <52193148.2090601@citrix.com> (raw)
In-Reply-To: <521787C602000078000EE07F@nat28.tlf.novell.com>
[-- Attachment #1.1: Type: text/plain, Size: 11040 bytes --]
On 23/08/2013 15:03, Jan Beulich wrote:
> 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>
I certainly like and encourage of the idea of getting rid of the fixed
registers due to the hex literals. However, are macros really the
correct solution?
__vmread_safe(field, value) now has non-function like semantics for value.
To me, the more obvious (and as far as I can tell, functionally
identical) approach would be for
unsigned long always_inline __vmread_safe(unsigned long field, unsigned
long *value)
The compiler, given the correct constraints for value could resolve the
pointer back to the caller as it inlined the function, and calls would
look like "__vmread_safe(field, &value);" which looks rather more natural.
As for the memory clobbers, I see no indication from the VMX instruction
reference that vmread or inv{ept,vpid} have relevant side effects
requiring a clobber. For the load functions and vmwrite, there is a
possibilty of a memory clobber if someone has peaked into the relevant
VMCS page(s). However, doing so defeats the purpose of vmread/write, so
as far as I can tell, we could argue away the clobbers on those grounds
alone.
~Andrew
>
> --- a/Config.mk
> +++ b/Config.mk
> @@ -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)"; \
> --- 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
> --- 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)
> --- a/xen/arch/x86/hvm/vmx/vvmx.c
> +++ b/xen/arch/x86/hvm/vmx/vvmx.c
> @@ -951,13 +951,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;
>
> - value = __vmread_safe(field, &rc);
> - if ( !rc )
> + if ( __vmread_safe(field, value) )
> __set_vvmcs(vvmcs, field, value);
> }
>
> --- a/xen/include/asm-x86/hvm/vmx/vmx.h
> +++ b/xen/include/asm-x86/hvm/vmx/vmx.h
> @@ -282,27 +282,44 @@ 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,31 +342,58 @@ static inline unsigned long __vmread(uns
>
> 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)
> -{
> - unsigned long ecx;
> -
> - 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)
> - : "memory");
> -
> - return ecx;
> -}
> +#ifdef HAVE_GAS_VMX
> +#define __vmread_safe(field, value) ({ \
> + bool_t okay_; \
> + if ( sizeof(value) == sizeof(long) ) \
> + asm volatile ( "vmread %q2, %1\n\t" \
> + /* CF==1 or ZF==1 --> rc = 0 */ \
> + "setnbe %0" \
> + : "=qm" (okay_), "=rm" (value) \
> + : "r" (field) \
> + : "memory"); \
> + else \
> + { \
> + asm volatile ( "vmread %q2, %q1\n\t" \
> + /* CF==1 or ZF==1 --> rc = 0 */ \
> + "setnbe %0" \
> + : "=qm" (okay_), "=r" (value) \
> + : "r" (field) \
> + : "memory"); \
> + } \
> + okay_; \
> +})
> +#else
> +#define __vmread_safe(field, value) ({ \
> + bool_t okay_; \
> + asm volatile ( VMREAD_OPCODE MODRM_EAX_ECX \
> + /* CF==1 or ZF==1 --> rc = 0 */ \
> + "setnbe %0" \
> + : "=qm" (okay_), "=c" (value) \
> + : "a" (field) \
> + : "memory"); \
> + okay_; \
> +})
> +#endif
>
> static inline void __invept(int type, u64 eptp, u64 gpa)
> {
> @@ -365,14 +409,22 @@ static inline void __invept(int type, u6
> !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, %q1\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" );
> }
>
> @@ -385,14 +437,23 @@ static inline void __invvpid(int type, u
> } __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, %q1\n"
> +#else
> + INVVPID_OPCODE MODRM_EAX_08
> +#endif
> /* CF==1 or ZF==1 --> crash (ud2) */
> "2: " UNLIKELY_START(be, invvpid)
> "\tud2\n"
> UNLIKELY_END_SECTION "\n"
> _ASM_EXTABLE(1b, 2b)
> :
> +#ifdef HAVE_GAS_EPT
> + : "m" (operand), "r" (type)
> +#else
> : "a" (&operand), "c" (type)
> +#endif
> : "memory" );
> }
>
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
[-- Attachment #1.2: Type: text/html, Size: 11551 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2013-08-24 22:18 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-23 13:58 [PATCH 0/4] HVM: produce better binary code Jan Beulich
2013-08-23 14:01 ` [PATCH 1/4] VMX: streamline entry.S code Jan Beulich
2013-08-26 10:44 ` Andrew Cooper
2013-08-26 11:01 ` Jan Beulich
2013-08-26 11:48 ` Andrew Cooper
2013-08-26 13:12 ` Jan Beulich
2013-08-26 13:22 ` Andrew Cooper
2013-08-29 11:01 ` Tim Deegan
2013-08-29 12:35 ` Jan Beulich
2013-08-23 14:02 ` [PATCH 2/4] VMX: move various uses of UD2 out of fast paths Jan Beulich
2013-08-23 22:06 ` Andrew Cooper
2013-08-26 8:50 ` Jan Beulich
2013-08-26 9:07 ` Andrew Cooper
2013-08-26 8:58 ` [PATCH v2 " Jan Beulich
2013-08-26 9:09 ` Andrew Cooper
2013-08-29 11:08 ` Tim Deegan
2013-08-23 14:03 ` [PATCH 3/4] VMX: use proper instruction mnemonics if assembler supports them Jan Beulich
2013-08-24 22:18 ` Andrew Cooper [this message]
2013-08-26 9:06 ` Jan Beulich
2013-08-26 9:25 ` Andrew Cooper
2013-08-26 9:41 ` Jan Beulich
2013-08-26 10:18 ` [PATCH v3 " Jan Beulich
2013-08-26 13:05 ` Andrew Cooper
2013-08-26 13:20 ` Jan Beulich
2013-08-26 14:03 ` [PATCH v4 " Jan Beulich
2013-08-26 14:18 ` Andrew Cooper
2013-08-26 14:29 ` Jan Beulich
2013-08-26 15:07 ` Andrew Cooper
2013-08-26 15:10 ` Andrew Cooper
2013-08-26 15:30 ` Jan Beulich
2013-08-26 15:29 ` Jan Beulich
2013-08-26 15:33 ` Andrew Cooper
2013-08-26 15:31 ` [PATCH v5 " Jan Beulich
2013-08-26 15:36 ` Andrew Cooper
2013-08-29 11:47 ` Tim Deegan
2013-08-29 12:30 ` Jan Beulich
2013-08-29 13:11 ` Tim Deegan
2013-08-29 13:27 ` Jan Beulich
2013-08-29 14:02 ` Tim Deegan
2013-08-29 12:45 ` Jan Beulich
2013-08-29 13:19 ` Tim Deegan
2013-08-26 9:03 ` [PATCH v2 " Jan Beulich
2013-08-23 14:04 ` [PATCH 4/4] SVM: streamline entry.S code Jan Beulich
2013-08-26 16:20 ` Andrew Cooper
2013-08-26 17:20 ` Keir Fraser
2013-08-26 17:46 ` Andrew Cooper
2013-08-26 21:47 ` Andrew Cooper
2013-08-27 7:38 ` Jan Beulich
2013-08-29 11:56 ` Tim Deegan
2013-09-04 14:39 ` Boris Ostrovsky
2013-09-04 14:50 ` Jan Beulich
2013-09-04 15:09 ` Boris Ostrovsky
2013-09-04 15:20 ` Jan Beulich
2013-09-04 16:42 ` Boris Ostrovsky
2013-09-05 7:10 ` Jan Beulich
2013-09-04 10:06 ` Ping: [PATCH 0/4] HVM: produce better binary code Jan Beulich
2013-09-04 16:16 ` Andrew Cooper
2013-09-04 16:30 ` Tim Deegan
2013-09-05 7:52 ` Jan Beulich
2013-09-05 7:58 ` Tim Deegan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52193148.2090601@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=eddie.dong@intel.com \
--cc=jun.nakajima@intel.com \
--cc=keir@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.