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

Re: [Xen-devel] [PATCH] libx86: Work around GCC bug with ebx output constrants



>>> On 19.11.18 at 14:11, <andrew.cooper3@xxxxxxxxxx> wrote:
> Some versions of GCC can't compile cpuid.c, and fail with the rather cryptic:
> 
>   In file included from lib/x86/cpuid.c:3:0:
>   lib/x86/cpuid.c: In function ‘x86_cpuid_policy_fill_native’:
>   include/xen/lib/x86/cpuid.h:25:5: error: inconsistent operand constraints 
> in an ‘asm’
>        asm ( "cpuid"
>        ^

And indeed the version I've seen this with (4.3; I wrongly said "newer"
on irc) does slightly better: "can't find a register in class 'BREG' while
reloading 'asm'" (followed again by an "impossible constraint" one).

> In practice, this is a collision between the output constraint and the GOT
> which is held in %ebx when compiling with -fPIC for libraries.
> 
> This affects at least GCC 4.9 as shipped in Debian Jessie, but experimentally
> is fixed in GCC 6 and later.  Curiously, it only affects 32-bit builds.

I don't think there's anything curious here: The GOT (or actually
.rodata here) gets accessed by %rip-relative addressing in small
model 64-bit code, iirc.

> --- a/xen/include/xen/lib/x86/cpuid.h
> +++ b/xen/include/xen/lib/x86/cpuid.h
> @@ -20,21 +20,48 @@ struct cpuid_leaf
>      uint32_t a, b, c, d;
>  };
>  
> +/*
> + * Some versions of GCC are unable to cope with preserving the GOT (held in
> + * %ebx) around an asm() with an %ebx output constraint, and produce a rather
> + * cryptic error:
> + *    error: inconsistent operand constraints in an ‘asm’
> + *
> + * Experimentally, 64-bit builds work correctly, and 32-bit builds on GCC 6 
> or
> + * later work correctly.
> + *
> + * To work around the issue, use a separate register to hold the the ebx
> + * output, and xchg twice to leave %ebx preserved around the asm() statement.
> + */
> +#if __PIC__ && __i386__ && __GNUC__ < 6 && !__clang__

I think you're missing a bunch of defined() here.

> +#define XCHG_BX "xchg %%ebx, %k[bx];"

I don't think the k modifier is actually needed?

> +#define BX_CON [bx] "=&r"
> +#else
> +#define XCHG_BX ""
> +#define BX_CON "=b"
> +#endif
> +
>  static inline void cpuid_leaf(uint32_t leaf, struct cpuid_leaf *l)
>  {
> -    asm ( "cpuid"
> -          : "=a" (l->a), "=b" (l->b), "=c" (l->c), "=d" (l->d)
> +    asm ( XCHG_BX
> +          "cpuid;"
> +          XCHG_BX
> +          : "=a" (l->a), BX_CON (l->b), "=c" (l->c), "=d" (l->d)

Strictly speaking all other outputs also need to use =& in the
32-bit case. But I wouldn't insist on such an adjustment. With
the others done
Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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