diff options
Diffstat (limited to 'arch/x86/include/asm/cpufeature.h')
| -rw-r--r-- | arch/x86/include/asm/cpufeature.h | 13 | 
1 files changed, 9 insertions, 4 deletions
| diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 16a51e7288d5..1261842d006c 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -173,20 +173,25 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit);   * means that the boot_cpu_has() variant is already fast enough for the   * majority of cases and you should stick to using it as it is generally   * only two instructions: a RIP-relative MOV and a TEST. + * + * Do not use an "m" constraint for [cap_byte] here: gcc doesn't know + * that this is only used on a fallback path and will sometimes cause + * it to manifest the address of boot_cpu_data in a register, fouling + * the mainline (post-initialization) code.   */  static __always_inline bool _static_cpu_has(u16 bit)  {  	asm_volatile_goto(  		ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") -		".section .altinstr_aux,\"ax\"\n" +		".pushsection .altinstr_aux,\"ax\"\n"  		"6:\n" -		" testb %[bitnum],%[cap_byte]\n" +		" testb %[bitnum]," _ASM_RIP(%P[cap_byte]) "\n"  		" jnz %l[t_yes]\n"  		" jmp %l[t_no]\n" -		".previous\n" +		".popsection\n"  		 : : [feature]  "i" (bit),  		     [bitnum]   "i" (1 << (bit & 7)), -		     [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) +		     [cap_byte] "i" (&((const char *)boot_cpu_data.x86_capability)[bit >> 3])  		 : : t_yes, t_no);  t_yes:  	return true; |