x86: static_cpu_has_safe: discard dynamic check after init
Subsystems (14)
PATCH 1/1 x86: static_cpu_has_safe: discard dynamic check after init
Move the code to do the dynamic check to the init text section so that it is discarded after alternatives have run and a static branch has been chosen.
A new section is defined to avoid warnings with modpost due to references to init text from main text, which in this case is legitimate. All such references are patched out before init mem is discarded.
--- arch/x86/include/asm/cpufeature.h | 33 ++++++++++++++++++++++----------- arch/x86/kernel/cpu/common.c | 6 ------ arch/x86/kernel/vmlinux.lds.S | 6 ++++++ 3 files changed, 28 insertions(+), 17 deletions(-)
arch/x86/include/asm/cpufeature.h +22 -11
@@ -412,7 +412,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS )extern void warn_pre_alternatives (void ); -extern bool __static_cpu_has_safe (u16 bit);/* * Static testing of CPU features. Used the same as boot_cpu_has().
@@ -502,10 +501,10 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) boot_cpu_has(bit) \ ) -static __always_inline __pure bool _static_cpu_has_safe(u16 bit) +static __always_inline __pure bool _static_cpu_has_safe(u16 bit, __u32 *caps) {#ifdef CC_HAVE_ASM_GOTO -asm_volatile_goto ("1: jmp %l[t_dynamic]\n" +asm_volatile_goto ("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n"
@@ -530,17 +529,22 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)" .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); +".section .static_cpu_has,\"ax\"\n" +"6: testl %2,%3\n" +" jnz %l[t_yes]\n" +" jmp %l[t_no]\n" +".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), +"i" (1 << (bit &31 )),"m" (caps[bit/32 ]) + : : t_yes, t_no); + t_yes:return true; t_no:return false; - t_dynamic: -return __static_cpu_has_safe (bit);#else u8 flag;/* Open-coded due to __stringify() in ALTERNATIVE() */ - asmvolatile ("1: movb $2,%0\n" + asmvolatile ("1: jmp 7f\n" "2:\n" ".section .altinstructions,\"a\"\n" " .long 1b - .\n" /* src offset */
@@ -572,9 +576,15 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) "5: movb $1,%0\n" "6:\n" ".previous\n" + ".section .static_cpu_has,\"ax\"\n" + "7: testl %3,%4\n" + " setnz %0\n" + " jmp 2b\n" + ".previous\n" : "=qm" (flag) - : "i" (bit), "i" (X86_FEATURE_ALWAYS)); -return (flag ==2 ?__static_cpu_has_safe (bit) : flag); + : "i" (bit), "i" (X86_FEATURE_ALWAYS), + "i" (1 << (bit & 31)), "m" (caps[bit/32])); +return (flag !=0 );#endif /* CC_HAVE_ASM_GOTO */ }
@@ -582,7 +592,8 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) ( \__builtin_constant_p (boot_cpu_has (bit)) ? \boot_cpu_has (bit) : \ -_static_cpu_has_safe (bit) \ +_static_cpu_has_safe (bit, \ + &boot_cpu_data.x86_capability[0 ]) \ ) #else/*
arch/x86/kernel/cpu/common.c +0 -6
@@ -1483,12 +1483,6 @@ void warn_pre_alternatives(void)EXPORT_SYMBOL_GPL (warn_pre_alternatives);#endif -inline bool __static_cpu_has_safe (u16 bit) -{ -return boot_cpu_has (bit); -} -EXPORT_SYMBOL_GPL (__static_cpu_has_safe); -static void bsp_resume (void ) {if (this_cpu->c_bsp_resume)
arch/x86/kernel/vmlinux.lds.S +6 -0
@@ -195,6 +195,12 @@ SECTIONS :init #endif + .static_cpu_has : AT(ADDR(.static_cpu_has) - LOAD_OFFSET) { + __static_cpu_has_start = .; + *(.static_cpu_has) + __static_cpu_has_end = .; + } + INIT_DATA_SECTION(16) .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
Signature · 1 line
2.5.0
Quoted 7 lines · Brian Gerst
Move the code to do the dynamic check to the init text section so that it is discarded after alternatives have run and a static branch has been chosen.
A new section is defined to avoid warnings with modpost due to references to init text from main text, which in this case is legitimate. All such references are patched out before init mem is discarded.
And we're doing this because...? Space savings? How much are we talkin'?
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 10 lines · Borislav Petkov
Quoted 7 lines · Brian Gerst
Move the code to do the dynamic check to the init text section so that it is discarded after alternatives have run and a static branch has been chosen.
A new section is defined to avoid warnings with modpost due to references to init text from main text, which in this case is legitimate. All such references are patched out before init mem is discarded.
And we're doing this because...? Space savings? How much are we talkin'?
It saves space. The only thing left in main text is one jump instruction (5 bytes).
The old t_dynamic branch looked something like this (26 bytes in .text, not discarded):
553: bf 7d 00 00 00 mov $0x7d,%edi
558: 48 89 4d c8 mov %rcx,-0x38(%rbp)
55c: e8 00 00 00 00 callq 561 <__switch_to+0xf1>
55d: R_X86_64_PC32 __static_cpu_has_safe-0x4
561: 84 c0 test %al,%al
563: 48 8b 4d c8 mov -0x38(%rbp),%rcx
567: 0f 85 77 01 00 00 jne 6e4 <__switch_to+0x274>New (21 bytes, discarded after init):
0: f7 05 00 00 00 00 00 testl $0x20000000,0x0(%rip) #
a <.static_cpu_has+0xa>
7: 00 00 20
2: R_X86_64_PC32 boot_cpu_data+0x18
a: 0f 85 00 00 00 00 jne 10 <.static_cpu_has+0x10>
c: R_X86_64_PC32 .text+0x4b9
10: e9 00 00 00 00 jmpq 15 <.static_cpu_has+0x15>
11: R_X86_64_PC32 .text+0x529--
Brian Gerst
Quoted 2 lines · Brian Gerst
It saves space. The only thing left in main text is one jump instruction (5 bytes).
How do I measure this?
Because with my tailored config here, the only thing I'm seeing is a growth of text by 730 bytes:
before:
text data bss dec hex filename
10926552 3598944 16642048 31167544 1db9438 vmlinux
[ 0.056552] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 2.883728] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)
after:
text data bss dec hex filename
10927282 3598944 16642048 31168274 1db9712 vmlinux
[ 0.052559] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 3.225318] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 17 lines · Borislav Petkov
Quoted 2 lines · Brian Gerst
It saves space. The only thing left in main text is one jump instruction (5 bytes).
How do I measure this?
Because with my tailored config here, the only thing I'm seeing is a growth of text by 730 bytes:
before:
text data bss dec hex filename
10926552 3598944 16642048 31167544 1db9438 vmlinux[ 0.056552] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 2.883728] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)
Quoted 6 lines
after:
text data bss dec hex filename
10927282 3598944 16642048 31168274 1db9712 vmlinux[ 0.052559] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 3.225318] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)
It is due to page alignment padding. It was not enough to lose a whole page from .text in your case.
The size command includes any section that is marked executable in the text count, including init text. If you use readelf -S vmlinux.o instead you will notice that .text is the same size or smaller, and .static_cpu_has (which is freed after boot) is the difference.
--
Brian Gerst
Quoted 25 lines · Brian Gerst
Quoted 17 lines · Borislav Petkov
Quoted 2 lines · Brian Gerst
It saves space. The only thing left in main text is one jump instruction (5 bytes).
How do I measure this?
Because with my tailored config here, the only thing I'm seeing is a growth of text by 730 bytes:
before:
text data bss dec hex filename
10926552 3598944 16642048 31167544 1db9438 vmlinux[ 0.056552] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 2.883728] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)Quoted 6 lines
after:
text data bss dec hex filename
10927282 3598944 16642048 31168274 1db9712 vmlinux[ 0.052559] Freeing SMP alternatives memory: 24K (ffffffff81dd7000 - ffffffff81ddd000) [ 3.225318] Freeing unused kernel memory: 2904K (ffffffff81b01000 - ffffffff81dd7000)
Quoted 8 lines
It is due to page alignment padding. It was not enough to lose a whole page from .text in your case.
The size command includes any section that is marked executable in the text count, including init text. If you use readelf -S vmlinux.o instead you will notice that .text is the same size or smaller, and .static_cpu_has (which is freed after boot) is the difference.
If I'm understanding this correctly, the total non-init overhead from static_cpu_has_safe with your patch is five bytes. I'd imagine that the short jmp optimization in regular static_cpu_has essentially never works, which means it will also use five bytes of text, which makes me wonder whether we should just make static_cpu_has safe and remove the distinction.
Also, someone should write a little script to measure kernel size minus .init stuff.
--Andy
Quoted 2 lines · Brian Gerst
It is due to page alignment padding. It was not enough to lose a whole page from .text in your case.
So nothing more got freed.
Quoted 4 lines
The size command includes any section that is marked executable in the text count, including init text. If you use readelf -S vmlinux.o instead you will notice that .text is the same size or smaller, and .static_cpu_has (which is freed after boot) is the difference.
So we're talking about less than a page here?
[19] .static_cpu_has PROGBITS ffffffff81d335d3 011335d3
00000000000002df 0000000000000000 AX 0 0 1
That's 479 bytes. Meh, it doesn't look like it is worth the trouble.
Maybe I should build an allyesconfig.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 11 lines · Borislav Petkov
Quoted 2 lines · Brian Gerst
It is due to page alignment padding. It was not enough to lose a whole page from .text in your case.
So nothing more got freed.
Quoted 4 lines
The size command includes any section that is marked executable in the text count, including init text. If you use readelf -S vmlinux.o instead you will notice that .text is the same size or smaller, and .static_cpu_has (which is freed after boot) is the difference.
Quoted 7 lines
So we're talking about less than a page here?
[19] .static_cpu_has PROGBITS
ffffffff81d335d3011335d300000000000002df 0000000000000000 AX 0 0 1That's 479 bytes. Meh, it doesn't look like it is worth the trouble.
I think that, if we can make static_cpu_has be unconditionally safe as a result and get rid of warn_pre_alternatives, then it is worth the trouble.
--Andy
Quoted 2 lines · Andy Lutomirski
I think that, if we can make
static_cpu_hasbe unconditionally safe as a result
Problem with this is the additional .altinstructions entry for X86_FEATURE_ALWAYS. And sometimes you don't really need to use the _safe variant when you know you're safe.
Quoted 1 line
and get rid of
warn_pre_alternatives,
That's off by default, behind CONFIG_X86_DEBUG_STATIC_CPU_HAS.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 8 lines · Borislav Petkov
Quoted 2 lines · Andy Lutomirski
I think that, if we can make
static_cpu_hasbe unconditionally safe as a resultProblem with this is the additional .altinstructions entry for
X86_FEATURE_ALWAYS. And sometimes you don't really need to use the_safevariant when you know you're safe.
I think the two-byte optimization is the real issue if there is one at all. I don't care about the inittext, and unless I'm misremembering completely altinstructions also get ejected.
So I don't personally object to killing off the unsafe variant.
-hpa
Quoted 2 lines · H. Peter Anvin
I think the two-byte optimization is the real issue if there is one at all.
Well, we do optimize the jumps for a couple releases now, see recompute_jump(). So we would always get the short JMP, if made possible by how gcc lays out the code so that the target is not far away. If the JMP to the dynamic branch doesn't get nopped out anyway, that is.
We have "debug-alternative" to dump exactly what happens during patching.
Quoted 2 lines
I don't care about the inittext, and unless I'm misremembering completely altinstructions also get ejected.
Ah yes, they do.
Quoted 1 line
So I don't personally object to killing off the unsafe variant.
Ok.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 14 lines · Borislav Petkov
Quoted 1 line · H. Peter Anvin
I think the two-byte optimization is the real issue if there is one
at
Quoted 1 line
all.
Well, we do optimize the jumps for a couple releases now, see
recompute_jump(). So we would always get the short JMP, if made possible
by how gcc lays out the code so that the target is not far away. If the JMP to the dynamic branch doesn't get nopped out anyway, that is.We have "debug-alternative" to dump exactly what happens during patching.
Quoted 8 lines
Quoted 2 lines
I don't care about the inittext, and unless I'm misremembering completely altinstructions also get ejected.
Ah yes, they do.
Quoted 1 line
So I don't personally object to killing off the unsafe variant.
Ok.
The optimization has always been there, the question is how often it actually kicks in.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 2 lines · H. Peter Anvin
The optimization has always been there, the question is how often it actually kicks in.
Luckily, I have this disassembler tool which dumps the alternatives sections in a more readable format. I can dump all the static_cpu_has() call sites tomorrow and we can see what gcc generates.
;-}
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 3 lines · Borislav Petkov
Luckily, I have this disassembler tool which dumps the alternatives sections in a more readable format. I can dump all the
static_cpu_has()call sites tomorrow and we can see what gcc generates.
Ok, below is the list of all 12(!) places where static_cpu_has() has generated a 2-byte JMP. Which has saved us a whopping 36 bytes! On an x86_64 allyesconfig!
Patch removing it below. I better look at a 32-bit allyesconfig too first, though.
old insn VA: 0xffffffff8146b5ac, CPU feat: X86_FEATURE_PCOMMIT, size: 2, padlen: 0 wmb_pmem:
ffffffff8146b5ac: eb 02 jmp ffffffff8146b5b0
repl insn: 0xffffffff8ca7c651, size: 0
old insn VA: 0xffffffff8200dcd6, CPU feat: X86_FEATURE_PCOMMIT, size: 2, padlen: 0 arch_has_wmb_pmem:
ffffffff8200dcd6: eb 02 jmp ffffffff8200dcda
repl insn: 0xffffffff8ca7ebd8, size: 0
old insn VA: 0xffffffff828afe51, CPU feat: X86_FEATURE_PCOMMIT, size: 2, padlen: 0 arch_has_wmb_pmem:
ffffffff828afe51: eb 02 jmp ffffffff828afe55
repl insn: 0xffffffff8ca80f98, size: 0
old insn VA: 0xffffffff81072f77, CPU feat: X86_FEATURE_NRIPS, size: 2, padlen: 0 rdpmc_interception:
ffffffff81072f77: eb 4d jmp ffffffff81072fc6
repl insn: 0xffffffff8ca79f6b, size: 0
old insn VA: 0xffffffff8107437d, CPU feat: X86_FEATURE_NRIPS, size: 2, padlen: 0 svm_queue_exception:
ffffffff8107437d: eb 6f jmp ffffffff810743ee
repl insn: 0xffffffff8ca79f9f, size: 0
old insn VA: 0xffffffff8107741b, CPU feat: X86_FEATURE_NRIPS, size: 2, padlen: 0 svm_check_intercept:
ffffffff8107741b: eb 67 jmp ffffffff81077484
repl insn: 0xffffffff8ca79fed, size: 0
old insn VA: 0xffffffff8107741b, CPU feat: X86_FEATURE_NRIPS, size: 2, padlen: 0 svm_check_intercept:
ffffffff8107741b: eb 67 jmp ffffffff81077484
repl insn: 0xffffffff8ca79fed, size: 0
old insn VA: 0xffffffff81075c4f, CPU feat: X86_FEATURE_TSCRATEMSR, size: 2, padlen: 0 svm_hardware_enable:
ffffffff81075c4f: eb 57 jmp ffffffff81075ca8
repl insn: 0xffffffff8ca79fb9, size: 0
old insn VA: 0xffffffff81072c00, CPU feat: X86_FEATURE_DECODEASSISTS, size: 2, padlen: 0 invlpg_interception:
ffffffff81072c00: eb 55 jmp ffffffff81072c57
repl insn: 0xffffffff8ca79f51, size: 0
old insn VA: 0xffffffff8107097c, CPU feat: X86_FEATURE_FLUSHBYASID, size: 2, padlen: 0 svm_flush_tlb:
ffffffff8107097c: eb 35 jmp ffffffff810709b3
repl insn: 0xffffffff8ca79ee9, size: 0
old insn VA: 0xffffffff8108c0d0, CPU feat: X86_BUG_SYSRET_SS_ATTRS, size: 2, padlen: 0 __switch_to:
ffffffff8108c0d0: eb 70 jmp ffffffff8108c142
repl insn: 0xffffffff8ca7a1a7, size: 0
old insn VA: 0xffffffff81075d90, CPU feat: X86_BUG_AMD_TLB_MMATCH, size: 2, padlen: 0 svm_hardware_enable:
ffffffff81075d90: eb 7c jmp ffffffff81075e0e
repl insn: 0xffffffff8ca79fd3, size: 0
---
arch/x86/Kconfig.debug +0 -10
@@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL
arch/x86/entry/common.c +1 -1
@@ -477,7 +477,7 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)* We don't allow syscalls at all from VM86 mode, but we still * need to check VM, because we might be returning from sys_vm86. */ -return static_cpu_has (X86_FEATURE_SEP ) && +return static_cpu_has_safe (X86_FEATURE_SEP ) && regs->cs == __USER_CS && regs->ss == __USER_DS && regs->ip == landing_pad && (regs->flags & (X86_EFLAGS_RF |X86_EFLAGS_TF |X86_EFLAGS_VM )) ==0 ;
arch/x86/include/asm/archrandom.h +2 -2
@@ -114,8 +114,8 @@ GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);#endif /* CONFIG_X86_64 */ -#define arch_has_random () static_cpu_has(X86_FEATURE_RDRAND) -#define arch_has_random_seed () static_cpu_has(X86_FEATURE_RDSEED) +#define arch_has_random () static_cpu_has_safe(X86_FEATURE_RDRAND) +#define arch_has_random_seed () static_cpu_has_safe(X86_FEATURE_RDSEED)#else
arch/x86/include/asm/cpufeature.h +0 -85
103 lines not on this page · raw message
arch/x86/include/asm/mwait.h +1 -1
@@ -96,7 +96,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)static inline void mwait_idle_with_hints (unsigned long eax,unsigned long ecx) {if (!current_set_polling_and_test ()) { -if (static_cpu_has_bug (X86_BUG_CLFLUSH_MONITOR )) { +if (static_cpu_has_bug_safe (X86_BUG_CLFLUSH_MONITOR )) {mb ();clflush ((void *)¤t_thread_info ()->flags);mb ();
arch/x86/include/asm/pmem.h +1 -1
@@ -142,7 +142,7 @@ static inline bool __arch_has_wmb_pmem(void)* We require that wmb() be an 'sfence', that is only guaranteed on * 64-bit builds */ -return static_cpu_has (X86_FEATURE_PCOMMIT ); +return static_cpu_has_safe (X86_FEATURE_PCOMMIT ); }#endif /* CONFIG_ARCH_HAS_PMEM_API */ #endif /* __ASM_X86_PMEM_H__ */
arch/x86/include/asm/qspinlock.h +1 -1
@@ -43,7 +43,7 @@ static inline void queued_spin_unlock(struct qspinlock *lock)#define virt_spin_lock virt_spin_lockstatic inline bool virt_spin_lock (struct qspinlock *lock) { -if (!static_cpu_has (X86_FEATURE_HYPERVISOR )) +if (!static_cpu_has_safe (X86_FEATURE_HYPERVISOR ))return false;/*
arch/x86/kernel/cpu/proc.c +5 -5
@@ -32,11 +32,11 @@ static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)"fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: %s\n" , -static_cpu_has_bug (X86_BUG_FDIV ) ?"yes" :"no" , -static_cpu_has_bug (X86_BUG_F00F ) ?"yes" :"no" , -static_cpu_has_bug (X86_BUG_COMA ) ?"yes" :"no" , -static_cpu_has (X86_FEATURE_FPU ) ?"yes" :"no" , -static_cpu_has (X86_FEATURE_FPU ) ?"yes" :"no" , +static_cpu_has_bug_safe (X86_BUG_FDIV ) ?"yes" :"no" , +static_cpu_has_bug_safe (X86_BUG_F00F ) ?"yes" :"no" , +static_cpu_has_bug_safe (X86_BUG_COMA ) ?"yes" :"no" , +static_cpu_has_safe (X86_FEATURE_FPU ) ?"yes" :"no" , +static_cpu_has_safe (X86_FEATURE_FPU ) ?"yes" :"no" , c->cpuid_level, c->wp_works_ok ? "yes" : "no"); }
arch/x86/kernel/fpu/regset.c +2 -2
@@ -275,7 +275,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset,fpu__activate_fpstate_read (fpu); -if (!static_cpu_has (X86_FEATURE_FPU )) +if (!static_cpu_has_safe (X86_FEATURE_FPU ))return fpregs_soft_get (target, regset, pos, count, kbuf, ubuf);if (!cpu_has_fxsr)
@@ -306,7 +306,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,fpu__activate_fpstate_write (fpu);fpstate_sanitize_xstate (fpu); -if (!static_cpu_has (X86_FEATURE_FPU )) +if (!static_cpu_has_safe (X86_FEATURE_FPU ))return fpregs_soft_set (target, regset, pos, count, kbuf, ubuf);if (!cpu_has_fxsr)
arch/x86/kernel/fpu/signal.c +2 -2
@@ -162,7 +162,7 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)if (!access_ok (VERIFY_WRITE , buf, size))return -EACCES ; -if (!static_cpu_has (X86_FEATURE_FPU )) +if (!static_cpu_has_safe (X86_FEATURE_FPU ))return fpregs_soft_get (current,NULL ,0 ,sizeof (struct user_i387_ia32_struct ),NULL , (struct _fpstate_32 __user *) buf) ?-1 :1 ;
@@ -267,7 +267,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)fpu__activate_curr (fpu); -if (!static_cpu_has (X86_FEATURE_FPU )) +if (!static_cpu_has_safe (X86_FEATURE_FPU ))return fpregs_soft_set (current,NULL ,0 ,sizeof (struct user_i387_ia32_struct ),NULL , buf) !=0 ;
arch/x86/kernel/process_64.c +1 -1
@@ -411,7 +411,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))__switch_to_xtra (prev_p, next_p, tss); -if (static_cpu_has_bug (X86_BUG_SYSRET_SS_ATTRS )) { +if (static_cpu_has_bug_safe (X86_BUG_SYSRET_SS_ATTRS )) {/* * AMD CPUs have a misfeature: SYSRET sets the SS selector but * does not update the cached descriptor. As a result, if we
arch/x86/kvm/cpuid.h +1 -1
@@ -32,7 +32,7 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) {struct kvm_cpuid_entry2 *best; -if (!static_cpu_has (X86_FEATURE_XSAVE )) +if (!static_cpu_has_safe (X86_FEATURE_XSAVE ))return false; best =kvm_find_cpuid_entry (vcpu,1 ,0 );
arch/x86/kvm/svm.c +12 -12
@@ -516,7 +516,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)struct vcpu_svm *svm =to_svm (vcpu);if (svm->vmcb->control.next_rip !=0 ) { -WARN_ON_ONCE (!static_cpu_has (X86_FEATURE_NRIPS )); +WARN_ON_ONCE (!static_cpu_has_safe (X86_FEATURE_NRIPS )); svm->next_rip = svm->vmcb->control.next_rip; }
@@ -548,7 +548,7 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr, nested_svm_check_exception(svm, nr, has_error_code, error_code)) return; -if (nr ==BP_VECTOR && !static_cpu_has (X86_FEATURE_NRIPS )) { +if (nr ==BP_VECTOR && !static_cpu_has_safe (X86_FEATURE_NRIPS )) {unsigned long rip, old_rip =kvm_rip_read (&svm->vcpu);/*
@@ -577,7 +577,7 @@ static void svm_init_erratum_383(void)int err;u64 val; -if (!static_cpu_has_bug (X86_BUG_AMD_TLB_MMATCH )) +if (!static_cpu_has_bug_safe (X86_BUG_AMD_TLB_MMATCH ))return ;/* Use _safe variants to not break nested virtualization */
@@ -631,7 +631,7 @@ static int has_svm(void)static void svm_hardware_disable (void ) {/* Make sure we clean up behind us */ -if (static_cpu_has (X86_FEATURE_TSCRATEMSR )) +if (static_cpu_has_safe (X86_FEATURE_TSCRATEMSR ))wrmsrl (MSR_AMD64_TSC_RATIO ,TSC_RATIO_DEFAULT );cpu_svm_disable ();
@@ -674,7 +674,7 @@ static int svm_hardware_enable(void)wrmsrl (MSR_VM_HSAVE_PA ,page_to_pfn (sd->save_area) <<PAGE_SHIFT ); -if (static_cpu_has (X86_FEATURE_TSCRATEMSR )) { +if (static_cpu_has_safe (X86_FEATURE_TSCRATEMSR )) {wrmsrl (MSR_AMD64_TSC_RATIO ,TSC_RATIO_DEFAULT );__this_cpu_write (current_tsc_ratio,TSC_RATIO_DEFAULT ); }
@@ -1233,7 +1233,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)for (i =0 ; i <NR_HOST_SAVE_USER_MSRS ; i++)rdmsrl (host_save_user_msrs[i], svm->host_user_msrs[i]); -if (static_cpu_has (X86_FEATURE_TSCRATEMSR )) { +if (static_cpu_has_safe (X86_FEATURE_TSCRATEMSR )) {u64 tsc_ratio = vcpu->arch.tsc_scaling_ratio;if (tsc_ratio !=__this_cpu_read (current_tsc_ratio)) {__this_cpu_write (current_tsc_ratio, tsc_ratio);
@@ -1241,7 +1241,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) } }/* This assumes that the kernel never uses MSR_TSC_AUX */ -if (static_cpu_has (X86_FEATURE_RDTSCP )) +if (static_cpu_has_safe (X86_FEATURE_RDTSCP ))wrmsrl (MSR_TSC_AUX , svm->tsc_aux); }
@@ -2806,7 +2806,7 @@ static int iret_interception(struct vcpu_svm *svm)static int invlpg_interception (struct vcpu_svm *svm) { -if (!static_cpu_has (X86_FEATURE_DECODEASSISTS )) +if (!static_cpu_has_safe (X86_FEATURE_DECODEASSISTS ))return emulate_instruction (&svm->vcpu,0 ) ==EMULATE_DONE ;kvm_mmu_invlpg (&svm->vcpu, svm->vmcb->control.exit_info_1);
@@ -2823,7 +2823,7 @@ static int rdpmc_interception(struct vcpu_svm *svm) {int err; -if (!static_cpu_has (X86_FEATURE_NRIPS )) +if (!static_cpu_has_safe (X86_FEATURE_NRIPS ))return emulate_on_interception (svm); err =kvm_rdpmc (&svm->vcpu);
@@ -2864,7 +2864,7 @@ static int cr_interception(struct vcpu_svm *svm)unsigned long val;int err; -if (!static_cpu_has (X86_FEATURE_DECODEASSISTS )) +if (!static_cpu_has_safe (X86_FEATURE_DECODEASSISTS ))return emulate_on_interception (svm);if (unlikely ((svm->vmcb->control.exit_info_1 &CR_VALID ) ==0 ))
@@ -3710,7 +3710,7 @@ static void svm_flush_tlb(struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu); -if (static_cpu_has (X86_FEATURE_FLUSHBYASID )) +if (static_cpu_has_safe (X86_FEATURE_FLUSHBYASID )) svm->vmcb->control.tlb_ctl =TLB_CONTROL_FLUSH_ASID ;else svm->asid_generation--;
@@ -4282,7 +4282,7 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, }/* TODO: Advertise NRIPS to guest hypervisor unconditionally */ -if (static_cpu_has (X86_FEATURE_NRIPS )) +if (static_cpu_has_safe (X86_FEATURE_NRIPS )) vmcb->control.next_rip = info->next_rip; vmcb->control.exit_code = icpt_info.exit_code; vmexit =nested_svm_exit_handled (svm);
arch/x86/kvm/vmx.c +1 -1
@@ -8993,7 +8993,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)if (cpu_has_secondary_exec_ctrls ())vmcs_set_secondary_exec_control (secondary_exec_ctl); -if (static_cpu_has (X86_FEATURE_PCOMMIT ) && nested) { +if (static_cpu_has_safe (X86_FEATURE_PCOMMIT ) && nested) {if (guest_cpuid_has_pcommit (vcpu)) vmx->nested.nested_vmx_secondary_ctls_high |=SECONDARY_EXEC_PCOMMIT ;
arch/x86/mm/fault.c +1 -1
@@ -1033,7 +1033,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)if (!IS_ENABLED (CONFIG_X86_SMAP ))return false; -if (!static_cpu_has (X86_FEATURE_SMAP )) +if (!static_cpu_has_safe (X86_FEATURE_SMAP ))return false;if (error_code &PF_USER )
arch/x86/ras/mce_amd_inj.c +1 -1
@@ -275,7 +275,7 @@ static void do_inject(void)* only on the node base core. Refer to D18F3x44[NbMcaToMstCpuEn] for * Fam10h and later BKDGs. */ -if (static_cpu_has (X86_FEATURE_AMD_DCM ) && b ==4 ) { +if (static_cpu_has_safe (X86_FEATURE_AMD_DCM ) && b ==4 ) {toggle_nb_mca_mst_cpu (amd_get_nb_id (cpu)); cpu =get_nbc_for_node (amd_get_nb_id (cpu)); }
drivers/cpufreq/amd_freq_sensitivity.c +1 -1
@@ -115,7 +115,7 @@ static int __init amd_freq_sensitivity_init(void)if (boot_cpu_data.x86_vendor !=X86_VENDOR_AMD )return -ENODEV ; -if (!static_cpu_has (X86_FEATURE_PROC_FEEDBACK )) +if (!static_cpu_has_safe (X86_FEATURE_PROC_FEEDBACK ))return -ENODEV ;if (rdmsrl_safe (MSR_AMD64_FREQ_SENSITIVITY_ACTUAL , &val))
drivers/cpufreq/powernow-k8.c +1 -1
@@ -1193,7 +1193,7 @@ static int powernowk8_init(void)unsigned int i, supported_cpus =0 ;int ret; -if (static_cpu_has (X86_FEATURE_HW_PSTATE )) { +if (static_cpu_has_safe (X86_FEATURE_HW_PSTATE )) {__request_acpi_cpufreq ();return -ENODEV ; }
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 2 lines · Borislav Petkov
Patch removing it below. I better look at a 32-bit allyesconfig too first, though.
Yap, no 2-byte jumps in the static_cpu_has()-generated code on an 32-bit allyesconfig build.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 1 line · Borislav Petkov
Patch removing it below.
Andy has a point: I should simply drop static_cpu_has and kill the "_safe" suffix of the remaining variant:
--- arch/x86/Kconfig.debug | 10 ---- arch/x86/include/asm/cpufeature.h | 99 +++--------------------------------- arch/x86/include/asm/fpu/internal.h | 14 ++--- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 4 +- arch/x86/kernel/vm86_32.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- fs/btrfs/disk-io.c | 2 +- 8 files changed, 21 insertions(+), 116 deletions(-)
arch/x86/Kconfig.debug +0 -10
@@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL
arch/x86/include/asm/cpufeature.h +7 -92
146 lines not on this page · raw message
arch/x86/include/asm/fpu/internal.h +7 -7
@@ -58,22 +58,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void);*/ static __always_inline __pure bool use_eager_fpu(void) { -return static_cpu_has_safe (X86_FEATURE_EAGER_FPU ); +return static_cpu_has (X86_FEATURE_EAGER_FPU ); } static __always_inline __pure bool use_xsaveopt(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVEOPT ); +return static_cpu_has (X86_FEATURE_XSAVEOPT ); } static __always_inline __pure bool use_xsave(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVE ); +return static_cpu_has (X86_FEATURE_XSAVE ); } static __always_inline __pure bool use_fxsr(void) { -return static_cpu_has_safe (X86_FEATURE_FXSR ); +return static_cpu_has (X86_FEATURE_FXSR ); }/*
@@ -300,7 +300,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XSAVES , xstate, lmask, hmask, err);else XSTATE_OP (XSAVE , xstate, lmask, hmask, err);
@@ -322,7 +322,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XRSTORS , xstate, lmask, hmask, err);else XSTATE_OP (XRSTOR , xstate, lmask, hmask, err);
@@ -460,7 +460,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)* pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ -if (unlikely (static_cpu_has_bug_safe (X86_BUG_FXSAVE_LEAK ))) { +if (unlikely (static_cpu_has_bug (X86_BUG_FXSAVE_LEAK ))) { asmvolatile ("fnclex\n\t" "emms\n\t"
arch/x86/kernel/apic/apic_numachip.c +2 -2
@@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x)unsigned long value;unsigned int id = (x >>24 ) &0xff ; -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , value); id |= (value <<2 ) &0xff00 ; }
@@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)this_cpu_write (cpu_llc_id, node);/* Account for nodes per socket in multi-core-module processors */ -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , val); nodes = ((val >>3 ) &7 ) +1 ; }
arch/x86/kernel/cpu/common.c +2 -2
@@ -1483,11 +1483,11 @@ void warn_pre_alternatives(void)EXPORT_SYMBOL_GPL (warn_pre_alternatives);#endif -inline bool __static_cpu_has_safe (u16 bit) +inline bool __static_cpu_has (u16 bit) {return boot_cpu_has (bit); } -EXPORT_SYMBOL_GPL (__static_cpu_has_safe); +EXPORT_SYMBOL_GPL (__static_cpu_has);static void bsp_resume (void ) {
arch/x86/kernel/vm86_32.c +1 -1
@@ -362,7 +362,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)/* make room for real-mode segments */ tsk->thread.sp0 +=16 ; -if (static_cpu_has_safe (X86_FEATURE_SEP )) +if (static_cpu_has (X86_FEATURE_SEP )) tsk->thread.sysenter_cs =0 ;load_sp0 (tss, &tsk->thread);
drivers/cpufreq/intel_pstate.c +1 -1
@@ -1431,7 +1431,7 @@ static int __init intel_pstate_init(void)if (!all_cpu_data)return -ENOMEM ; -if (static_cpu_has_safe (X86_FEATURE_HWP ) && !no_hwp) { +if (static_cpu_has (X86_FEATURE_HWP ) && !no_hwp) {pr_info ("intel_pstate: HWP enabled\n" ); hwp_active++; }
fs/btrfs/disk-io.c +1 -1
@@ -924,7 +924,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags)if (bio_flags &EXTENT_BIO_TREE_LOG )return 0 ;#ifdef CONFIG_X86 -if (static_cpu_has_safe (X86_FEATURE_XMM4_2 )) +if (static_cpu_has (X86_FEATURE_XMM4_2 ))return 0 ;#endif return 1 ;
Signature · 4 lines
1.8.5.6 SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) --
Quoted 6 lines · Borislav Petkov
Quoted 1 line · Borislav Petkov
Patch removing it below.
Andy has a point: I should simply drop
static_cpu_hasand kill the "_safe" suffix of the remaining variant:
Is this on top of Brian's patch? I think we should do both or neither.
--Andy
Quoted 1 line · Andy Lutomirski
Is this on top of Brian's patch? I think we should do both or >neither.
Of course. I'll prep a branch tomorrow for the build bot to smoke-test.
Signature · 1 line
Sent from a small device: formatting sux and brevity is inevitable.
H. Peter Anvin
maintainerQuoted 6 lines · Borislav Petkov
old insn VA:
0xffffffff8108c0d0, CPU feat:X86_BUG_SYSRET_SS_ATTRS, size: 2, padlen: 0__switch_to:
ffffffff8108c0d0: eb 70 jmpffffffff8108c142
repl insn:0xffffffff8ca7a1a7, size: 0
This is the only one I could possibly imagine mattering. Would it be possible to get the disassembly here?
-hpa
Quoted 10 lines · H. Peter Anvin
Quoted 6 lines · Borislav Petkov
old insn VA:
0xffffffff8108c0d0, CPU feat:X86_BUG_SYSRET_SS_ATTRS, size: 2, padlen: 0__switch_to:
ffffffff8108c0d0: eb 70 jmpffffffff8108c142
repl insn:0xffffffff8ca7a1a7, size: 0This is the only one I could possibly imagine mattering. Would it be possible to get the disassembly here?
Sure, I've kept the vmlinux, see below:
ffffffff8108c0d0: eb 70 jmp ffffffff8108c142 <__switch_to+0x838>
jumps to:
ffffffff8108c142: 48 ff 05 b7 08 aa 0b incq 0xbaa08b7(%rip)
which is something-gcov. In any case, it jumps over the SS fixup code:
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
...
unsigned short ss_sel;
savesegment(ss, ss_sel);
if (ss_sel != __KERNEL_DS)
loadsegment(ss, __KERNEL_DS);
}I guess we could fix that with an alternative_call() where @oldinstr is empty so that on !X86_BUG_SYSRET_SS_ATTRS machines we simply return and on the others, we do a CALL fixup_ss or so.
We have to pay attention to clobbers, though, similar to the POPCNT fun in __arch_hweight32().
ffffffff8108b90a <__switch_to>:
ffffffff8108b90a: 55 push %rbp ffffffff8108b90b: 48 8d 87 c0 2d 00 00 lea 0x2dc0(%rdi),%rax ffffffff8108b912: 48 c7 c1 80 f6 1d 00 mov $0x1df680,%rcx ffffffff8108b919: 48 89 e5 mov %rsp,%rbp ffffffff8108b91c: 41 57 push %r15 ffffffff8108b91e: 45 31 ff xor %r15d,%r15d ffffffff8108b921: 41 56 push %r14
...
ffffffff8108c0c2: 48 ff 05 07 09 aa 0b incq 0xbaa0907(%rip) # ffffffff8cb2c9d0 <__gcov0.__switch_to+0xc0> ffffffff8108c0c9: 48 ff 05 08 09 aa 0b incq 0xbaa0908(%rip) # ffffffff8cb2c9d8 <__gcov0.__switch_to+0xc8> ffffffff8108c0d0: eb 70 jmp ffffffff8108c142 <__switch_to+0x838> ffffffff8108c0d2: 48 ff 05 07 09 aa 0b incq 0xbaa0907(%rip) # ffffffff8cb2c9e0 <__gcov0.__switch_to+0xd0> ffffffff8108c0d9: 48 ff 05 08 09 aa 0b incq 0xbaa0908(%rip) # ffffffff8cb2c9e8 <__gcov0.__switch_to+0xd8> ffffffff8108c0e0: 48 ff 05 11 09 aa 0b incq 0xbaa0911(%rip) # ffffffff8cb2c9f8 <__gcov0.__switch_to+0xe8> ffffffff8108c0e7: 66 8c d0 mov %ss,%ax ffffffff8108c0ea: 66 83 f8 18 cmp $0x18,%ax ffffffff8108c0ee: 75 17 jne ffffffff8108c107 <__switch_to+0x7fd> ffffffff8108c0f0: eb 57 jmp ffffffff8108c149 <__switch_to+0x83f> ffffffff8108c0f2: 48 ff 05 cf 08 aa 0b incq 0xbaa08cf(%rip) # ffffffff8cb2c9c8 <__gcov0.__switch_to+0xb8> ffffffff8108c0f9: e8 db b0 01 00 callq ffffffff810a71d9 <warn_pre_alternatives> ffffffff8108c0fe: 48 ff 05 eb 08 aa 0b incq 0xbaa08eb(%rip) # ffffffff8cb2c9f0 <__gcov0.__switch_to+0xe0> ffffffff8108c105: eb 3b jmp ffffffff8108c142 <__switch_to+0x838> ffffffff8108c107: 48 ff 05 fa 08 aa 0b incq 0xbaa08fa(%rip) # ffffffff8cb2ca08 <__gcov0.__switch_to+0xf8> ffffffff8108c10e: b8 18 00 00 00 mov $0x18,%eax ffffffff8108c113: 8e d0 mov %eax,%ss ffffffff8108c115: 48 ff 05 f4 08 aa 0b incq 0xbaa08f4(%rip) # ffffffff8cb2ca10 <__gcov0.__switch_to+0x100> ffffffff8108c11c: eb 2b jmp ffffffff8108c149 <__switch_to+0x83f> ffffffff8108c11e: 48 ff 05 9b 02 aa 0b incq 0xbaa029b(%rip) # ffffffff8cb2c3c0 <__gcov0.copy_xregs_to_kernel+0x30> ffffffff8108c125: e9 91 f9 ff ff jmpq ffffffff8108babb <__switch_to+0x1b1> ffffffff8108c12a: 48 ff 05 bf 02 aa 0b incq 0xbaa02bf(%rip) # ffffffff8cb2c3f0 <__gcov0.copy_kernel_to_xregs+0x20> ffffffff8108c131: e9 84 fe ff ff jmpq ffffffff8108bfba <__switch_to+0x6b0> ffffffff8108c136: 48 ff 05 43 02 aa 0b incq 0xbaa0243(%rip) # ffffffff8cb2c380 <__gcov0.copy_kernel_to_fxregs+0x20> ffffffff8108c13d: e9 db fe ff ff jmpq ffffffff8108c01d <__switch_to+0x713> ffffffff8108c142: 48 ff 05 b7 08 aa 0b incq 0xbaa08b7(%rip) # ffffffff8cb2ca00 <__gcov0.__switch_to+0xf0> ffffffff8108c149: 48 83 c4 28 add $0x28,%rsp ffffffff8108c14d: 4c 89 e0 mov %r12,%rax ffffffff8108c150: 5b pop %rbx ffffffff8108c151: 41 5c pop %r12 ffffffff8108c153: 41 5d pop %r13 ffffffff8108c155: 41 5e pop %r14 ffffffff8108c157: 41 5f pop %r15 ffffffff8108c159: 5d pop %rbp ffffffff8108c15a: c3 retq
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 103 lines · Borislav Petkov
Quoted 3 lines · H. Peter Anvin
Quoted 2 lines · Borislav Petkov
old insn VA:
0xffffffff8108c0d0, CPU feat:X86_BUG_SYSRET_SS_ATTRS,size: 2, padlen: 0
Quoted 2 lines
Quoted 2 lines
__switch_to:
ffffffff8108c0d0: eb 70 jmp
ffffffff8108c142Quoted 5 lines
Quoted 2 lines
repl insn:
0xffffffff8ca7a1a7, size: 0This is the only one I could possibly imagine mattering. Would it be possible to get the disassembly here?
Sure, I've kept the vmlinux, see below:
ffffffff8108c0d0: eb 70 jmpffffffff8108c142
<__switch_to+0x838>jumps to:
ffffffff8108c142: 48 ff 05 b7 08 aa 0b incq 0xbaa08b7(%rip)which is something-gcov. In any case, it jumps over the SS fixup code:
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) { ... unsigned short ss_sel; savesegment(ss, ss_sel); if (ss_sel != __KERNEL_DS) loadsegment(ss, __KERNEL_DS); }I guess we could fix that with an
alternative_call()where @oldinstr is empty so that on !X86_BUG_SYSRET_SS_ATTRS machines we simply return and on the others, we do a CALLfixup_ssor so.We have to pay attention to clobbers, though, similar to the POPCNT fun in
__arch_hweight32().
ffffffff8108b90a<__switch_to>:ffffffff8108b90a: 55 push %rbp ffffffff8108b90b: 48 8d 87 c0 2d 00 00 lea 0x2dc0(%rdi),%rax ffffffff8108b912: 48 c7 c1 80 f6 1d 00 mov $0x1df680,%rcx ffffffff8108b919: 48 89 e5 mov %rsp,%rbp ffffffff8108b91c: 41 57 push %r15 ffffffff8108b91e: 45 31 ff xor %r15d,%r15d ffffffff8108b921: 41 56 push %r14...
ffffffff8108c0c2: 48 ff 05 07 09 aa 0b incq 0xbaa0907(%rip)# ffffffff8cb2c9d0 <__gcov0.__switch_to+0xc0> ffffffff8108c0c9: 48 ff 05 08 09 aa 0b incq 0xbaa0908(%rip) # ffffffff8cb2c9d8 <__gcov0.__switch_to+0xc8> ffffffff8108c0d0: eb 70 jmp ffffffff8108c142 <__switch_to+0x838> ffffffff8108c0d2: 48 ff 05 07 09 aa 0b incq 0xbaa0907(%rip) # ffffffff8cb2c9e0 <__gcov0.__switch_to+0xd0> ffffffff8108c0d9: 48 ff 05 08 09 aa 0b incq 0xbaa0908(%rip) # ffffffff8cb2c9e8 <__gcov0.__switch_to+0xd8> ffffffff8108c0e0: 48 ff 05 11 09 aa 0b incq 0xbaa0911(%rip) # ffffffff8cb2c9f8 <__gcov0.__switch_to+0xe8> ffffffff8108c0e7: 66 8c d0 mov %ss,%ax ffffffff8108c0ea: 66 83 f8 18 cmp $0x18,%ax ffffffff8108c0ee: 75 17 jne ffffffff8108c107 <__switch_to+0x7fd> ffffffff8108c0f0: eb 57 jmp ffffffff8108c149 <__switch_to+0x83f> ffffffff8108c0f2: 48 ff 05 cf 08 aa 0b incq 0xbaa08cf(%rip) # ffffffff8cb2c9c8 <__gcov0.__switch_to+0xb8> ffffffff8108c0f9: e8 db b0 01 00 callq ffffffff810a71d9 <warn_pre_alternatives> ffffffff8108c0fe: 48 ff 05 eb 08 aa 0b incq 0xbaa08eb(%rip) # ffffffff8cb2c9f0 <__gcov0.__switch_to+0xe0> ffffffff8108c105: eb 3b jmp ffffffff8108c142 <__switch_to+0x838> ffffffff8108c107: 48 ff 05 fa 08 aa 0b incq 0xbaa08fa(%rip) # ffffffff8cb2ca08 <__gcov0.__switch_to+0xf8> ffffffff8108c10e: b8 18 00 00 00 mov $0x18,%eax ffffffff8108c113: 8e d0 mov %eax,%ss ffffffff8108c115: 48 ff 05 f4 08 aa 0b incq 0xbaa08f4(%rip) # ffffffff8cb2ca10 <__gcov0.__switch_to+0x100> ffffffff8108c11c: eb 2b jmp ffffffff8108c149 <__switch_to+0x83f> ffffffff8108c11e: 48 ff 05 9b 02 aa 0b incq 0xbaa029b(%rip) # ffffffff8cb2c3c0 <__gcov0.copy_xregs_to_kernel+0x30> ffffffff8108c125: e9 91 f9 ff ff jmpq ffffffff8108babb <__switch_to+0x1b1> ffffffff8108c12a: 48 ff 05 bf 02 aa 0b incq 0xbaa02bf(%rip) # ffffffff8cb2c3f0 <__gcov0.copy_kernel_to_xregs+0x20> ffffffff8108c131: e9 84 fe ff ff jmpq ffffffff8108bfba <__switch_to+0x6b0> ffffffff8108c136: 48 ff 05 43 02 aa 0b incq 0xbaa0243(%rip) # ffffffff8cb2c380 <__gcov0.copy_kernel_to_fxregs+0x20> ffffffff8108c13d: e9 db fe ff ff jmpq ffffffff8108c01d <__switch_to+0x713> ffffffff8108c142: 48 ff 05 b7 08 aa 0b incq 0xbaa08b7(%rip) # ffffffff8cb2ca00 <__gcov0.__switch_to+0xf0> ffffffff8108c149: 48 83 c4 28 add $0x28,%rsp
Quoted 8 lines
ffffffff8108c14d: 4c 89 e0 mov %r12,%rax ffffffff8108c150: 5b pop %rbx ffffffff8108c151: 41 5c pop %r12 ffffffff8108c153: 41 5d pop %r13 ffffffff8108c155: 41 5e pop %r14 ffffffff8108c157: 41 5f pop %r15 ffffffff8108c159: 5d pop %rbp ffffffff8108c15a: c3 retq
Ah. What would be even more of a win would be to rebias static_cpu_has_bug() so that the fallthrough case is the functional one. Easily done by reversing the labels.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 3 lines · H. Peter Anvin
Ah. What would be even more of a win would be to rebias
static_cpu_has_bug()so that the fallthrough case is the functional one. Easily done by reversing the labels.
By reversing you mean this:
---
arch/x86/include/asm/cpufeature.h +2 -2
@@ -174,10 +174,10 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) [bitnum] "i" (1 << (bit & 7)), [cap_word] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) : : t_yes, t_no); - t_yes: -return true; t_no:return false; + t_yes: +return true;#else return boot_cpu_has (bit);#endif /* CC_HAVE_ASM_GOTO */
---
?
In any case, here's what happens with the current patchset:
vmlinux:
ffffffff8100472a: e9 50 0e de 00 jmpq ffffffff81de557f <__alt_instructions_end+0x7aa> ffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retq
That first JMP above sends us to the dynamic section which is in asm now:
ffffffff81de557f: f6 05 8f de d1 ff 01 testb $0x1,-0x2e2171(%rip) # ffffffff81b03415 <boot_cpu_data+0x55> ffffffff81de5586: 0f 85 a3 f1 21 ff jne ffffffff8100472f <__switch_to+0x2df> ffffffff81de558c: e9 ae f1 21 ff jmpq ffffffff8100473f <__switch_to+0x2ef>
After X86_FEATURE_ALWAYS patching, that first JMP has become a 2-byte JMP:
[ 0.306333] apply_alternatives: feat: 3*32+21, old: (ffffffff8100472a, len: 5), repl: (ffffffff81de4e12, len: 5), pad: 0 [ 0.308005] ffffffff8100472a: old_insn: e9 50 0e de 00 [ 0.312012] ffffffff81de4e12: rpl_insn: e9 28 f9 21 ff [ 0.318201] recompute_jump: target RIP: ffffffff8100473f, new_displ: 0x15 [ 0.320007] recompute_jump: final displ: 0x00000013, JMP 0xffffffff8100473f [ 0.324005] ffffffff8100472a: final_insn: eb 13 0f 1f 00
so basically we jump over the %ss fixup:
ffffffff8100472a: eb 13 0f 1f 00 jmp ffffffff8100473f
ffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp <---- ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retq
After X86_BUG_SYSRET_SS_ATTRS patching:
[ 0.330367] apply_alternatives: feat: 16*32+8, old: (ffffffff8100472a, len: 5), repl: (ffffffff81de3996, len: 0), pad: 0 [ 0.332005] ffffffff8100472a: old_insn: eb 13 0f 1f 00 [ 0.338332] ffffffff8100472a: final_insn: 0f 1f 44 00 00
ffffffff8100472a: 0f 1f 44 00 00 nop
ffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retq
So the penalty for the !X86_BUG_SYSRET_SS_ATTRS CPUs is a 2-byte JMP. Do we care?
In the case we do, we could do this:
JMP ss_fixup
ret:
RET return prev_p;
ss_fixup:
<fixup SS>
jmp ret
and the !X86_BUG_SYSRET_SS_ATTRS CPUs would overwrite that "JMP ss_fixup" with a NOP and they're fine. However, the X86_BUG_SYSRET_SS_ATTRS CPUs will have to do two jumps, one to the fixup code and one back to RET.
Now, how about I convert
unsigned short ss_sel;
savesegment(ss, ss_sel);
if (ss_sel != __KERNEL_DS)
loadsegment(ss, __KERNEL_DS);into asm and into an alternative()?
Then, the !X86_BUG_SYSRET_SS_ATTRS CPUs will trade off that JMP with a bunch of NOPs which will pollute I$.
Hmmm.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 148 lines · Borislav Petkov
Quoted 3 lines · H. Peter Anvin
Ah. What would be even more of a win would be to rebias
static_cpu_has_bug()so that the fallthrough case is the functional one. Easily done by reversing the labels.By reversing you mean this:
---
arch/x86/include/asm/cpufeature.h +2
-2@@ -174,10 +174,10 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) [bitnum] "i" (1 << (bit & 7)), [cap_word] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) : : t_yes, t_no); - t_yes: -return true; t_no:return false; + t_yes: +return true;#else return boot_cpu_has (bit);#endif /*
CC_HAVE_ASM_GOTO*/
---?
In any case, here's what happens with the current patchset:
vmlinux:
ffffffff8100472a: e9 50 0e de 00 jmpqffffffff81de557f
<__alt_instructions_end+0x7aa>ffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retqThat first JMP above sends us to the dynamic section which is in asm now:
ffffffff81de557f: f6 05 8f de d1 ff 01 testb
$0x1,-0x2e2171(%rip) #ffffffff81b03415<boot_cpu_data+0x55>ffffffff81de5586: 0f 85 a3 f1 21 ff jneffffffff8100472f
<__switch_to+0x2df>ffffffff81de558c: e9 ae f1 21 ff jmpqffffffff8100473f
<__switch_to+0x2ef>After
X86_FEATURE_ALWAYSpatching, that first JMP has become a 2-byte JMP:[ 0.306333] apply_alternatives: feat: 3*32+21, old: (ffffffff8100472a, len: 5), repl: (ffffffff81de4e12, len: 5), pad: 0 [ 0.308005] ffffffff8100472a: old_insn: e9 50 0e de 00 [ 0.312012] ffffffff81de4e12: rpl_insn: e9 28 f9 21 ff [ 0.318201] recompute_jump: target RIP: ffffffff8100473f, new_displ: 0x15 [ 0.320007] recompute_jump: final displ: 0x00000013, JMP 0xffffffff8100473f [ 0.324005] ffffffff8100472a: final_insn: eb 13 0f 1f 00so basically we jump over the %ss fixup:
ffffffff8100472a: eb 13 0f 1f 00 jmpffffffff8100473fffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp <---- ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retqAfter
X86_BUG_SYSRET_SS_ATTRSpatching:[ 0.330367] apply_alternatives: feat: 16*32+8, old: (ffffffff8100472a, len: 5), repl: (ffffffff81de3996, len: 0), pad: 0 [ 0.332005] ffffffff8100472a: old_insn: eb 13 0f 1f 00 [ 0.338332] ffffffff8100472a: final_insn: 0f 1f 44 00 00
ffffffff8100472a: 0f 1f 44 00 00 nopffffffff8100472f: 66 8c d0 mov %ss,%ax ffffffff81004732: 66 83 f8 18 cmp $0x18,%ax ffffffff81004736: 74 07 je ffffffff8100473f <__switch_to+0x2ef> ffffffff81004738: b8 18 00 00 00 mov $0x18,%eax ffffffff8100473d: 8e d0 mov %eax,%ss ffffffff8100473f: 48 83 c4 18 add $0x18,%rsp ffffffff81004743: 4c 89 e0 mov %r12,%rax ffffffff81004746: 5b pop %rbx ffffffff81004747: 41 5c pop %r12 ffffffff81004749: 41 5d pop %r13 ffffffff8100474b: 41 5e pop %r14 ffffffff8100474d: 41 5f pop %r15 ffffffff8100474f: 5d pop %rbp ffffffff81004750: c3 retqSo the penalty for the !X86_BUG_SYSRET_SS_ATTRS CPUs is a 2-byte JMP. Do
we care?In the case we do, we could do this:
JMP
ss_fixup
ret:RET return prev_p;
ss_fixup:
<fixup SS>
jmp retand the !X86_BUG_SYSRET_SS_ATTRS CPUs would overwrite that "JMP
ss_fixup" with a NOP and they're fine. However, theX86_BUG_SYSRET_SS_ATTRSCPUs will have to do two jumps, one to the fixup
code and one back to RET.Now, how about I convert
unsigned short ss_sel; savesegment(ss, ss_sel); if (ss_sel != __KERNEL_DS) loadsegment(ss, __KERNEL_DS);
Quoted 6 lines
into asm and into an
alternative()?Then, the !X86_BUG_SYSRET_SS_ATTRS CPUs will trade off that JMP with a bunch of NOPs which will pollute I$.
Hmmm.
Yes, having t_no as the fallthrough case ought to move the yes code out of line.
The current code probably pollutes the i$ too.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 2 lines · H. Peter Anvin
Yes, having
t_noas the fallthrough case ought to move the yes code out of line.
Dunno, maybe I'm doing something wrong:
I have this change:
---
arch/x86/include/asm/cpufeature.h +2 -2
@@ -175,10 +175,10 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) [bitnum] "i" (1 << (bit & 7)), [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) : : t_yes, t_no); - t_yes: -return true; t_no:return false; + t_yes: +return true; }#define static_cpu_has (bit) \
---
and the resulting code looks even wrong (or my brain is fried for today
- one of the two).
vmlinux:
ffffffff810046ae: e9 cc 0e de 00 jmpq ffffffff81de557f <__alt_instructions_end+0x7aa> ffffffff810046b3: 48 83 c4 18 add $0x18,%rsp ffffffff810046b7: 4c 89 e0 mov %r12,%rax ffffffff810046ba: 5b pop %rbx ffffffff810046bb: 41 5c pop %r12 ffffffff810046bd: 41 5d pop %r13 ffffffff810046bf: 41 5e pop %r14 ffffffff810046c1: 41 5f pop %r15 ffffffff810046c3: 5d pop %rbp ffffffff810046c4: c3 retq
dynamic branch:
ffffffff81de557f: f6 05 8f de d1 ff 01 testb $0x1,-0x2e2171(%rip) # ffffffff81b03415 <boot_cpu_data+0x55> ffffffff81de5586: 0f 85 f6 f1 21 ff jne ffffffff81004782 <__switch_to+0x332> ffffffff81de558c: e9 22 f1 21 ff jmpq ffffffff810046b3 <__switch_to+0x263>
after X86_FEATURE_ALWAYS patching:
[ 0.288007] apply_alternatives: feat: 3*32+21, old: (ffffffff810046ae, len: 5), repl: (ffffffff81de4dff, len: 5), pad: 0 [ 0.292004] ffffffff810046ae: old_insn: e9 cc 0e de 00 [ 0.300013] ffffffff81de4dff: rpl_insn: e9 af f8 21 ff [ 0.308006] recompute_jump: target RIP: ffffffff810046b3, new_displ: 0x5 [ 0.312006] recompute_jump: final displ: 0x00000003, JMP 0xffffffff810046b3 [ 0.316006] ffffffff810046ae: final_insn: eb 03 0f 1f 00
ffffffff810046ae: eb 03 0f 1f 00 jmp ffffffff810046b3 --- ffffffff810046b3: 48 83 c4 18 add $0x18,%rsp <-- ffffffff810046b7: 4c 89 e0 mov %r12,%rax ffffffff810046ba: 5b pop %rbx ffffffff810046bb: 41 5c pop %r12 ffffffff810046bd: 41 5d pop %r13 ffffffff810046bf: 41 5e pop %r14 ffffffff810046c1: 41 5f pop %r15 ffffffff810046c3: 5d pop %rbp ffffffff810046c4: c3 retq
so this is silly: we're basically jumping after the JMP instruction itself. So that will be the case on !X86_BUG_SYSRET_SS_ATTRS CPUs. Still a two-byte and now even a useless JMP.
The right thing to do would be to generate a NOP simply.
On X86_BUG_SYSRET_SS_ATTRS CPUs:
[ 0.322014] apply_alternatives: feat: 16*32+8, old: (ffffffff810046ae, len: 5), repl: (ffffffff81de3962, len: 0), pad: 0 [ 0.324005] ffffffff810046ae: old_insn: eb 03 0f 1f 00 [ 0.332006] ffffffff810046ae: final_insn: 0f 1f 44 00 00
ffffffff810046ae: 0f 1f 44 00 00 nop ffffffff810046b3: 48 83 c4 18 add $0x18,%rsp ffffffff810046b7: 4c 89 e0 mov %r12,%rax ffffffff810046ba: 5b pop %rbx ffffffff810046bb: 41 5c pop %r12 ffffffff810046bd: 41 5d pop %r13 ffffffff810046bf: 41 5e pop %r14 ffffffff810046c1: 41 5f pop %r15 ffffffff810046c3: 5d pop %rbp ffffffff810046c4: c3 retq
which is actually even wrong!
What it should've done is
jne ffffffff81004782
as the dynamic code did. At that address we have the ss fixup:
ffffffff81004782: 66 8c d0 mov %ss,%ax ffffffff81004785: 66 83 f8 18 cmp $0x18,%ax ffffffff81004789: 0f 84 24 ff ff ff je ffffffff810046b3 <__switch_to+0x263> ffffffff8100478f: b8 18 00 00 00 mov $0x18,%eax ffffffff81004794: 8e d0 mov %eax,%ss ffffffff81004796: e9 18 ff ff ff jmpq ffffffff810046b3 <__switch_to+0x263>
with the jump back to the ret code. Which means, !X86_BUG_SYSRET_SS_ATTRS CPUs get to do a forward and a backward JMP. So even if it did the right thing, it would be two JMPs.
Meh.
I need to think about something better.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 7 lines · Borislav Petkov
so this is silly: we're basically jumping after the JMP instruction itself. So that will be the case on !X86_BUG_SYSRET_SS_ATTRS CPUs. Still a two-byte and now even a useless JMP.
The right thing to do would be to generate a NOP simply.
OK, so gcc isn't as clever as I thought.
-hpa
H. Peter Anvin
maintainerMaybe a label attribute would help, I don't know.
-hpa
Quoted 1 line · H. Peter Anvin
Maybe a label attribute would help, I don't know.
Here's another version which works, not really better though:
Change is this:
---
+ asm_volatile_goto(ALTERNATIVE("", "jmp %l[t_fixup_ss]",
+ X86_BUG_SYSRET_SS_ATTRS)
+ : : : : t_fixup_ss);
+
+ return prev_p;
+
+t_fixup_ss:
<snip comment>
+ savesegment(ss, ss_sel);
+ if (ss_sel != __KERNEL_DS)
+ loadsegment(ss, __KERNEL_DS);
return prev_p;
---
with two "return prev_p" with the hope that gcc won't generate a second JMP back to the frame restore and ret code. But, nah, it does.
vmlinux:
ffffffff8100472a: 90 nop ffffffff8100472b: 90 nop ffffffff8100472c: 90 nop ffffffff8100472d: 90 nop ffffffff8100472e: 90 nop ffffffff8100472f: 48 83 c4 18 add $0x18,%rsp ffffffff81004733: 4c 89 e0 mov %r12,%rax ffffffff81004736: 5b pop %rbx ffffffff81004737: 41 5c pop %r12 ffffffff81004739: 41 5d pop %r13 ffffffff8100473b: 41 5e pop %r14 ffffffff8100473d: 41 5f pop %r15 ffffffff8100473f: 5d pop %rbp ffffffff81004740: c3 retq
after patching on an X86_BUG_SYSRET_SS_ATTRS CPU:
[ 0.264007] apply_alternatives: feat: 16*32+8, old: (ffffffff8100472a, len: 5), repl: (ffffffff81de4e05, len: 5), pad: 5 [ 0.268005] ffffffff8100472a: old_insn: 90 90 90 90 90 [ 0.273510] ffffffff81de4e05: rpl_insn: e9 68 f9 21 ff [ 0.277496] recompute_jump: target RIP: ffffffff81004772, new_displ: 0x48 [ 0.280005] recompute_jump: final displ: 0x00000046, JMP 0xffffffff81004772 [ 0.283159] ffffffff8100472a: final_insn: eb 46 0f 1f 00
ffffffff8100472a: eb 46 0f 1f 00 jmp ffffffff81004772 ffffffff8100472f: 48 83 c4 18 add $0x18,%rsp ffffffff81004733: 4c 89 e0 mov %r12,%rax ffffffff81004736: 5b pop %rbx ffffffff81004737: 41 5c pop %r12 ffffffff81004739: 41 5d pop %r13 ffffffff8100473b: 41 5e pop %r14 ffffffff8100473d: 41 5f pop %r15 ffffffff8100473f: 5d pop %rbp ffffffff81004740: c3 retq
so a two-byte JMP jumping to:
ffffffff81004772: 66 8c d0 mov %ss,%ax ffffffff81004775: 66 83 f8 18 cmp $0x18,%ax ffffffff81004779: 74 b4 je ffffffff8100472f <__switch_to+0x2df> ffffffff8100477b: b8 18 00 00 00 mov $0x18,%eax ffffffff81004780: 8e d0 mov %eax,%ss ffffffff81004782: eb ab jmp ffffffff8100472f <__switch_to+0x2df>
which does the fixup and jumps back to ...472f which restores the frame and returns.
I wish I could be able to tell gcc to not jump back but add the function return here too as we don't care about code size in that case.
And it's not like it is really better on !X86_BUG_SYSRET_SS_ATTRS CPUs - there we have the 5-byte padding NOP being converted to 5-byte one:
[ 0.293164] ffffffff8100472a: [0:5) optimized NOPs: 0f 1f 44 00 00
I need to talk to my gcc guy... :)
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 8 lines · Borislav Petkov
So we're talking about less than a page here?
[19] .static_cpu_has PROGBITS
ffffffff81d335d3011335d300000000000002df 0000000000000000 AX 0 0 1That's 479 bytes. Meh, it doesn't look like it is worth the trouble.
Maybe I should build an allyesconfig.
[45] .static_cpu_has PROGBITS ffffffff97aa655b 16ea655b
00000000000002df 0000000000000000 AX 0 0 1
Same.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Quoted 2 lines · Borislav Petkov
[45] .static_cpu_has PROGBITS
ffffffff97aa655b16ea655b00000000000002df 0000000000000000 AX 0 0 1
Ok, staring at this section was wrong. I went and looked at the .s file and now it clicked: gcc inlines those calls to __static_cpu_has_safe of the dynamic jump target:
.loc 4 538 0
movl $125, %edi #,
call __static_cpu_has_safe #
.LBE885:
.LBE886:
.LBE914:
.loc 1 240 0
testb %al, %al # D.30157
je .L150 #,
jmp .L151 #.L152:
.LBB915:
.LBB909:
.LBB905:
.LBB893:
.LBB892:
.loc 4 538 0
movl $154, %edi #,
call __static_cpu_has_safe #
.LBE892:
.LBE893:
.LBE905:
.loc 7 431 0
testb %al, %al # D.30157
jne .L154 #,which turn into:
751: bf 7d 00 00 00 mov $0x7d,%edi 756: e8 00 00 00 00 callq 75b <fpu__copy+0xab> 75b: 84 c0 test %al,%al 75d: 74 a3 je 702 <fpu__copy+0x52> 75f: eb 90 jmp 6f1 <fpu__copy+0x41> 761: bf 9a 00 00 00 mov $0x9a,%edi 766: e8 00 00 00 00 callq 76b <fpu__copy+0xbb> 76b: 84 c0 test %al,%al
That's like 28 bytes in this particular case, which is 14 per call site, on average.
So grepping through my tailored vmlinux, it has 35 entries with X86_FEATURE_ALWAYS in .altinstructions X 14 = 490 bytes.
So yeah, we probably should do this, allyesconfig should give more savings.
One thing I'd probably do differently is not call the throwaway section .static_cpu_has but something like .altinstr_temporary or so and put it after the replacement insns:
.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
*(.altinstr_replacement)
*(.altinstr_temporary)
}so that we know those instructions belong to the alternatives mechanism. They'll get discared too, of course.
I could just as well be talking a lot of crap, it is waay too late here.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 64 lines · Borislav Petkov
Quoted 2 lines · Borislav Petkov
[45] .static_cpu_has PROGBITS
ffffffff97aa655b16ea655b00000000000002df 0000000000000000 AX 0 0 1Ok, staring at this section was wrong. I went and looked at the .s file and now it clicked: gcc inlines those calls to
__static_cpu_has_safeof the dynamic jump target:.loc 4 538 0 movl $125, %edi #, call __static_cpu_has_safe # .LBE885: .LBE886: .LBE914: .loc 1 240 0 testb %al, %al # D.30157 je .L150 #, jmp .L151 #.L152:
.LBB915:
.LBB909:
.LBB905:
.LBB893:
.LBB892:.loc 4 538 0 movl $154, %edi #, call __static_cpu_has_safe # .LBE892: .LBE893: .LBE905: .loc 7 431 0 testb %al, %al # D.30157 jne .L154 #,which turn into:
751: bf 7d 00 00 00 mov $0x7d,%edi 756: e8 00 00 00 00 callq 75b <fpu__copy+0xab> 75b: 84 c0 test %al,%al 75d: 74 a3 je 702 <fpu__copy+0x52> 75f: eb 90 jmp 6f1 <fpu__copy+0x41> 761: bf 9a 00 00 00 mov $0x9a,%edi 766: e8 00 00 00 00 callq 76b <fpu__copy+0xbb> 76b: 84 c0 test %al,%alThat's like 28 bytes in this particular case, which is 14 per call site,
on average.So grepping through my tailored vmlinux, it has 35 entries with
X86_FEATURE_ALWAYSin .altinstructions X 14 = 490 bytes.So yeah, we probably should do this, allyesconfig should give more savings.
One thing I'd probably do differently is not call the throwaway section .static_cpu_has but something like .altinstr_temporary or so and put it after the replacement insns:
.altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) *(.altinstr_temporary) }
Quoted 6 lines
so that we know those instructions belong to the alternatives mechanism.
They'll get discared too, of course.I could just as well be talking a lot of crap, it is waay too late here.
Why the f do we call a subroutine for what amounts to a single bt or test instruction?
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 2 lines · H. Peter Anvin
Why the f do we call a subroutine for what amounts to a single bt or test instruction?
No real reason. You can kick me when you see me next time:
4a90a99c4f80 ("x86: Add a static_cpu_has_safe variant")
:-)
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 8 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin
Why the f do we call a subroutine for what amounts to a single bt or test instruction?
No real reason. You can kick me when you see me next time:
4a90a99c4f80("x86: Add astatic_cpu_has_safevariant")
So, here is my suggestion:
1. Just get rid of static_cpu_has_safe() and make static_cpu_has() safe.
2. Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)
3. Put the dynamic test in the .init.text section and inline it:
.section .init.text,"ax" testb %2,%3 jnz %[t_yes] jmp %[t_no] .previous ... "i" (1 << (bit & 7)), "m" (((const char *)boot_cpu_data->x86_capability)[bit >> 3]) ...
(The code would be slightly simpler/cleaner with testl, but that would unnecessarily create a long immediate, or with btl, but that would be slower. We could use CONST_MASK_ADDR() and CONST_MASK() from asm/bitops.h, but I'm slightly uncomfortable with the idea of leveraging an interface which is ultimately an internal implementation detail of bitops.h that might change in the future without people realizing its implications.)
The only thing we lose is the 2-byte optimization in case we have the good luck for it to actually work. At this point I'm thinking it isn't worth it, and instead that safety trumps it. It *would* be interesting to see if there are any call sites where it would actually kick in.
-hpa
Quoted 22 lines · H. Peter Anvin
Quoted 8 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin
Why the f do we call a subroutine for what amounts to a single bt or test instruction?
No real reason. You can kick me when you see me next time:
4a90a99c4f80("x86: Add astatic_cpu_has_safevariant")So, here is my suggestion:
1. Just get rid of
static_cpu_has_safe()and makestatic_cpu_has()safe.2. Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)
3. Put the dynamic test in the .init.text section and inline it:
Quoted 8 lines
.section .init.text,"ax"
testb %2,%3
jnz %[t_yes]
jmp %[t_no]
.previous
... "i" (1 << (bit & 7)),
"m" (((const char *)boot_cpu_data->x86_capability)[bit >> 3]) ...Can't put it in .init.text or else you get:
WARNING: arch/x86/kernel/built-in.o(.text+0x4b9): Section mismatch in reference from the function __switch_to() to the (unknown reference) .init.text:(unknown)
The function __switch_to() references
the (unknown reference) __init (unknown).
This is often because __switch_to lacks a __init annotation or the annotation of (unknown) is wrong.
We want to override that because we know that the reference will be removed after alternatives run. That's why I created a new section.
--
Brian Gerst
H. Peter Anvin
maintainerQuoted 10 lines · Brian Gerst
Can't put it in .init.text or else you get:
WARNING: arch/x86/kernel/built-in.o(.text+0x4b9): Section mismatch in reference from the function__switch_to()to the (unknown reference) .init.text:(unknown)
The function__switch_to()references
the (unknown reference)__init(unknown).
This is often because__switch_tolacks a__initannotation or the annotation of (unknown) is wrong.
Quoted 3 lines
We want to override that because we know that the reference will be removed after alternatives run. That's why I created a new section.
Right. I wish we could tag reference call sites as clean, not sources or targets. Sigh.
However, that's not too much of an issue.
-hpa
Quoted 2 lines · H. Peter Anvin
Right. I wish we could tag reference call sites as clean, not sources or targets. Sigh.
I was thinking about something like this:
From: Borislav Petkov <[email protected]>
Date: Wed, 20 Jan 2016 11:45:36 +0100
Subject: [PATCH] x86/alternatives: Add an auxilary section
Add .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch.
--- arch/x86/kernel/vmlinux.lds.S | 5 +++++ 1 file changed, 5 insertions(+)
arch/x86/kernel/vmlinux.lds.S +5 -0
@@ -244,6 +244,11 @@ SECTIONS */ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) + /* + * Auxiliary section for misc instruction patching tasks. See + * static_cpu_has(), for an example. + */ + *(.altinstr_aux) } /*
Signature · 4 lines
2.3.5 SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) --
H. Peter Anvin
maintainerQuoted 37 lines · Borislav Petkov
Quoted 1 line · H. Peter Anvin
Right. I wish we could tag reference call sites as clean, not
sources
Quoted 1 line
or targets. Sigh.
I was thinking about something like this:
From: Borislav Petkov <[email protected]>
Date: Wed, 20 Jan 2016 11:45:36 +0100
Subject: [PATCH] x86/alternatives: Add an auxilary sectionAdd .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch.
Signed-off-by Borislav Petkov <[email protected]>---
arch/x86/kernel/vmlinux.lds.S| 5 +++++1 file changed, 5 insertions(+)arch/x86/kernel/vmlinux.lds.S +5
-0@@ -244,6 +244,11 @@ SECTIONS */ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) + /* + * Auxiliary section for misc instruction patching tasks. See + * static_cpu_has(), for an example. + */ + *(.altinstr_aux) }
Quoted 1 line
/*
How about:
section for code used exclusively before alternatives are run. All references to such code must be patched out by alternatives, normally by using a patch with X86_FEATURE_ALWAYS.
See static_cpu_has() for an example.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 5 lines · H. Peter Anvin
How about:
section for code used exclusively before alternatives are run. All references to such code must be patched out by alternatives, normally by using a patch with
X86_FEATURE_ALWAYS.See
static_cpu_has()for an example.
Sure.
My thinking was to make it a bit more generic so that if we decide to do some different monkey business with the alternatives, to put stuff in there too.
But we can always change that later - it's not like it is user-visible.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 9 lines · Borislav Petkov
Quoted 3 lines · H. Peter Anvin
How about:
section for code used exclusively before alternatives are run. All
references to such code must be patched out by alternatives, normally by using a patch with
X86_FEATURE_ALWAYS.Quoted 2 lines
See
static_cpu_has()for an example.
Quoted 8 lines
Sure.
My thinking was to make it a bit more generic so that if we decide to do
some different monkey business with the alternatives, to put stuff in there too.But we can always change that later - it's not like it is user-visible.
I don't think the verbiage I suggested in any way disagrees with that notion.
Signature · 1 line
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.
Quoted 2 lines · H. Peter Anvin
... "i" (1 << (bit & 7)), "m" (((const char *)boot_cpu_data->x86_capability)[bit >> 3]) ...
Nice!
I was going to do:
"i" (1 << (bit & 31)),
"m" (((boot_cpu_data->x86_capability)[bit >> 5])):-)
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- H. Peter Anvin
maintainerQuoted 11 lines · Borislav Petkov
Quoted 2 lines · H. Peter Anvin
... "i" (1 << (bit & 7)), "m" (((const char *)boot_cpu_data->x86_capability)[bit >> 3]) ...Nice!
I was going to do:
"i" (1 << (bit & 31)), "m" (((boot_cpu_data->x86_capability)[bit >> 5]))
But then you're using testl and get long immediates.
(And the parentheses around boot_cpu_data->x86_capability are redundant.)
-hpa
Quoted 3 lines · H. Peter Anvin
But then you're using testl and get long immediates.
(And the parentheses around
boot_cpu_data->x86_capabilityare redundant.)
Right.
Ok, below is what builds here. So no SOBs etc.
All this include hell wankery is so that we can use boot_cpu_data in cpufeature.h. And that's not simple because boot/mkcpustr.c includes it too so if I carve out struct cpuinfo_x86 to a separate asm/cpuinfo.h header, it complains because it doesn't see it.
Thus this _ASM_BOOT_MKCPUSTR_ yucky marker to stop arch/x86/boot from including it.
I'm very open to better ideas. :-)
Other than that, we do:
+ "6: testb %[bitnum],%[cap_word]\n" + " jnz %l[t_yes]\n" + " jmp %l[t_no]\n" + ".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS),
+ [bitnum] "i" (1 << (bit & 7)),
+ [cap_word] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])
and that has the TESTB.
Thoughts?
--- arch/x86/boot/mkcpustr.c | 5 +++ arch/x86/include/asm/cpufeature.h | 34 +++++++++++++----- arch/x86/include/asm/cpuinfo.h | 73 +++++++++++++++++++++++++++++++++++++++ arch/x86/include/asm/processor.h | 65 ---------------------------------- arch/x86/kernel/cpu/common.c | 6 ---- arch/x86/kernel/vmlinux.lds.S | 9 +++-- 6 files changed, 110 insertions(+), 82 deletions(-) create mode 100644 arch/x86/include/asm/cpuinfo.h
arch/x86/boot/mkcpustr.c +5 -0
@@ -17,6 +17,11 @@#include "../include/asm/required-features.h" #include "../include/asm/disabled-features.h" + +/* +* Stop cpufeature.h from including cpuinfo.h in kernel proper. +*/ +#define _ASM_BOOT_MKCPUSTR_#include "../include/asm/cpufeature.h" #include "../kernel/cpu/capflags.c"
arch/x86/include/asm/cpufeature.h +25 -9
@@ -15,6 +15,10 @@#define NCAPINTS 16/* N 32-bit words worth of info */ #define NBUGINTS 1/* N 32-bit bug flags */ +#ifndef _ASM_BOOT_MKCPUSTR_ +#include <asm/cpuinfo.h> +#endif +/* * Note: If the comment begins with a quoted string, that string is used * in /proc/cpuinfo instead of the macro name. If the string is "",
@@ -412,7 +416,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS )extern void warn_pre_alternatives (void ); -extern bool __static_cpu_has_safe (u16 bit);/* * Static testing of CPU features. Used the same as boot_cpu_has().
@@ -505,7 +508,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) static __always_inline __pure bool _static_cpu_has_safe(u16 bit) {#ifdef CC_HAVE_ASM_GOTO -asm_volatile_goto ("1: jmp %l[t_dynamic]\n" +asm_volatile_goto ("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n"
@@ -530,17 +533,23 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit)" .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); +".section .altinstr_aux,\"ax\"\n" +"6: testb %[bitnum],%[cap_word]\n" +" jnz %l[t_yes]\n" +" jmp %l[t_no]\n" +".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_word] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes:return true; t_no:return false; - t_dynamic: -return __static_cpu_has_safe (bit);#else u8 flag;/* Open-coded due to __stringify() in ALTERNATIVE() */ - asmvolatile ("1: movb $2,%0\n" + asmvolatile ("1: jmp 7f\n" "2:\n" ".section .altinstructions,\"a\"\n" " .long 1b - .\n" /* src offset */
@@ -572,9 +581,16 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) "5: movb $1,%0\n" "6:\n" ".previous\n" + ".section .altinstr_aux,\"ax\"\n" + "7: testb %[bitnum],%[cap_word]\n" + " setnz %0\n" + " jmp 2b\n" + ".previous\n" : "=qm" (flag) - : "i" (bit), "i" (X86_FEATURE_ALWAYS)); -return (flag ==2 ?__static_cpu_has_safe (bit) : flag); + : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_word] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3])); +return (flag !=0 );#endif /* CC_HAVE_ASM_GOTO */ }
arch/x86/include/asm/cpuinfo.h new file +73 -0
73 lines not on this page · raw message
arch/x86/include/asm/processor.h +0 -65
77 lines not on this page · raw message
arch/x86/kernel/cpu/common.c +0 -6
@@ -1483,12 +1483,6 @@ void warn_pre_alternatives(void)EXPORT_SYMBOL_GPL (warn_pre_alternatives);#endif -inline bool __static_cpu_has_safe (u16 bit) -{ -return boot_cpu_has (bit); -} -EXPORT_SYMBOL_GPL (__static_cpu_has_safe); -static void bsp_resume (void ) {if (this_cpu->c_bsp_resume)
arch/x86/kernel/vmlinux.lds.S +7 -2
@@ -244,9 +244,14 @@ SECTIONS */ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) + /* - * Auxiliary section for misc instruction patching tasks. See - * static_cpu_has(), for an example. + * Section for code used exclusively before alternatives are + * run. All references to such code must be patched out by + * alternatives, normally by using a patch with + * X86_FEATURE_ALWAYS. + * + * See static_cpu_has() for an example. */ *(.altinstr_aux) }
Signature · 4 lines
2.3.5 SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg) --
H. Peter Anvin
maintainerQuoted 14 lines · Borislav Petkov
Quoted 3 lines · H. Peter Anvin
But then you're using testl and get long immediates.
(And the parentheses around
boot_cpu_data->x86_capabilityare redundant.)Right.
Ok, below is what builds here. So no SOBs etc.
All this include hell wankery is so that we can use
boot_cpu_dataincpufeature.h. And that's not simple becauseboot/mkcpustr.cincludes it too so if I carve out structcpuinfo_x86to a separateasm/cpuinfo.hheader, it complains because it doesn't see it.
Quoted 5 lines
Thus this _ASM_BOOT_MKCPUSTR_ yucky marker to stop
arch/x86/bootfrom including it.I'm very open to better ideas. :-)
I think the right answer is to split the macros that define specific CPU features into a separate file. It would also make it assembly-safe which would be useful in some other places.
However, I do also want to observe that we already do have this specific marker... it is called __KERNEL__.
-hpa
PATCH 1/1 x86/head_64.S: do not use temporary register to check alignment
We are using temporary %rax register during checking of kernel address alignment. We can ged rid of it since testl instruction is safe and does not change value of the rbp register.
--- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/head_64.S +1 -3
@@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp /* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /*
Signature · 1 line
2.7.0.25.gfc10eb5
Borislav Petkov
AppliedRe: [PATCH] x86/head_64.S: do not use temporary register to check alignment
Quoted 16 lines · Alexander Kuleshov
We are using temporary %rax register during checking of kernel address alignment. We can ged rid of it since testl instruction is safe and does not change value of the rbp register.
Signed-off-by Alexander Kuleshov <[email protected]>Suggested-by Brian Gerst <[email protected]>--- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/x86/kernel/head_64.S +0
-0@@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp
arch/x86/kernel/head_64.S startup_64:
Quoted 10 lines
arch/x86/kernel/head_64.S +1
-4/* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /* --
Applied, thanks.
Signature · 5 lines
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- Borislav Petkov
maintainercover tip-queue 2016-01-26, rest
From: Borislav Petkov <[email protected]>
Hi,
this is the rest of the series today. Main one is the cpufeature cleanup. I merged the AVIC patch from tip:x86/cpu so that the rest applies cleanly. The rest is simplifications/cleanups.
Please apply,
thanks.
Alexander Kuleshov (1):
x86/head_64: Simplify kernel load address alignment check
Borislav Petkov (5):
x86/cpufeature: Carve out X86_FEATURE_*
x86/cpufeature: Replace the old static_cpu_has() with safe variant x86/cpufeature: Get rid of the non-asm goto variant x86/alternatives: Add an auxilary section
x86/vdso: Use static_cpu_has()
Brian Gerst (1):
x86/alternatives: Discard dynamic check after init
Michael S. Tsirkin (3):
x86/asm: Add condition codes clobber to memory barrier macros x86/asm: Drop a comment left over from X86_OOSTORE x86/asm: Tweak the comment about wmb() use for IO
Borislav Petkov
maintainerPATCH 1/10 x86/asm: Add condition codes clobber to memory barrier macros
From: "Michael S. Tsirkin" <[email protected]>
ADDL clobbers flags (such as CF) but barrier.h didn't tell this to gcc. Historically, gcc doesn't need them on x86, and always considers flags clobbered. We are probably missing the cc clobber in a *lot* of places for this reason.
But even if not necessary, it's probably a good thing to add for documentation, and in case gcc semantics ever change.
--- arch/x86/include/asm/barrier.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/x86/include/asm/barrier.h +6 -3
@@ -15,9 +15,12 @@* Some non-Intel clones support out of order store. wmb() ceases to be a * nop for these. */ -#define mb () alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) -#define rmb () alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) -#define wmb () alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) +#define mb () asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc") +#define rmb () asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc") +#define wmb () asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "sfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc")#else #define mb () asm volatile("mfence":::"memory")#define rmb () asm volatile("lfence":::"memory")
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 2/10 x86/asm: Drop a comment left over from X86_OOSTORE
In reply to Borislav PetkovFrom: "Michael S. Tsirkin" <[email protected]>
The comment about wmb() being non-nop to deal with non-intel CPUs is a left over from before commit
09df7c4c8097 ("x86: Remove CONFIG_X86_OOSTORE").
It makes no sense now: in particular, wmb() is not a nop even for regular intel CPUs because of weird use-cases e.g. dealing with WC memory.
Drop this comment.
--- arch/x86/include/asm/barrier.h | 4 ---- 1 file changed, 4 deletions(-)
arch/x86/include/asm/barrier.h +0 -4
@@ -11,10 +11,6 @@*/ #ifdef CONFIG_X86_32 -/* -* Some non-Intel clones support out of order store. wmb() ceases to be a -* nop for these. -*/ #define mb () asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \ X86_FEATURE_XMM2) ::: "memory", "cc")#define rmb () asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 3/10 x86/asm: Tweak the comment about wmb() use for IO
In reply to Borislav PetkovFrom: "Michael S. Tsirkin" <[email protected]>
On x86, we *do* still use the non-nop rmb()/wmb() for IO barriers, but even that is generally questionable.
Leave them around for historical reasons, unless somebody can point to a case where they care about the performance. Tweak the comment so people don't think they are strictly required in all cases.
--- arch/x86/include/asm/barrier.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/include/asm/barrier.h +2 -2
@@ -6,8 +6,8 @@/* * Force strict CPU ordering. -* And yes, this is required on UP too when we're talking -* to devices. +* +* And yes, this might be required on UP too when we're talking to devices. */ #ifdef CONFIG_X86_32
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 4/10 x86/cpufeature: Carve out X86_FEATURE_*
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
Move them to a separate header and have the following dependency:
x86/cpufeatures.h <- x86/processor.h <- x86/cpufeature.h
This makes it easier to use the header in asm code and not include the whole cpufeature.h and add guards for asm.
--- Documentation/kernel-parameters.txt | 2 +- arch/x86/boot/cpuflags.h | 2 +- arch/x86/boot/mkcpustr.c | 2 +- arch/x86/crypto/crc32-pclmul_glue.c | 2 +- arch/x86/crypto/crc32c-intel_glue.c | 2 +- arch/x86/crypto/crct10dif-pclmul_glue.c | 2 +- arch/x86/entry/common.c | 1 + arch/x86/entry/entry_32.S | 2 +- arch/x86/entry/vdso/vdso32-setup.c | 1 - arch/x86/entry/vdso/vdso32/system_call.S | 2 +- arch/x86/entry/vdso/vma.c | 1 + arch/x86/include/asm/alternative.h | 6 - arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/arch_hweight.h | 2 + arch/x86/include/asm/cmpxchg.h | 1 + arch/x86/include/asm/cpufeature.h | 284 +----------------------------- arch/x86/include/asm/cpufeatures.h | 288 +++++++++++++++++++++++++++++++ arch/x86/include/asm/fpu/internal.h | 1 + arch/x86/include/asm/irq_work.h | 2 +- arch/x86/include/asm/mwait.h | 2 + arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/smap.h | 2 +- arch/x86/include/asm/smp.h | 1 - arch/x86/include/asm/thread_info.h | 2 +- arch/x86/include/asm/tlbflush.h | 1 + arch/x86/include/asm/uaccess_64.h | 2 +- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/cyrix.c | 1 + arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/match.c | 2 +- arch/x86/kernel/cpu/mkcapflags.sh | 6 +- arch/x86/kernel/cpu/mtrr/main.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 2 +- arch/x86/kernel/e820.c | 1 + arch/x86/kernel/head_32.S | 2 +- arch/x86/kernel/hpet.c | 1 + arch/x86/kernel/msr.c | 2 +- arch/x86/kernel/verify_cpu.S | 2 +- arch/x86/lib/clear_page_64.S | 2 +- arch/x86/lib/copy_page_64.S | 2 +- arch/x86/lib/copy_user_64.S | 2 +- arch/x86/lib/memcpy_64.S | 2 +- arch/x86/lib/memmove_64.S | 2 +- arch/x86/lib/memset_64.S | 2 +- arch/x86/mm/setup_nx.c | 1 + arch/x86/oprofile/op_model_amd.c | 1 - arch/x86/um/asm/barrier.h | 2 +- lib/atomic64_test.c | 2 +- 50 files changed, 336 insertions(+), 328 deletions(-) create mode 100644 arch/x86/include/asm/cpufeatures.h
Documentation/kernel-parameters.txt +1 -1
@@ -661,7 +661,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. clearcpuid=BITNUM [X86] Disable CPUID feature X for the kernel. See - arch/x86/include/asm/cpufeature.h for the valid bit + arch/x86/include/asm/cpufeatures.h for the valid bit numbers. Note the Linux specific bits are not necessarily stable over kernel options, but the vendor specific ones should be.
arch/x86/boot/cpuflags.h +1 -1
@@ -1,7 +1,7 @@#ifndef BOOT_CPUFLAGS_H #define BOOT_CPUFLAGS_H -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/processor-flags.h> struct cpu_features {
arch/x86/boot/mkcpustr.c +1 -1
@@ -17,7 +17,7 @@#include "../include/asm/required-features.h" #include "../include/asm/disabled-features.h" -#include "../include/asm/cpufeature.h" +#include "../include/asm/cpufeatures.h" #include "../kernel/cpu/capflags.c" int main (void )
arch/x86/crypto/crc32-pclmul_glue.c +1 -1
@@ -33,7 +33,7 @@#include <linux/crc32.h> #include <crypto/internal/hash.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> #include <asm/fpu/api.h>
arch/x86/crypto/crc32c-intel_glue.c +1 -1
@@ -30,7 +30,7 @@#include <linux/kernel.h> #include <crypto/internal/hash.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> #include <asm/fpu/internal.h>
arch/x86/crypto/crct10dif-pclmul_glue.c +1 -1
@@ -30,7 +30,7 @@#include <linux/string.h> #include <linux/kernel.h> #include <asm/fpu/api.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf,
arch/x86/entry/common.c +1 -0
@@ -26,6 +26,7 @@#include <asm/traps.h> #include <asm/vdso.h> #include <asm/uaccess.h> +#include <asm/cpufeature.h> #define CREATE_TRACE_POINTS #include <trace/events/syscalls.h>
arch/x86/entry/entry_32.S +1 -1
@@ -40,7 +40,7 @@ #include <asm/processor-flags.h> #include <asm/ftrace.h> #include <asm/irq_vectors.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h>
arch/x86/entry/vdso/vdso32-setup.c +0 -1
@@ -11,7 +11,6 @@#include <linux/kernel.h> #include <linux/mm_types.h> -#include <asm/cpufeature.h> #include <asm/processor.h> #include <asm/vdso.h>
arch/x86/entry/vdso/vdso32/system_call.S +1 -1
@@ -3,7 +3,7 @@ */ #include <asm/dwarf2.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/entry/vdso/vma.c +1 -0
@@ -20,6 +20,7 @@#include <asm/page.h> #include <asm/hpet.h> #include <asm/desc.h> +#include <asm/cpufeature.h> #if defined(CONFIG_X86_64 )unsigned int __read_mostly vdso64_enabled =1 ;
arch/x86/include/asm/alternative.h +0 -6
@@ -152,12 +152,6 @@ static inline int alternatives_text_reserved(void *start, void *end)".popsection" /* -* This must be included *after* the definition of ALTERNATIVE due to -* <asm/arch_hweight.h> - */ -#include <asm/cpufeature.h> - -/* * Alternative instructions for different CPU types or capabilities. * * This allows to use optimized instructions even on generic binary
arch/x86/include/asm/apic.h +0 -1
@@ -6,7 +6,6 @@#include <asm/alternative.h> #include <asm/cpufeature.h> -#include <asm/processor.h> #include <asm/apicdef.h> #include <linux/atomic.h> #include <asm/fixmap.h>
arch/x86/include/asm/arch_hweight.h +2 -0
@@ -1,6 +1,8 @@#ifndef _ASM_X86_HWEIGHT_H#define _ASM_X86_HWEIGHT_H +#include <asm/cpufeatures.h> +#ifdef CONFIG_64BIT /* popcnt %edi, %eax -- redundant REX prefix for alignment */ #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
arch/x86/include/asm/cmpxchg.h +1 -0
@@ -2,6 +2,7 @@#define ASM_X86_CMPXCHG_H #include <linux/compiler.h> +#include <asm/cpufeatures.h> #include <asm/alternative.h> /* Provides LOCK_PREFIX */ /*
arch/x86/include/asm/cpufeature.h +1 -283
290 lines not on this page · raw message
arch/x86/include/asm/cpufeatures.h new file +288 -0
288 lines not on this page · raw message
arch/x86/include/asm/fpu/internal.h +1 -0
@@ -17,6 +17,7 @@#include <asm/user.h> #include <asm/fpu/api.h> #include <asm/fpu/xstate.h> +#include <asm/cpufeature.h> /* * High level FPU state handling functions:
arch/x86/include/asm/irq_work.h +1 -1
@@ -1,7 +1,7 @@#ifndef _ASM_IRQ_WORK_H#define _ASM_IRQ_WORK_H -#include <asm/processor.h> +#include <asm/cpufeature.h> static inline bool arch_irq_work_has_interrupt (void ) {
arch/x86/include/asm/mwait.h +2 -0
@@ -3,6 +3,8 @@#include <linux/sched.h> +#include <asm/cpufeature.h> +#define MWAIT_SUBSTATE_MASK 0xf#define MWAIT_CSTATE_MASK 0xf#define MWAIT_SUBSTATE_SIZE 4
arch/x86/include/asm/processor.h +1 -2
@@ -13,7 +13,7 @@ struct vm86;#include <asm/types.h> #include <uapi/asm/sigcontext.h> #include <asm/current.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/page.h> #include <asm/pgtable_types.h> #include <asm/percpu.h>
@@ -24,7 +24,6 @@ struct vm86;#include <asm/fpu/types.h> #include <linux/personality.h> -#include <linux/cpumask.h> #include <linux/cache.h> #include <linux/threads.h> #include <linux/math64.h>
arch/x86/include/asm/smap.h +1 -1
@@ -15,7 +15,7 @@#include <linux/stringify.h> #include <asm/nops.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> /* "Raw" instruction opcodes */ #define __ASM_CLAC .byte 0x0f,0x01,0xca
arch/x86/include/asm/smp.h +0 -1
@@ -16,7 +16,6 @@#endif #include <asm/thread_info.h> #include <asm/cpumask.h> -#include <asm/cpufeature.h> extern int smp_num_siblings;extern unsigned int num_processors;
arch/x86/include/asm/thread_info.h +1 -1
@@ -49,7 +49,7 @@*/ #ifndef __ASSEMBLY__struct task_struct ; -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <linux/atomic.h> struct thread_info {
arch/x86/include/asm/tlbflush.h +1 -0
@@ -5,6 +5,7 @@#include <linux/sched.h> #include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/special_insns.h> #ifdef CONFIG_PARAVIRT
arch/x86/include/asm/uaccess_64.h +1 -1
@@ -8,7 +8,7 @@#include <linux/errno.h> #include <linux/lockdep.h> #include <asm/alternative.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/page.h> /*
arch/x86/kernel/cpu/Makefile +1 -1
@@ -64,7 +64,7 @@ ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@ -cpufeature = $(src)/../../include/asm/cpufeature.h +cpufeature = $(src)/../../include/asm/cpufeatures.h targets += capflags.c $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE
arch/x86/kernel/cpu/centaur.c +1 -1
@@ -1,7 +1,7 @@#include <linux/bitops.h> #include <linux/kernel.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/e820.h> #include <asm/mtrr.h> #include <asm/msr.h>
arch/x86/kernel/cpu/cyrix.c +1 -0
@@ -8,6 +8,7 @@#include <linux/timer.h> #include <asm/pci-direct.h> #include <asm/tsc.h> +#include <asm/cpufeature.h> #include "cpu.h"
arch/x86/kernel/cpu/intel.c +1 -1
@@ -8,7 +8,7 @@#include <linux/module.h> #include <linux/uaccess.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/pgtable.h> #include <asm/msr.h> #include <asm/bugs.h>
arch/x86/kernel/cpu/intel_cacheinfo.c +1 -1
@@ -14,7 +14,7 @@#include <linux/sysfs.h> #include <linux/pci.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/amd_nb.h> #include <asm/smp.h>
arch/x86/kernel/cpu/match.c +1 -1
@@ -1,5 +1,5 @@#include <asm/cpu_device_id.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <linux/cpu.h> #include <linux/module.h> #include <linux/slab.h>
arch/x86/kernel/cpu/mkcapflags.sh +3 -3
@@ -1,6 +1,6 @@ #!/bin/sh # -# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h +# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h # IN=$1
@@ -49,8 +49,8 @@ dump_array() trap 'rm "$OUT"' EXIT ( - echo "#ifndef _ASM_X86_CPUFEATURE_H" - echo "#include <asm/cpufeature.h>" + echo "#ifndef _ASM_X86_CPUFEATURES_H" + echo "#include <asm/cpufeatures.h>" echo "#endif" echo ""
arch/x86/kernel/cpu/mtrr/main.c +1 -1
@@ -47,7 +47,7 @@#include <linux/smp.h> #include <linux/syscore_ops.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/e820.h> #include <asm/mtrr.h> #include <asm/msr.h>
arch/x86/kernel/cpu/transmeta.c +1 -1
@@ -1,6 +1,6 @@#include <linux/kernel.h> #include <linux/mm.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/msr.h> #include "cpu.h"
arch/x86/kernel/e820.c +1 -0
@@ -24,6 +24,7 @@#include <asm/e820.h> #include <asm/proto.h> #include <asm/setup.h> +#include <asm/cpufeature.h> /* * The e820 map is the map that gets modified e.g. with command line parameters
arch/x86/kernel/head_32.S +1 -1
@@ -19,7 +19,7 @@ #include <asm/setup.h> #include <asm/processor-flags.h> #include <asm/msr-index.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/percpu.h> #include <asm/nops.h> #include <asm/bootparam.h>
arch/x86/kernel/hpet.c +1 -0
@@ -12,6 +12,7 @@#include <linux/pm.h> #include <linux/io.h> +#include <asm/cpufeature.h> #include <asm/irqdomain.h> #include <asm/fixmap.h> #include <asm/hpet.h>
arch/x86/kernel/msr.c +1 -1
@@ -40,7 +40,7 @@#include <linux/uaccess.h> #include <linux/gfp.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/msr.h> static struct class *msr_class;
arch/x86/kernel/verify_cpu.S +1 -1
@@ -30,7 +30,7 @@ * appropriately. Either display a message or halt. */ -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/msr-index.h> verify_cpu:
arch/x86/lib/clear_page_64.S +1 -1
@@ -1,5 +1,5 @@ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/copy_page_64.S +1 -1
@@ -1,7 +1,7 @@ /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/copy_user_64.S +1 -1
@@ -10,7 +10,7 @@ #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h>
arch/x86/lib/memcpy_64.S +1 -1
@@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/memmove_64.S +1 -1
@@ -6,7 +6,7 @@ * - Copyright 2011 Fenghua Yu <[email protected]> */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #undef memmove
arch/x86/lib/memset_64.S +1 -1
@@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen, SuSE Labs */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> .weak memset
arch/x86/mm/setup_nx.c +1 -0
@@ -4,6 +4,7 @@#include <asm/pgtable.h> #include <asm/proto.h> +#include <asm/cpufeature.h> static int disable_nx;
arch/x86/oprofile/op_model_amd.c +0 -1
@@ -24,7 +24,6 @@#include <asm/nmi.h> #include <asm/apic.h> #include <asm/processor.h> -#include <asm/cpufeature.h> #include "op_x86_model.h" #include "op_counter.h"
arch/x86/um/asm/barrier.h +1 -1
@@ -3,7 +3,7 @@#include <asm/asm.h> #include <asm/segment.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cmpxchg.h> #include <asm/nops.h>
lib/atomic64_test.c +1 -1
@@ -17,7 +17,7 @@#include <linux/atomic.h> #ifdef CONFIG_X86 -#include <asm/processor.h> /* for boot_cpu_has below */ +#include <asm/cpufeature.h> /* for boot_cpu_has below */ #endif #define TEST (bit, op, c_op, val) \
Signature · 1 line
2.3.5
tip-bot for Borislav Petkov
merge bot[tip:x86/asm] x86/cpufeature: Carve out X86_FEATURE_*
x86/cpufeature: Carve out X86_FEATURE_*
Commit-ID: cd4d09ec6f6c12a2cc3db5b7d8876a325a53545b Gitweb: http://git.kernel.org/tip/cd4d09ec6f6c12a2cc3db5b7d8876a325a53545b Author: Borislav Petkov <[email protected]> AuthorDate: Tue, 26 Jan 2016 22:12:04 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:17 +0100
x86/cpufeature: Carve out X86_FEATURE_*
Move them to a separate header and have the following dependency:
x86/cpufeatures.h <- x86/processor.h <- x86/cpufeature.h
This makes it easier to use the header in asm code and not include the whole cpufeature.h and add guards for asm.
---
Documentation/kernel-parameters.txt | 2 +-
arch/x86/boot/cpuflags.h | 2 +-
arch/x86/boot/mkcpustr.c | 2 +-
arch/x86/crypto/crc32-pclmul_glue.c | 2 +-
arch/x86/crypto/crc32c-intel_glue.c | 2 +-
arch/x86/crypto/crct10dif-pclmul_glue.c | 2 +-
arch/x86/entry/common.c | 1 +
arch/x86/entry/entry_32.S | 2 +-
arch/x86/entry/vdso/vdso32-setup.c | 1 -
arch/x86/entry/vdso/vdso32/system_call.S | 2 +-
arch/x86/entry/vdso/vma.c | 1 +
arch/x86/include/asm/alternative.h | 6 -
arch/x86/include/asm/apic.h | 1 -
arch/x86/include/asm/arch_hweight.h | 2 +
arch/x86/include/asm/cmpxchg.h | 1 +
arch/x86/include/asm/cpufeature.h | 284 +----------------
.../include/asm/{cpufeature.h => cpufeatures.h} | 336 +--------------------
arch/x86/include/asm/fpu/internal.h | 1 +
arch/x86/include/asm/irq_work.h | 2 +-
arch/x86/include/asm/mwait.h | 2 +
arch/x86/include/asm/processor.h | 3 +-
arch/x86/include/asm/smap.h | 2 +-
arch/x86/include/asm/smp.h | 1 -
arch/x86/include/asm/thread_info.h | 2 +-
arch/x86/include/asm/tlbflush.h | 1 +
arch/x86/include/asm/uaccess_64.h | 2 +-
arch/x86/kernel/cpu/Makefile | 2 +-
arch/x86/kernel/cpu/centaur.c | 2 +-
arch/x86/kernel/cpu/cyrix.c | 1 +
arch/x86/kernel/cpu/intel.c | 2 +-
arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +-
arch/x86/kernel/cpu/match.c | 2 +-
arch/x86/kernel/cpu/mkcapflags.sh | 6 +-
arch/x86/kernel/cpu/mtrr/main.c | 2 +-
arch/x86/kernel/cpu/transmeta.c | 2 +-
arch/x86/kernel/e820.c | 1 +
arch/x86/kernel/head_32.S | 2 +-
arch/x86/kernel/hpet.c | 1 +
arch/x86/kernel/msr.c | 2 +-
arch/x86/kernel/verify_cpu.S | 2 +-
arch/x86/lib/clear_page_64.S | 2 +-
arch/x86/lib/copy_page_64.S | 2 +-
arch/x86/lib/copy_user_64.S | 2 +-
arch/x86/lib/memcpy_64.S | 2 +-
arch/x86/lib/memmove_64.S | 2 +-
arch/x86/lib/memset_64.S | 2 +-
arch/x86/mm/setup_nx.c | 1 +
arch/x86/oprofile/op_model_amd.c | 1 -
arch/x86/um/asm/barrier.h | 2 +-
lib/atomic64_test.c | 2 +-
50 files changed, 54 insertions(+), 658 deletions(-)Documentation/kernel-parameters.txt +1 -1
@@ -666,7 +666,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. clearcpuid=BITNUM [X86] Disable CPUID feature X for the kernel. See - arch/x86/include/asm/cpufeature.h for the valid bit + arch/x86/include/asm/cpufeatures.h for the valid bit numbers. Note the Linux specific bits are not necessarily stable over kernel options, but the vendor specific ones should be.
arch/x86/boot/cpuflags.h +1 -1
@@ -1,7 +1,7 @@#ifndef BOOT_CPUFLAGS_H #define BOOT_CPUFLAGS_H -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/processor-flags.h> struct cpu_features {
arch/x86/boot/mkcpustr.c +1 -1
@@ -17,7 +17,7 @@#include "../include/asm/required-features.h" #include "../include/asm/disabled-features.h" -#include "../include/asm/cpufeature.h" +#include "../include/asm/cpufeatures.h" #include "../kernel/cpu/capflags.c" int main (void )
arch/x86/crypto/crc32-pclmul_glue.c +1 -1
@@ -33,7 +33,7 @@#include <linux/crc32.h> #include <crypto/internal/hash.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> #include <asm/fpu/api.h>
arch/x86/crypto/crc32c-intel_glue.c +1 -1
@@ -30,7 +30,7 @@#include <linux/kernel.h> #include <crypto/internal/hash.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> #include <asm/fpu/internal.h>
arch/x86/crypto/crct10dif-pclmul_glue.c +1 -1
@@ -30,7 +30,7 @@#include <linux/string.h> #include <linux/kernel.h> #include <asm/fpu/api.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cpu_device_id.h> asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf,
arch/x86/entry/common.c +1 -0
@@ -26,6 +26,7 @@#include <asm/traps.h> #include <asm/vdso.h> #include <asm/uaccess.h> +#include <asm/cpufeature.h> #define CREATE_TRACE_POINTS #include <trace/events/syscalls.h>
arch/x86/entry/entry_32.S +1 -1
@@ -40,7 +40,7 @@ #include <asm/processor-flags.h> #include <asm/ftrace.h> #include <asm/irq_vectors.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h>
arch/x86/entry/vdso/vdso32-setup.c +0 -1
@@ -11,7 +11,6 @@#include <linux/kernel.h> #include <linux/mm_types.h> -#include <asm/cpufeature.h> #include <asm/processor.h> #include <asm/vdso.h>
arch/x86/entry/vdso/vdso32/system_call.S +1 -1
@@ -3,7 +3,7 @@ */ #include <asm/dwarf2.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/entry/vdso/vma.c +1 -0
@@ -20,6 +20,7 @@#include <asm/page.h> #include <asm/hpet.h> #include <asm/desc.h> +#include <asm/cpufeature.h> #if defined(CONFIG_X86_64 )unsigned int __read_mostly vdso64_enabled =1 ;
arch/x86/include/asm/alternative.h +0 -6
@@ -152,12 +152,6 @@ static inline int alternatives_text_reserved(void *start, void *end)".popsection" /* -* This must be included *after* the definition of ALTERNATIVE due to -* <asm/arch_hweight.h> - */ -#include <asm/cpufeature.h> - -/* * Alternative instructions for different CPU types or capabilities. * * This allows to use optimized instructions even on generic binary
arch/x86/include/asm/apic.h +0 -1
@@ -6,7 +6,6 @@#include <asm/alternative.h> #include <asm/cpufeature.h> -#include <asm/processor.h> #include <asm/apicdef.h> #include <linux/atomic.h> #include <asm/fixmap.h>
arch/x86/include/asm/arch_hweight.h +2 -0
@@ -1,6 +1,8 @@#ifndef _ASM_X86_HWEIGHT_H#define _ASM_X86_HWEIGHT_H +#include <asm/cpufeatures.h> +#ifdef CONFIG_64BIT /* popcnt %edi, %eax -- redundant REX prefix for alignment */ #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
arch/x86/include/asm/cmpxchg.h +1 -0
@@ -2,6 +2,7 @@#define ASM_X86_CMPXCHG_H #include <linux/compiler.h> +#include <asm/cpufeatures.h> #include <asm/alternative.h> /* Provides LOCK_PREFIX */ /*
arch/x86/include/asm/cpufeature.h +1 -283
290 lines not on this page · raw message
arch/x86/include/asm/cpufeatures.h renamed from arch/x86/include/asm/cpufeature.h +6 -330
348 lines not on this page · raw message
arch/x86/include/asm/fpu/internal.h +1 -0
@@ -17,6 +17,7 @@#include <asm/user.h> #include <asm/fpu/api.h> #include <asm/fpu/xstate.h> +#include <asm/cpufeature.h> /* * High level FPU state handling functions:
arch/x86/include/asm/irq_work.h +1 -1
@@ -1,7 +1,7 @@#ifndef _ASM_IRQ_WORK_H#define _ASM_IRQ_WORK_H -#include <asm/processor.h> +#include <asm/cpufeature.h> static inline bool arch_irq_work_has_interrupt (void ) {
arch/x86/include/asm/mwait.h +2 -0
@@ -3,6 +3,8 @@#include <linux/sched.h> +#include <asm/cpufeature.h> +#define MWAIT_SUBSTATE_MASK 0xf#define MWAIT_CSTATE_MASK 0xf#define MWAIT_SUBSTATE_SIZE 4
arch/x86/include/asm/processor.h +1 -2
@@ -13,7 +13,7 @@ struct vm86;#include <asm/types.h> #include <uapi/asm/sigcontext.h> #include <asm/current.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/page.h> #include <asm/pgtable_types.h> #include <asm/percpu.h>
@@ -24,7 +24,6 @@ struct vm86;#include <asm/fpu/types.h> #include <linux/personality.h> -#include <linux/cpumask.h> #include <linux/cache.h> #include <linux/threads.h> #include <linux/math64.h>
arch/x86/include/asm/smap.h +1 -1
@@ -15,7 +15,7 @@#include <linux/stringify.h> #include <asm/nops.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> /* "Raw" instruction opcodes */ #define __ASM_CLAC .byte 0x0f,0x01,0xca
arch/x86/include/asm/smp.h +0 -1
@@ -16,7 +16,6 @@#endif #include <asm/thread_info.h> #include <asm/cpumask.h> -#include <asm/cpufeature.h> extern int smp_num_siblings;extern unsigned int num_processors;
arch/x86/include/asm/thread_info.h +1 -1
@@ -49,7 +49,7 @@*/ #ifndef __ASSEMBLY__struct task_struct ; -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <linux/atomic.h> struct thread_info {
arch/x86/include/asm/tlbflush.h +1 -0
@@ -5,6 +5,7 @@#include <linux/sched.h> #include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/special_insns.h> #ifdef CONFIG_PARAVIRT
arch/x86/include/asm/uaccess_64.h +1 -1
@@ -8,7 +8,7 @@#include <linux/errno.h> #include <linux/lockdep.h> #include <asm/alternative.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/page.h> /*
arch/x86/kernel/cpu/Makefile +1 -1
@@ -64,7 +64,7 @@ ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@ -cpufeature = $(src)/../../include/asm/cpufeature.h +cpufeature = $(src)/../../include/asm/cpufeatures.h targets += capflags.c $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE
arch/x86/kernel/cpu/centaur.c +1 -1
@@ -1,7 +1,7 @@#include <linux/bitops.h> #include <linux/kernel.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/e820.h> #include <asm/mtrr.h> #include <asm/msr.h>
arch/x86/kernel/cpu/cyrix.c +1 -0
@@ -8,6 +8,7 @@#include <linux/timer.h> #include <asm/pci-direct.h> #include <asm/tsc.h> +#include <asm/cpufeature.h> #include "cpu.h"
arch/x86/kernel/cpu/intel.c +1 -1
@@ -8,7 +8,7 @@#include <linux/module.h> #include <linux/uaccess.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/pgtable.h> #include <asm/msr.h> #include <asm/bugs.h>
arch/x86/kernel/cpu/intel_cacheinfo.c +1 -1
@@ -14,7 +14,7 @@#include <linux/sysfs.h> #include <linux/pci.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/amd_nb.h> #include <asm/smp.h>
arch/x86/kernel/cpu/match.c +1 -1
@@ -1,5 +1,5 @@#include <asm/cpu_device_id.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <linux/cpu.h> #include <linux/module.h> #include <linux/slab.h>
arch/x86/kernel/cpu/mkcapflags.sh +3 -3
@@ -1,6 +1,6 @@ #!/bin/sh # -# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h +# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h # IN=$1
@@ -49,8 +49,8 @@ dump_array() trap 'rm "$OUT"' EXIT ( - echo "#ifndef _ASM_X86_CPUFEATURE_H" - echo "#include <asm/cpufeature.h>" + echo "#ifndef _ASM_X86_CPUFEATURES_H" + echo "#include <asm/cpufeatures.h>" echo "#endif" echo ""
arch/x86/kernel/cpu/mtrr/main.c +1 -1
@@ -47,7 +47,7 @@#include <linux/smp.h> #include <linux/syscore_ops.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/e820.h> #include <asm/mtrr.h> #include <asm/msr.h>
arch/x86/kernel/cpu/transmeta.c +1 -1
@@ -1,6 +1,6 @@#include <linux/kernel.h> #include <linux/mm.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/msr.h> #include "cpu.h"
arch/x86/kernel/e820.c +1 -0
@@ -24,6 +24,7 @@#include <asm/e820.h> #include <asm/proto.h> #include <asm/setup.h> +#include <asm/cpufeature.h> /* * The e820 map is the map that gets modified e.g. with command line parameters
arch/x86/kernel/head_32.S +1 -1
@@ -19,7 +19,7 @@ #include <asm/setup.h> #include <asm/processor-flags.h> #include <asm/msr-index.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/percpu.h> #include <asm/nops.h> #include <asm/bootparam.h>
arch/x86/kernel/hpet.c +1 -0
@@ -12,6 +12,7 @@#include <linux/pm.h> #include <linux/io.h> +#include <asm/cpufeature.h> #include <asm/irqdomain.h> #include <asm/fixmap.h> #include <asm/hpet.h>
arch/x86/kernel/msr.c +1 -1
@@ -40,7 +40,7 @@#include <linux/uaccess.h> #include <linux/gfp.h> -#include <asm/processor.h> +#include <asm/cpufeature.h> #include <asm/msr.h> static struct class *msr_class;
arch/x86/kernel/verify_cpu.S +1 -1
@@ -30,7 +30,7 @@ * appropriately. Either display a message or halt. */ -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/msr-index.h> verify_cpu:
arch/x86/lib/clear_page_64.S +1 -1
@@ -1,5 +1,5 @@ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/copy_page_64.S +1 -1
@@ -1,7 +1,7 @@ /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/copy_user_64.S +1 -1
@@ -10,7 +10,7 @@ #include <asm/current.h> #include <asm/asm-offsets.h> #include <asm/thread_info.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #include <asm/asm.h> #include <asm/smap.h>
arch/x86/lib/memcpy_64.S +1 -1
@@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> /*
arch/x86/lib/memmove_64.S +1 -1
@@ -6,7 +6,7 @@ * - Copyright 2011 Fenghua Yu <[email protected]> */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> #undef memmove
arch/x86/lib/memset_64.S +1 -1
@@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen, SuSE Labs */ #include <linux/linkage.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/alternative-asm.h> .weak memset
arch/x86/mm/setup_nx.c +1 -0
@@ -4,6 +4,7 @@#include <asm/pgtable.h> #include <asm/proto.h> +#include <asm/cpufeature.h> static int disable_nx;
arch/x86/oprofile/op_model_amd.c +0 -1
@@ -24,7 +24,6 @@#include <asm/nmi.h> #include <asm/apic.h> #include <asm/processor.h> -#include <asm/cpufeature.h> #include "op_x86_model.h" #include "op_counter.h"
arch/x86/um/asm/barrier.h +1 -1
@@ -3,7 +3,7 @@#include <asm/asm.h> #include <asm/segment.h> -#include <asm/cpufeature.h> +#include <asm/cpufeatures.h> #include <asm/cmpxchg.h> #include <asm/nops.h>
lib/atomic64_test.c +1 -1
@@ -17,7 +17,7 @@#include <linux/atomic.h> #ifdef CONFIG_X86 -#include <asm/processor.h> /* for boot_cpu_has below */ +#include <asm/cpufeature.h> /* for boot_cpu_has below */ #endif #define TEST (bit, op, c_op, val) \
Borislav Petkov
maintainerPATCH 5/10 x86/cpufeature: Replace the old static_cpu_has() with safe variant
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
So the old one didn't work properly before alternatives had run. And it was supposed to provide an optimized JMP because the assumption was that the offset it is jumping to is within a signed byte and thus a two-byte JMP.
So I did an x86_64 allyesconfig build and dumped all possible sites where static_cpu_has() was used. The optimization amounted to all in all 12(!) places where static_cpu_has() had generated a 2-byte JMP. Which has saved us a whopping 36 bytes!
This clearly is not worth the trouble so we can remove it. The only place where the optimization might count - in __switch_to() - we will handle differently. But that's not subject of this patch.
--- arch/x86/Kconfig.debug | 10 ---- arch/x86/include/asm/cpufeature.h | 100 +++-------------------------------- arch/x86/include/asm/fpu/internal.h | 14 ++--- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 12 +---- arch/x86/kernel/vm86_32.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- fs/btrfs/disk-io.c | 2 +- 8 files changed, 21 insertions(+), 125 deletions(-)
arch/x86/Kconfig.debug +0 -10
@@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL
arch/x86/include/asm/cpufeature.h +7 -93
146 lines not on this page · raw message
arch/x86/include/asm/fpu/internal.h +7 -7
@@ -59,22 +59,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void);*/ static __always_inline __pure bool use_eager_fpu(void) { -return static_cpu_has_safe (X86_FEATURE_EAGER_FPU ); +return static_cpu_has (X86_FEATURE_EAGER_FPU ); } static __always_inline __pure bool use_xsaveopt(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVEOPT ); +return static_cpu_has (X86_FEATURE_XSAVEOPT ); } static __always_inline __pure bool use_xsave(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVE ); +return static_cpu_has (X86_FEATURE_XSAVE ); } static __always_inline __pure bool use_fxsr(void) { -return static_cpu_has_safe (X86_FEATURE_FXSR ); +return static_cpu_has (X86_FEATURE_FXSR ); }/*
@@ -301,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XSAVES , xstate, lmask, hmask, err);else XSTATE_OP (XSAVE , xstate, lmask, hmask, err);
@@ -323,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XRSTORS , xstate, lmask, hmask, err);else XSTATE_OP (XRSTOR , xstate, lmask, hmask, err);
@@ -461,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)* pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ -if (unlikely (static_cpu_has_bug_safe (X86_BUG_FXSAVE_LEAK ))) { +if (unlikely (static_cpu_has_bug (X86_BUG_FXSAVE_LEAK ))) { asmvolatile ("fnclex\n\t" "emms\n\t"
arch/x86/kernel/apic/apic_numachip.c +2 -2
@@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x)unsigned long value;unsigned int id = (x >>24 ) &0xff ; -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , value); id |= (value <<2 ) &0xff00 ; }
@@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)this_cpu_write (cpu_llc_id, node);/* Account for nodes per socket in multi-core-module processors */ -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , val); nodes = ((val >>3 ) &7 ) +1 ; }
arch/x86/kernel/cpu/common.c +2 -10
@@ -1475,19 +1475,11 @@ void cpu_init(void) }#endif -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS -void warn_pre_alternatives (void ) -{ -WARN (1 ,"You're using static_cpu_has before alternatives have run!\n" ); -} -EXPORT_SYMBOL_GPL (warn_pre_alternatives); -#endif - -inline bool __static_cpu_has_safe (u16 bit) +inline bool __static_cpu_has (u16 bit) {return boot_cpu_has (bit); } -EXPORT_SYMBOL_GPL (__static_cpu_has_safe); +EXPORT_SYMBOL_GPL (__static_cpu_has);static void bsp_resume (void ) {
arch/x86/kernel/vm86_32.c +1 -1
@@ -358,7 +358,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)/* make room for real-mode segments */ tsk->thread.sp0 +=16 ; -if (static_cpu_has_safe (X86_FEATURE_SEP )) +if (static_cpu_has (X86_FEATURE_SEP )) tsk->thread.sysenter_cs =0 ;load_sp0 (tss, &tsk->thread);
drivers/cpufreq/intel_pstate.c +1 -1
@@ -1431,7 +1431,7 @@ static int __init intel_pstate_init(void)if (!all_cpu_data)return -ENOMEM ; -if (static_cpu_has_safe (X86_FEATURE_HWP ) && !no_hwp) { +if (static_cpu_has (X86_FEATURE_HWP ) && !no_hwp) {pr_info ("intel_pstate: HWP enabled\n" ); hwp_active++; }
fs/btrfs/disk-io.c +1 -1
@@ -923,7 +923,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags)if (bio_flags &EXTENT_BIO_TREE_LOG )return 0 ;#ifdef CONFIG_X86 -if (static_cpu_has_safe (X86_FEATURE_XMM4_2 )) +if (static_cpu_has (X86_FEATURE_XMM4_2 ))return 0 ;#endif return 1 ;
Signature · 1 line
2.3.5
tip-bot for Borislav Petkov
merge bot[tip:x86/asm] x86/cpufeature: Replace the old static_cpu_has() with safe variant
x86/cpufeature: Replace the old static_cpu_has() with safe variant
Commit-ID: bc696ca05f5a8927329ec276a892341e006b00ba Gitweb: http://git.kernel.org/tip/bc696ca05f5a8927329ec276a892341e006b00ba Author: Borislav Petkov <[email protected]> AuthorDate: Tue, 26 Jan 2016 22:12:05 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:18 +0100
x86/cpufeature: Replace the old static_cpu_has() with safe variant
So the old one didn't work properly before alternatives had run. And it was supposed to provide an optimized JMP because the assumption was that the offset it is jumping to is within a signed byte and thus a two-byte JMP.
So I did an x86_64 allyesconfig build and dumped all possible sites where static_cpu_has() was used. The optimization amounted to all in all 12(!) places where static_cpu_has() had generated a 2-byte JMP. Which has saved us a whopping 36 bytes!
This clearly is not worth the trouble so we can remove it. The only place where the optimization might count - in __switch_to()
- we will handle differently. But that's not subject of this patch.
--- arch/x86/Kconfig.debug | 10 ---- arch/x86/include/asm/cpufeature.h | 100 +++-------------------------------- arch/x86/include/asm/fpu/internal.h | 14 ++--- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 12 +---- arch/x86/kernel/vm86_32.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- fs/btrfs/disk-io.c | 2 +- 8 files changed, 21 insertions(+), 125 deletions(-)
arch/x86/Kconfig.debug +0 -10
@@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL
arch/x86/include/asm/cpufeature.h +7 -93
146 lines not on this page · raw message
arch/x86/include/asm/fpu/internal.h +7 -7
@@ -59,22 +59,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void);*/ static __always_inline __pure bool use_eager_fpu(void) { -return static_cpu_has_safe (X86_FEATURE_EAGER_FPU ); +return static_cpu_has (X86_FEATURE_EAGER_FPU ); } static __always_inline __pure bool use_xsaveopt(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVEOPT ); +return static_cpu_has (X86_FEATURE_XSAVEOPT ); } static __always_inline __pure bool use_xsave(void) { -return static_cpu_has_safe (X86_FEATURE_XSAVE ); +return static_cpu_has (X86_FEATURE_XSAVE ); } static __always_inline __pure bool use_fxsr(void) { -return static_cpu_has_safe (X86_FEATURE_FXSR ); +return static_cpu_has (X86_FEATURE_FXSR ); }/*
@@ -301,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XSAVES , xstate, lmask, hmask, err);else XSTATE_OP (XSAVE , xstate, lmask, hmask, err);
@@ -323,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)WARN_ON (system_state !=SYSTEM_BOOTING ); -if (static_cpu_has_safe (X86_FEATURE_XSAVES )) +if (static_cpu_has (X86_FEATURE_XSAVES ))XSTATE_OP (XRSTORS , xstate, lmask, hmask, err);else XSTATE_OP (XRSTOR , xstate, lmask, hmask, err);
@@ -461,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate)* pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ -if (unlikely (static_cpu_has_bug_safe (X86_BUG_FXSAVE_LEAK ))) { +if (unlikely (static_cpu_has_bug (X86_BUG_FXSAVE_LEAK ))) { asmvolatile ("fnclex\n\t" "emms\n\t"
arch/x86/kernel/apic/apic_numachip.c +2 -2
@@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x)unsigned long value;unsigned int id = (x >>24 ) &0xff ; -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , value); id |= (value <<2 ) &0xff00 ; }
@@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)this_cpu_write (cpu_llc_id, node);/* Account for nodes per socket in multi-core-module processors */ -if (static_cpu_has_safe (X86_FEATURE_NODEID_MSR )) { +if (static_cpu_has (X86_FEATURE_NODEID_MSR )) {rdmsrl (MSR_FAM10H_NODE_ID , val); nodes = ((val >>3 ) &7 ) +1 ; }
arch/x86/kernel/cpu/common.c +2 -10
@@ -1475,19 +1475,11 @@ void cpu_init(void) }#endif -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS -void warn_pre_alternatives (void ) -{ -WARN (1 ,"You're using static_cpu_has before alternatives have run!\n" ); -} -EXPORT_SYMBOL_GPL (warn_pre_alternatives); -#endif - -inline bool __static_cpu_has_safe (u16 bit) +inline bool __static_cpu_has (u16 bit) {return boot_cpu_has (bit); } -EXPORT_SYMBOL_GPL (__static_cpu_has_safe); +EXPORT_SYMBOL_GPL (__static_cpu_has);static void bsp_resume (void ) {
arch/x86/kernel/vm86_32.c +1 -1
@@ -362,7 +362,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)/* make room for real-mode segments */ tsk->thread.sp0 +=16 ; -if (static_cpu_has_safe (X86_FEATURE_SEP )) +if (static_cpu_has (X86_FEATURE_SEP )) tsk->thread.sysenter_cs =0 ;load_sp0 (tss, &tsk->thread);
drivers/cpufreq/intel_pstate.c +1 -1
@@ -1431,7 +1431,7 @@ static int __init intel_pstate_init(void)if (!all_cpu_data)return -ENOMEM ; -if (static_cpu_has_safe (X86_FEATURE_HWP ) && !no_hwp) { +if (static_cpu_has (X86_FEATURE_HWP ) && !no_hwp) {pr_info ("intel_pstate: HWP enabled\n" ); hwp_active++; }
fs/btrfs/disk-io.c +1 -1
@@ -930,7 +930,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags)if (bio_flags &EXTENT_BIO_TREE_LOG )return 0 ;#ifdef CONFIG_X86 -if (static_cpu_has_safe (X86_FEATURE_XMM4_2 )) +if (static_cpu_has (X86_FEATURE_XMM4_2 ))return 0 ;#endif return 1 ;
Borislav Petkov
maintainerPATCH 6/10 x86/cpufeature: Get rid of the non-asm goto variant
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
I can simply quote hpa from the mail:
"Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)"
Booy, am I lazy.
Cleanup the whole CC_HAVE_ASM_GOTO ifdeffery too, while at it.
--- arch/x86/include/asm/cpufeature.h | 49 ++++----------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-)
arch/x86/include/asm/cpufeature.h +5 -44
@@ -129,17 +129,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32];* fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS ) +#if CC_HAVE_ASM_GOTO && defined(CONFIG_X86_FAST_FEATURE_TESTS )extern bool __static_cpu_has (u16 bit);/* * Static testing of CPU features. Used the same as boot_cpu_has(). -* These are only valid after alternatives have run, but will statically -* patch the target code for additional performance. +* These will statically patch the target code for additional +* performance. */ static __always_inline __pure bool _static_cpu_has(u16 bit) { -#ifdef CC_HAVE_ASM_GOTO asm_volatile_goto ("1: jmp %l[t_dynamic]\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * "
@@ -172,45 +171,6 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)return false; t_dynamic:return __static_cpu_has (bit); -#else -u8 flag; -/* Open-coded due to __stringify() in ALTERNATIVE() */ - asmvolatile ("1: movb $2,%0\n" -"2:\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 3f - .\n" /* repl offset */ -" .word %P2\n" /* always replace */ -" .byte 2b - 1b\n" /* source len */ -" .byte 4f - 3f\n" /* replacement len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"3: movb $0,%0\n" -"4:\n" -".previous\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 5f - .\n" /* repl offset */ -" .word %P1\n" /* feature bit */ -" .byte 4b - 3b\n" /* src len */ -" .byte 6f - 5f\n" /* repl len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"5: movb $1,%0\n" -"6:\n" -".previous\n" - :"=qm" (flag) - :"i" (bit),"i" (X86_FEATURE_ALWAYS )); -return (flag ==2 ?__static_cpu_has (bit) : flag); -#endif /* CC_HAVE_ASM_GOTO */ }#define static_cpu_has (bit) \
@@ -221,7 +181,8 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) )#else /* -* gcc 3.x is too stupid to do the static test; fall back to dynamic. +* Fall back to dynamic for gcc versions which don't support asm goto. Should be +* a minority now anyway. */ #define static_cpu_has (bit) boot_cpu_has(bit)#endif
Signature · 1 line
2.3.5
Re: [PATCH 06/10] x86/cpufeature: Get rid of the non-asm goto variant
Quoted 25 lines · Borislav Petkov
From: Borislav Petkov <[email protected]>
I can simply quote hpa from the mail:
"Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)"
Booy, am I lazy.
Cleanup the whole
CC_HAVE_ASM_GOTOifdeffery too, while at it.Signed-off-by Borislav Petkov <[email protected]>Suggested-by "H. Peter Anvin" <[email protected]>--- arch/x86/include/asm/cpufeature.h | 49 ++++----------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-)arch/x86/include/asm/cpufeature.h +0
-0
arch/x86/include/asm/cpufeature.h extern const char * const x86_bug_flags[NBUGINTS*32]; · line 132
Quoted 5 lines
arch/x86/include/asm/cpufeature.h +1
-1@@ -129,17 +129,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32];* fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS ) +#if CC_HAVE_ASM_GOTO && defined(CONFIG_X86_FAST_FEATURE_TESTS )
This should be:
#if defined(CC_HAVE_ASM_GOTO) && ...
--
Brian Gerst
Borislav Petkov
maintainerRe: [PATCH 06/10] x86/cpufeature: Get rid of the non-asm goto variant
Quoted 2 lines · Brian Gerst
This should be:
#ifdefined(CC_HAVE_ASM_GOTO)&& ...
Good catch, thanks!
I thought about it while typing and then gcc didn't complain so I forgot again. :-\
Ingo, I'm sending the patches which changed as a reply to this message.
Thanks.
Signature · 4 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.Borislav Petkov
maintainerPATCH 6/10 x86/cpufeature: Get rid of the non-asm goto variant
From: Borislav Petkov <[email protected]>
Date: Wed, 20 Jan 2016 19:14:03 +0100
Subject: [PATCH 1/4] x86/cpufeature: Get rid of the non-asm goto variant
I can simply quote hpa from the mail:
"Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)"
Booy, am I lazy.
Cleanup the whole CC_HAVE_ASM_GOTO ifdeffery too, while at it.
--- arch/x86/include/asm/cpufeature.h | 49 ++++----------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-)
arch/x86/include/asm/cpufeature.h +5 -44
@@ -129,17 +129,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32];* fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS ) +#if defined(CC_HAVE_ASM_GOTO ) && defined(CONFIG_X86_FAST_FEATURE_TESTS )extern bool __static_cpu_has (u16 bit);/* * Static testing of CPU features. Used the same as boot_cpu_has(). -* These are only valid after alternatives have run, but will statically -* patch the target code for additional performance. +* These will statically patch the target code for additional +* performance. */ static __always_inline __pure bool _static_cpu_has(u16 bit) { -#ifdef CC_HAVE_ASM_GOTO asm_volatile_goto ("1: jmp %l[t_dynamic]\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * "
@@ -172,45 +171,6 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)return false; t_dynamic:return __static_cpu_has (bit); -#else -u8 flag; -/* Open-coded due to __stringify() in ALTERNATIVE() */ - asmvolatile ("1: movb $2,%0\n" -"2:\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 3f - .\n" /* repl offset */ -" .word %P2\n" /* always replace */ -" .byte 2b - 1b\n" /* source len */ -" .byte 4f - 3f\n" /* replacement len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"3: movb $0,%0\n" -"4:\n" -".previous\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 5f - .\n" /* repl offset */ -" .word %P1\n" /* feature bit */ -" .byte 4b - 3b\n" /* src len */ -" .byte 6f - 5f\n" /* repl len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"5: movb $1,%0\n" -"6:\n" -".previous\n" - :"=qm" (flag) - :"i" (bit),"i" (X86_FEATURE_ALWAYS )); -return (flag ==2 ?__static_cpu_has (bit) : flag); -#endif /* CC_HAVE_ASM_GOTO */ }#define static_cpu_has (bit) \
@@ -221,7 +181,8 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) )#else /* -* gcc 3.x is too stupid to do the static test; fall back to dynamic. +* Fall back to dynamic for gcc versions which don't support asm goto. Should be +* a minority now anyway. */ #define static_cpu_has (bit) boot_cpu_has(bit)#endif
Signature · 7 lines
2.3.5
--
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.tip-bot for Borislav Petkov
merge bot[tip:x86/asm] x86/cpufeature: Get rid of the non-asm goto variant
x86/cpufeature: Get rid of the non-asm goto variant
Commit-ID: a362bf9f5e7dd659b96d01382da7b855f4e5a7a1 Gitweb: http://git.kernel.org/tip/a362bf9f5e7dd659b96d01382da7b855f4e5a7a1 Author: Borislav Petkov <[email protected]> AuthorDate: Wed, 27 Jan 2016 09:43:25 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:19 +0100
x86/cpufeature: Get rid of the non-asm goto variant
I can simply quote hpa from the mail:
"Get rid of the non-asm goto variant and just fall back to
dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)"
Booy, am I lazy.
Cleanup the whole CC_HAVE_ASM_GOTO ifdeffery too, while at it.
--- arch/x86/include/asm/cpufeature.h | 49 ++++----------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-)
arch/x86/include/asm/cpufeature.h +5 -44
@@ -129,17 +129,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32];* fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >=4 && defined(CONFIG_X86_FAST_FEATURE_TESTS ) +#if defined(CC_HAVE_ASM_GOTO ) && defined(CONFIG_X86_FAST_FEATURE_TESTS )extern bool __static_cpu_has (u16 bit);/* * Static testing of CPU features. Used the same as boot_cpu_has(). -* These are only valid after alternatives have run, but will statically -* patch the target code for additional performance. +* These will statically patch the target code for additional +* performance. */ static __always_inline __pure bool _static_cpu_has(u16 bit) { -#ifdef CC_HAVE_ASM_GOTO asm_volatile_goto ("1: jmp %l[t_dynamic]\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * "
@@ -172,45 +171,6 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)return false; t_dynamic:return __static_cpu_has (bit); -#else -u8 flag; -/* Open-coded due to __stringify() in ALTERNATIVE() */ - asmvolatile ("1: movb $2,%0\n" -"2:\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 3f - .\n" /* repl offset */ -" .word %P2\n" /* always replace */ -" .byte 2b - 1b\n" /* source len */ -" .byte 4f - 3f\n" /* replacement len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"3: movb $0,%0\n" -"4:\n" -".previous\n" -".section .altinstructions,\"a\"\n" -" .long 1b - .\n" /* src offset */ -" .long 5f - .\n" /* repl offset */ -" .word %P1\n" /* feature bit */ -" .byte 4b - 3b\n" /* src len */ -" .byte 6f - 5f\n" /* repl len */ -" .byte 0\n" /* pad len */ -".previous\n" -".section .discard,\"aw\",@progbits\n" -" .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */ -".previous\n" -".section .altinstr_replacement,\"ax\"\n" -"5: movb $1,%0\n" -"6:\n" -".previous\n" - :"=qm" (flag) - :"i" (bit),"i" (X86_FEATURE_ALWAYS )); -return (flag ==2 ?__static_cpu_has (bit) : flag); -#endif /* CC_HAVE_ASM_GOTO */ }#define static_cpu_has (bit) \
@@ -221,7 +181,8 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) )#else /* -* gcc 3.x is too stupid to do the static test; fall back to dynamic. +* Fall back to dynamic for gcc versions which don't support asm goto. Should be +* a minority now anyway. */ #define static_cpu_has (bit) boot_cpu_has(bit)#endif
Borislav Petkov
maintainerPATCH 8/10 x86/alternatives: Discard dynamic check after init
In reply to Borislav PetkovFrom: Brian Gerst <[email protected]>
Date: Sat, 16 Jan 2016 14:22:04 -0500
Subject: [PATCH -v1.1 8/10] x86/alternatives: Discard dynamic check after init
Move the code to do the dynamic check to the altinstr_aux section so that it is discarded after alternatives have run and a static branch has been chosen.
This way we're changing the dynamic branch from C code to assembly, which makes it *substantially* smaller while avoiding a completely unnecessary call to an out of line function.
Boris: change it to do TESTB, as hpa suggests.
--- arch/x86/include/asm/cpufeature.h | 19 ++++++++++++------- arch/x86/kernel/cpu/common.c | 6 ------ 2 files changed, 12 insertions(+), 13 deletions(-)
arch/x86/include/asm/cpufeature.h +12 -7
@@ -130,8 +130,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];*/ #if defined(CC_HAVE_ASM_GOTO ) && defined(CONFIG_X86_FAST_FEATURE_TESTS ) -extern bool __static_cpu_has (u16 bit); -/* * Static testing of CPU features. Used the same as boot_cpu_has(). * These will statically patch the target code for additional
@@ -139,7 +137,7 @@ extern bool __static_cpu_has(u16 bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { -asm_volatile_goto ("1: jmp %l[t_dynamic]\n" +asm_volatile_goto ("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n"
@@ -164,13 +162,20 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)" .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); +".section .altinstr_aux,\"ax\"\n" +"6:\n" +" testb %[bitnum],%[cap_byte]\n" +" jnz %l[t_yes]\n" +" jmp %l[t_no]\n" +".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes:return true; t_no:return false; - t_dynamic: -return __static_cpu_has (bit); }#define static_cpu_has (bit) \
arch/x86/kernel/cpu/common.c +0 -6
@@ -1475,12 +1475,6 @@ void cpu_init(void) }#endif -inline bool __static_cpu_has (u16 bit) -{ -return boot_cpu_has (bit); -} -EXPORT_SYMBOL_GPL (__static_cpu_has); -static void bsp_resume (void ) {if (this_cpu->c_bsp_resume)
Signature · 8 lines
2.3.5
--
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.tip-bot for Brian Gerst
merge bot[tip:x86/asm] x86/alternatives: Discard dynamic check after init
x86/alternatives: Discard dynamic check after init
Commit-ID: 2476f2fa20568bd5d9e09cd35bcd73e99a6f4cc6 Gitweb: http://git.kernel.org/tip/2476f2fa20568bd5d9e09cd35bcd73e99a6f4cc6 Author: Brian Gerst <[email protected]> AuthorDate: Wed, 27 Jan 2016 09:45:25 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:22 +0100
x86/alternatives: Discard dynamic check after init
Move the code to do the dynamic check to the altinstr_aux section so that it is discarded after alternatives have run and a static branch has been chosen.
This way we're changing the dynamic branch from C code to assembly, which makes it *substantially* smaller while avoiding a completely unnecessary call to an out of line function.
--- arch/x86/include/asm/cpufeature.h | 19 ++++++++++++------- arch/x86/kernel/cpu/common.c | 6 ------ 2 files changed, 12 insertions(+), 13 deletions(-)
arch/x86/include/asm/cpufeature.h +12 -7
@@ -130,8 +130,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];*/ #if defined(CC_HAVE_ASM_GOTO ) && defined(CONFIG_X86_FAST_FEATURE_TESTS ) -extern bool __static_cpu_has (u16 bit); -/* * Static testing of CPU features. Used the same as boot_cpu_has(). * These will statically patch the target code for additional
@@ -139,7 +137,7 @@ extern bool __static_cpu_has(u16 bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { -asm_volatile_goto ("1: jmp %l[t_dynamic]\n" +asm_volatile_goto ("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n"
@@ -164,13 +162,20 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)" .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); +".section .altinstr_aux,\"ax\"\n" +"6:\n" +" testb %[bitnum],%[cap_byte]\n" +" jnz %l[t_yes]\n" +" jmp %l[t_no]\n" +".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes:return true; t_no:return false; - t_dynamic: -return __static_cpu_has (bit); }#define static_cpu_has (bit) \
arch/x86/kernel/cpu/common.c +0 -6
@@ -1475,12 +1475,6 @@ void cpu_init(void) }#endif -inline bool __static_cpu_has (u16 bit) -{ -return boot_cpu_has (bit); -} -EXPORT_SYMBOL_GPL (__static_cpu_has); -static void bsp_resume (void ) {if (this_cpu->c_bsp_resume)
Borislav Petkov
maintainerPATCH 7/10 x86/alternatives: Add an auxilary section
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
Add .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch.
--- arch/x86/kernel/vmlinux.lds.S | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/x86/kernel/vmlinux.lds.S +11 -0
@@ -195,6 +195,17 @@ SECTIONS :init #endif + /* + * Section for code used exclusively before alternatives are run. All + * references to such code must be patched out by alternatives, normally + * by using X86_FEATURE_ALWAYS CPU feature bit. + * + * See static_cpu_has() for an example. + */ + .altinstr_aux : AT(ADDR(.altinstr_aux) - LOAD_OFFSET) { + *(.altinstr_aux) + } + INIT_DATA_SECTION(16) .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
Signature · 1 line
2.3.5
tip-bot for Borislav Petkov
merge bot[tip:x86/asm] x86/alternatives: Add an auxilary section
x86/alternatives: Add an auxilary section
Commit-ID: 337e4cc84021212a87b04b77b65cccc49304909e Gitweb: http://git.kernel.org/tip/337e4cc84021212a87b04b77b65cccc49304909e Author: Borislav Petkov <[email protected]> AuthorDate: Tue, 26 Jan 2016 22:12:07 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:20 +0100
x86/alternatives: Add an auxilary section
Add .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch.
--- arch/x86/kernel/vmlinux.lds.S | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/x86/kernel/vmlinux.lds.S +11 -0
@@ -195,6 +195,17 @@ SECTIONS :init #endif + /* + * Section for code used exclusively before alternatives are run. All + * references to such code must be patched out by alternatives, normally + * by using X86_FEATURE_ALWAYS CPU feature bit. + * + * See static_cpu_has() for an example. + */ + .altinstr_aux : AT(ADDR(.altinstr_aux) - LOAD_OFFSET) { + *(.altinstr_aux) + } + INIT_DATA_SECTION(16) .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
Borislav Petkov
maintainerPATCH 8/10 x86/alternatives: Discard dynamic check after init
In reply to Borislav PetkovFrom: Brian Gerst <[email protected]>
Move the code to do the dynamic check to the altinstr_aux section so that it is discarded after alternatives have run and a static branch has been chosen.
This way we're changing the dynamic branch from C code to assembly, which makes it *substantially* smaller while avoiding a completely unnecessary call to an out of line function.
Boris: change it to do TESTB, as hpa suggests.
--- arch/x86/include/asm/cpufeature.h | 19 ++++++++++++------- arch/x86/kernel/cpu/common.c | 6 ------ 2 files changed, 12 insertions(+), 13 deletions(-)
arch/x86/include/asm/cpufeature.h +12 -7
@@ -130,8 +130,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32];*/ #if CC_HAVE_ASM_GOTO && defined(CONFIG_X86_FAST_FEATURE_TESTS ) -extern bool __static_cpu_has (u16 bit); -/* * Static testing of CPU features. Used the same as boot_cpu_has(). * These will statically patch the target code for additional
@@ -139,7 +137,7 @@ extern bool __static_cpu_has(u16 bit);*/ static __always_inline __pure bool _static_cpu_has(u16 bit) { -asm_volatile_goto ("1: jmp %l[t_dynamic]\n" +asm_volatile_goto ("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n"
@@ -164,13 +162,20 @@ static __always_inline __pure bool _static_cpu_has(u16 bit)" .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); +".section .altinstr_aux,\"ax\"\n" +"6:\n" +" testb %[bitnum],%[cap_byte]\n" +" jnz %l[t_yes]\n" +" jmp %l[t_no]\n" +".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes:return true; t_no:return false; - t_dynamic: -return __static_cpu_has (bit); }#define static_cpu_has (bit) \
arch/x86/kernel/cpu/common.c +0 -6
@@ -1475,12 +1475,6 @@ void cpu_init(void) }#endif -inline bool __static_cpu_has (u16 bit) -{ -return boot_cpu_has (bit); -} -EXPORT_SYMBOL_GPL (__static_cpu_has); -static void bsp_resume (void ) {if (this_cpu->c_bsp_resume)
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 9/10 x86/vdso: Use static_cpu_has()
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
... and simplify and speed up a tad.
--- arch/x86/entry/vdso/vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/entry/vdso/vma.c +1 -1
@@ -255,7 +255,7 @@ static void vgetcpu_cpu_init(void *arg)#ifdef CONFIG_NUMA node =cpu_to_node (cpu);#endif -if (cpu_has (&cpu_data (cpu),X86_FEATURE_RDTSCP )) +if (static_cpu_has (X86_FEATURE_RDTSCP ))write_rdtscp_aux ((node <<12 ) | cpu);/*
Signature · 1 line
2.3.5
tip-bot for Borislav Petkov
merge bot[tip:x86/asm] x86/vdso: Use static_cpu_has()
x86/vdso: Use static_cpu_has()
Commit-ID: 8c725306993198f845038dc9e45a1267099867a6 Gitweb: http://git.kernel.org/tip/8c725306993198f845038dc9e45a1267099867a6 Author: Borislav Petkov <[email protected]> AuthorDate: Tue, 26 Jan 2016 22:12:09 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:23 +0100
x86/vdso: Use static_cpu_has()
... and simplify and speed up a tad.
--- arch/x86/entry/vdso/vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/entry/vdso/vma.c +1 -1
@@ -285,7 +285,7 @@ static void vgetcpu_cpu_init(void *arg)#ifdef CONFIG_NUMA node =cpu_to_node (cpu);#endif -if (cpu_has (&cpu_data (cpu),X86_FEATURE_RDTSCP )) +if (static_cpu_has (X86_FEATURE_RDTSCP ))write_rdtscp_aux ((node <<12 ) | cpu);/*
Borislav Petkov
maintainerPATCH 10/10 x86/head_64: Simplify kernel load address alignment check
In reply to Borislav PetkovFrom: Alexander Kuleshov <[email protected]>
We are using %rax as temporary register to check the kernel address alignment. We don't really have to since the TEST instruction does not clobber the destination operand.
--- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/head_64.S +1 -3
@@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp /* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /*
Signature · 1 line
2.3.5
tip-bot for Alexander Kuleshov
merge bot[tip:x86/boot] x86/boot: Simplify kernel load address alignment check
x86/boot: Simplify kernel load address alignment check
Commit-ID: a4733143085d6c782ac1e6c85778655b6bac1d4e Gitweb: http://git.kernel.org/tip/a4733143085d6c782ac1e6c85778655b6bac1d4e Author: Alexander Kuleshov <[email protected]> AuthorDate: Tue, 26 Jan 2016 22:12:10 +0100 Committer: Ingo Molnar <[email protected]> CommitDate: Sat, 30 Jan 2016 11:22:48 +0100
x86/boot: Simplify kernel load address alignment check
We are using %rax as temporary register to check the kernel address alignment. We don't really have to since the TEST instruction does not clobber the destination operand.
--- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/head_64.S +1 -3
@@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp /* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /*