mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
libx86: Work around GCC being unable to spill the PIC hard register
Versions of GCC before 5 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"
^
See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54232 for more details.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
86d47adcd3
commit
73ee557408
1 file changed
+34
-4
@@ -20,21 +20,51 @@ struct cpuid_leaf
|
||||
uint32_t a, b, c, d;
|
||||
};
|
||||
|
||||
/*
|
||||
* Versions of GCC before 5 unconditionally reserve %rBX as the PIC hard
|
||||
* register, and are unable to cope with spilling it. This results in a
|
||||
* rather cryptic error:
|
||||
* error: inconsistent operand constraints in an ‘asm’
|
||||
*
|
||||
* In affected situations, work around the issue by using a separate register
|
||||
* to hold the the %rBX output, and xchg twice to leave %rBX preserved around
|
||||
* the asm() statement.
|
||||
*/
|
||||
#if defined(__PIC__) && __GNUC__ < 5 && !defined(__clang__) && defined(__i386__)
|
||||
# define XCHG_BX "xchg %%ebx, %[bx];"
|
||||
# define BX_CON [bx] "=&r"
|
||||
#elif defined(__PIC__) && __GNUC__ < 5 && !defined(__clang__) && \
|
||||
defined(__x86_64__) && (defined(__code_model_medium__) || \
|
||||
defined(__code_model_large__))
|
||||
# define XCHG_BX "xchg %%rbx, %q[bx];"
|
||||
# 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)
|
||||
: "a" (leaf) );
|
||||
}
|
||||
|
||||
static inline void cpuid_count_leaf(
|
||||
uint32_t leaf, uint32_t subleaf, 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)
|
||||
: "a" (leaf), "c" (subleaf) );
|
||||
}
|
||||
|
||||
#undef BX_CON
|
||||
#undef XCHG
|
||||
|
||||
#define CPUID_GUEST_NR_BASIC (0xdu + 1)
|
||||
#define CPUID_GUEST_NR_FEAT (0u + 1)
|
||||
#define CPUID_GUEST_NR_CACHE (5u + 1)
|
||||
|
||||