diff options
-rw-r--r-- | arch/x86/boot/cpuflags.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c index a9fcb7cfb241..431fa5f84537 100644 --- a/arch/x86/boot/cpuflags.c +++ b/arch/x86/boot/cpuflags.c | |||
@@ -28,20 +28,35 @@ static int has_fpu(void) | |||
28 | return fsw == 0 && (fcw & 0x103f) == 0x003f; | 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 | int has_eflag(unsigned long mask) | 46 | int has_eflag(unsigned long mask) |
32 | { | 47 | { |
33 | unsigned long f0, f1; | 48 | unsigned long f0, f1; |
34 | 49 | ||
35 | asm volatile("pushf \n\t" | 50 | asm volatile(PUSHF " \n\t" |
36 | "pushf \n\t" | 51 | PUSHF " \n\t" |
37 | "pop %0 \n\t" | 52 | "pop %0 \n\t" |
38 | "mov %0,%1 \n\t" | 53 | "mov %0,%1 \n\t" |
39 | "xor %2,%1 \n\t" | 54 | "xor %2,%1 \n\t" |
40 | "push %1 \n\t" | 55 | "push %1 \n\t" |
41 | "popf \n\t" | 56 | POPF " \n\t" |
42 | "pushf \n\t" | 57 | PUSHF " \n\t" |
43 | "pop %1 \n\t" | 58 | "pop %1 \n\t" |
44 | "popf" | 59 | POPF |
45 | : "=&r" (f0), "=&r" (f1) | 60 | : "=&r" (f0), "=&r" (f1) |
46 | : "ri" (mask)); | 61 | : "ri" (mask)); |
47 | 62 | ||