Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, boot: Fix word-size assumptions in has_eflag() inline asm

Commit dd78b97367bd575918204cc89107c1479d3fc1a7 ("x86, boot: Move CPU
flags out of cpucheck") introduced ambiguous inline asm in the
has_eflag() function. In 16-bit mode want the instruction to be
'pushfl', but we just say 'pushf' and hope the compiler does what we
wanted.

When building with 'clang -m16', it won't, because clang doesn't use
the horrid '.code16gcc' hack that even 'gcc -m16' uses internally.

Say what we mean and don't make the compiler make assumptions.

[ hpa: ideally we would be able to use the gcc %zN construct here, but
that is broken for 64-bit integers in gcc < 4.5.

The code with plain "pushf/popf" is fine for 32- or 64-bit mode, but
not for 16-bit mode; in 16-bit mode those are 16-bit instructions in
.code16 mode, and 32-bit instructions in .code16gcc mode. ]

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Link: http://lkml.kernel.org/r/1391079628.26079.82.camel@shinybook.infradead.org
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

authored by

David Woodhouse and committed by
H. Peter Anvin
5fbbc25a 4064e0ea

+20 -5
+20 -5
arch/x86/boot/cpuflags.c
··· 28 28 return fsw == 0 && (fcw & 0x103f) == 0x003f; 29 29 } 30 30 31 + /* 32 + * For building the 16-bit code we want to explicitly specify 32-bit 33 + * push/pop operations, rather than just saying 'pushf' or 'popf' and 34 + * letting the compiler choose. But this is also included from the 35 + * compressed/ directory where it may be 64-bit code, and thus needs 36 + * to be 'pushfq' or 'popfq' in that case. 37 + */ 38 + #ifdef __x86_64__ 39 + #define PUSHF "pushfq" 40 + #define POPF "popfq" 41 + #else 42 + #define PUSHF "pushfl" 43 + #define POPF "popfl" 44 + #endif 45 + 31 46 int has_eflag(unsigned long mask) 32 47 { 33 48 unsigned long f0, f1; 34 49 35 - asm volatile("pushf \n\t" 36 - "pushf \n\t" 50 + asm volatile(PUSHF " \n\t" 51 + PUSHF " \n\t" 37 52 "pop %0 \n\t" 38 53 "mov %0,%1 \n\t" 39 54 "xor %2,%1 \n\t" 40 55 "push %1 \n\t" 41 - "popf \n\t" 42 - "pushf \n\t" 56 + POPF " \n\t" 57 + PUSHF " \n\t" 43 58 "pop %1 \n\t" 44 - "popf" 59 + POPF 45 60 : "=&r" (f0), "=&r" (f1) 46 61 : "ri" (mask)); 47 62