CR4 fixes (one is urgent)
Subsystems (4)
v2 cover CR4 fixes (one is urgent)
Hi Ingo, etc:
Patch 1 fixes a boot regressions that's new in 4.8.
Patch 2 cleans the whole mess up. It's probably not 4.8 material, but I'm sending it as part of this series for ease of review. If you like, you could apply patch 1 to x86/urgent, merge into x86/asm, and apply patch 3 on top.
Changes from v1:
- Drop the patch that was already applied.
- Get rid of pointless CPUID check, which simplifies it a bit (Borislav)
Andy Lutomirski (2):
x86/boot: Fix another __read_cr4() case on 486
x86/asm: Get rid of __read_cr4_safe()
arch/x86/include/asm/paravirt.h | 4 ---- arch/x86/include/asm/paravirt_types.h | 1 - arch/x86/include/asm/special_insns.h | 22 +++++++--------------- arch/x86/include/asm/tlbflush.h | 2 +- arch/x86/kernel/paravirt.c | 1 - arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/setup.c | 4 +--- arch/x86/power/cpu.c | 2 +- arch/x86/xen/enlighten.c | 1 - 9 files changed, 11 insertions(+), 28 deletions(-)
Signature · 1 line
2.7.4
PATCH v2 2/2 x86/asm: Get rid of __read_cr4_safe()
We use __read_cr4() vs __read_cr4_safe() inconsistently. On CR4-less CPUs, all CR4 bits are effectively clear, so we can make the code simpler and more robust by making __read_cr4() always fix up faults on 32-bit kernels.
This may fix some bugs on old 486-like CPUs, but I don't have any easy way to test that.
--- arch/x86/include/asm/paravirt.h | 4 ---- arch/x86/include/asm/paravirt_types.h | 1 - arch/x86/include/asm/special_insns.h | 22 +++++++--------------- arch/x86/include/asm/tlbflush.h | 2 +- arch/x86/kernel/paravirt.c | 1 - arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/power/cpu.c | 2 +- arch/x86/xen/enlighten.c | 1 - 9 files changed, 11 insertions(+), 26 deletions(-)
arch/x86/include/asm/paravirt.h +0 -4
@@ -80,10 +80,6 @@ static inline unsigned long __read_cr4(void) { return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4); } -static inline unsigned long __read_cr4_safe (void ) -{ - return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe); -}static inline void __write_cr4 (unsigned long x) {
arch/x86/include/asm/paravirt_types.h +0 -1
@@ -108,7 +108,6 @@ struct pv_cpu_ops {unsigned long (*read_cr0)(void );void (*write_cr0)(unsigned long ); -unsigned long (*read_cr4_safe)(void );unsigned long (*read_cr4)(void );void (*write_cr4)(unsigned long );
arch/x86/include/asm/special_insns.h +7 -15
@@ -59,22 +59,19 @@ static inline void native_write_cr3(unsigned long val)static inline unsigned long native_read_cr4 (void ) {unsigned long val; - asmvolatile ("mov %%cr4,%0\n\t" :"=r" (val),"=m" (__force_order)); -return val; -} - -static inline unsigned long native_read_cr4_safe (void ) -{ -unsigned long val; -/* This could fault if %cr4 does not exist. In x86_64, a cr4 always -* exists, so it will never fail. */ #ifdef CONFIG_X86_32 +/* +* This could fault if CR4 does not exist. Non-existent CR4 +* is functionally equivalent to CR4 == 0. Keep it simple and pretend +* that CR4 == 0 on CPUs that don't have CR4. +*/ asm volatile("1: mov %%cr4, %0\n" "2:\n" _ASM_EXTABLE(1b, 2b) : "=r" (val), "=m" (__force_order) : "0" (0));#else - val =native_read_cr4 (); +/* CR4 always exists on x86_64. */ + asmvolatile ("mov %%cr4,%0\n\t" :"=r" (val),"=m" (__force_order));#endif return val; }
@@ -182,11 +179,6 @@ static inline unsigned long __read_cr4(void)return native_read_cr4 (); } -static inline unsigned long __read_cr4_safe (void ) -{ -return native_read_cr4_safe (); -} -static inline void __write_cr4 (unsigned long x) {native_write_cr4 (x);
arch/x86/include/asm/tlbflush.h +1 -1
@@ -81,7 +81,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);/* Initialize cr4 shadow for this CPU. */ static inline void cr4_init_shadow (void ) { -this_cpu_write (cpu_tlbstate.cr4,__read_cr4_safe ()); +this_cpu_write (cpu_tlbstate.cr4,__read_cr4 ()); }/* Set in this cpu's CR4. */
arch/x86/kernel/paravirt.c +0 -1
@@ -332,7 +332,6 @@ __visible struct pv_cpu_ops pv_cpu_ops = { .read_cr0 = native_read_cr0, .write_cr0 = native_write_cr0, .read_cr4 = native_read_cr4, - .read_cr4_safe = native_read_cr4_safe, .write_cr4 = native_write_cr4, #ifdef CONFIG_X86_64 .read_cr8 = native_read_cr8,
arch/x86/kernel/process_32.c +1 -1
@@ -101,7 +101,7 @@ void __show_regs(struct pt_regs *regs, int all) cr0 =read_cr0 (); cr2 =read_cr2 (); cr3 =read_cr3 (); - cr4 =__read_cr4_safe (); + cr4 =__read_cr4 ();printk (KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n" , cr0, cr2, cr3, cr4);
arch/x86/kernel/setup.c +1 -1
@@ -1137,7 +1137,7 @@ void __init setup_arch(char **cmdline_p)* auditing all the early-boot CR4 manipulation would be needed to * rule it out. */ - mmu_cr4_features =__read_cr4_safe (); + mmu_cr4_features =__read_cr4 ();memblock_set_current_limit (get_max_mapped ());
arch/x86/power/cpu.c +1 -1
@@ -130,7 +130,7 @@ static void __save_processor_state(struct saved_context *ctxt) ctxt->cr0 =read_cr0 (); ctxt->cr2 =read_cr2 (); ctxt->cr3 =read_cr3 (); - ctxt->cr4 =__read_cr4_safe (); + ctxt->cr4 =__read_cr4 ();#ifdef CONFIG_X86_64 ctxt->cr8 =read_cr8 ();#endif
arch/x86/xen/enlighten.c +0 -1
@@ -1237,7 +1237,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .write_cr0 = xen_write_cr0, .read_cr4 = native_read_cr4, - .read_cr4_safe = native_read_cr4_safe, .write_cr4 = xen_write_cr4,#ifdef CONFIG_X86_64
Signature · 1 line
2.7.4
PATCH v2 1/2 x86/boot: Fix another __read_cr4() case on 486
In reply to Andy LutomirskiThe condition for reading CR4 was wrong: there are some CPUs with CPUID but not CR4. Rather than trying to make the condition exact, using __read_cr4_safe().
--- arch/x86/kernel/setup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/setup.c +1 -3
@@ -1137,9 +1137,7 @@ void __init setup_arch(char **cmdline_p)* auditing all the early-boot CR4 manipulation would be needed to * rule it out. */ -if (boot_cpu_data.cpuid_level >=0 ) -/* A CPU has %cr4 if and only if it has CPUID. */ - mmu_cr4_features =__read_cr4 (); + mmu_cr4_features =__read_cr4_safe ();memblock_set_current_limit (get_max_mapped ());
Signature · 1 line
2.7.4
Re: [PATCH v2 1/2] x86/boot: Fix another __read_cr4() case on 486
Quoted 3 lines · Andy Lutomirski
The condition for reading CR4 was wrong: there are some CPUs with CPUID but not CR4. Rather than trying to make the condition exact, using
__read_cr4_safe().
Please s/using/use/ while applying.
Quoted 13 lines
Reported-by [email protected]Fixes 18bc7bd523e0 ("x86/boot: Synchronize trampoline_cr4_features and mmu_cr4_features directly")Signed-off-by Andy Lutomirski <[email protected]>--- arch/x86/kernel/setup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)arch/x86/kernel/setup.c +0
-0
arch/x86/kernel/setup.c void __init setup_arch(char **cmdline_p) · line 1143
Quoted 10 lines
arch/x86/kernel/setup.c +1
-3@@ -1137,9 +1137,7 @@ void __init setup_arch(char **cmdline_p)* auditing all the early-boot CR4 manipulation would be needed to * rule it out. */ -if (boot_cpu_data.cpuid_level >=0 ) -/* A CPU has %cr4 if and only if it has CPUID. */ - mmu_cr4_features =__read_cr4 (); + mmu_cr4_features =__read_cr4_safe ();memblock_set_current_limit (get_max_mapped ());
Signature · 5 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.
--tip-bot for Andy Lutomirski
merge bot[tip:x86/urgent] x86/boot: Fix another __read_cr4() case on 486
In reply to Andy Lutomirskix86/boot: Fix another __read_cr4() case on 486
Commit-ID: 192d1dccbfc5b901b66527df9df80304693cf06e Gitweb: http://git.kernel.org/tip/192d1dccbfc5b901b66527df9df80304693cf06e Author: Andy Lutomirski <[email protected]> AuthorDate: Thu, 29 Sep 2016 12:48:11 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Fri, 30 Sep 2016 12:37:40 +0200
x86/boot: Fix another __read_cr4() case on 486
The condition for reading CR4 was wrong: there are some CPUs with CPUID but not CR4. Rather than trying to make the condition exact, use __read_cr4_safe().
--- arch/x86/kernel/setup.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/setup.c +1 -3
@@ -1137,9 +1137,7 @@ void __init setup_arch(char **cmdline_p)* auditing all the early-boot CR4 manipulation would be needed to * rule it out. */ -if (boot_cpu_data.cpuid_level >=0 ) -/* A CPU has %cr4 if and only if it has CPUID. */ - mmu_cr4_features =__read_cr4 (); + mmu_cr4_features =__read_cr4_safe ();memblock_set_current_limit (get_max_mapped ());
tip-bot for Andy Lutomirski
merge bot[tip:x86/asm] x86/asm: Get rid of __read_cr4_safe()
In reply to Andy Lutomirskix86/asm: Get rid of __read_cr4_safe()
Commit-ID: 1ef55be16ed69538f89e0a6508be5e62fdc9851c Gitweb: http://git.kernel.org/tip/1ef55be16ed69538f89e0a6508be5e62fdc9851c Author: Andy Lutomirski <[email protected]> AuthorDate: Thu, 29 Sep 2016 12:48:12 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Fri, 30 Sep 2016 12:40:12 +0200
x86/asm: Get rid of __read_cr4_safe()
We use __read_cr4() vs __read_cr4_safe() inconsistently. On CR4-less CPUs, all CR4 bits are effectively clear, so we can make the code simpler and more robust by making __read_cr4() always fix up faults on 32-bit kernels.
This may fix some bugs on old 486-like CPUs, but I don't have any easy way to test that.
--- arch/x86/include/asm/paravirt.h | 4 ---- arch/x86/include/asm/paravirt_types.h | 1 - arch/x86/include/asm/special_insns.h | 22 +++++++--------------- arch/x86/include/asm/tlbflush.h | 2 +- arch/x86/kernel/paravirt.c | 1 - arch/x86/kernel/process_32.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/power/cpu.c | 2 +- arch/x86/xen/enlighten.c | 1 - 9 files changed, 11 insertions(+), 26 deletions(-)
arch/x86/include/asm/paravirt.h +0 -4
@@ -80,10 +80,6 @@ static inline unsigned long __read_cr4(void) { return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4); } -static inline unsigned long __read_cr4_safe (void ) -{ - return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr4_safe); -}static inline void __write_cr4 (unsigned long x) {
arch/x86/include/asm/paravirt_types.h +0 -1
@@ -108,7 +108,6 @@ struct pv_cpu_ops {unsigned long (*read_cr0)(void );void (*write_cr0)(unsigned long ); -unsigned long (*read_cr4_safe)(void );unsigned long (*read_cr4)(void );void (*write_cr4)(unsigned long );
arch/x86/include/asm/special_insns.h +7 -15
@@ -59,22 +59,19 @@ static inline void native_write_cr3(unsigned long val)static inline unsigned long native_read_cr4 (void ) {unsigned long val; - asmvolatile ("mov %%cr4,%0\n\t" :"=r" (val),"=m" (__force_order)); -return val; -} - -static inline unsigned long native_read_cr4_safe (void ) -{ -unsigned long val; -/* This could fault if %cr4 does not exist. In x86_64, a cr4 always -* exists, so it will never fail. */ #ifdef CONFIG_X86_32 +/* +* This could fault if CR4 does not exist. Non-existent CR4 +* is functionally equivalent to CR4 == 0. Keep it simple and pretend +* that CR4 == 0 on CPUs that don't have CR4. +*/ asm volatile("1: mov %%cr4, %0\n" "2:\n" _ASM_EXTABLE(1b, 2b) : "=r" (val), "=m" (__force_order) : "0" (0));#else - val =native_read_cr4 (); +/* CR4 always exists on x86_64. */ + asmvolatile ("mov %%cr4,%0\n\t" :"=r" (val),"=m" (__force_order));#endif return val; }
@@ -182,11 +179,6 @@ static inline unsigned long __read_cr4(void)return native_read_cr4 (); } -static inline unsigned long __read_cr4_safe (void ) -{ -return native_read_cr4_safe (); -} -static inline void __write_cr4 (unsigned long x) {native_write_cr4 (x);
arch/x86/include/asm/tlbflush.h +1 -1
@@ -81,7 +81,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);/* Initialize cr4 shadow for this CPU. */ static inline void cr4_init_shadow (void ) { -this_cpu_write (cpu_tlbstate.cr4,__read_cr4_safe ()); +this_cpu_write (cpu_tlbstate.cr4,__read_cr4 ()); }/* Set in this cpu's CR4. */
arch/x86/kernel/paravirt.c +0 -1
@@ -332,7 +332,6 @@ __visible struct pv_cpu_ops pv_cpu_ops = { .read_cr0 = native_read_cr0, .write_cr0 = native_write_cr0, .read_cr4 = native_read_cr4, - .read_cr4_safe = native_read_cr4_safe, .write_cr4 = native_write_cr4, #ifdef CONFIG_X86_64 .read_cr8 = native_read_cr8,
arch/x86/kernel/process_32.c +1 -1
@@ -90,7 +90,7 @@ void __show_regs(struct pt_regs *regs, int all) cr0 =read_cr0 (); cr2 =read_cr2 (); cr3 =read_cr3 (); - cr4 =__read_cr4_safe (); + cr4 =__read_cr4 ();printk (KERN_DEFAULT "CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n" , cr0, cr2, cr3, cr4);
arch/x86/kernel/setup.c +1 -1
@@ -1137,7 +1137,7 @@ void __init setup_arch(char **cmdline_p)* auditing all the early-boot CR4 manipulation would be needed to * rule it out. */ - mmu_cr4_features =__read_cr4_safe (); + mmu_cr4_features =__read_cr4 ();memblock_set_current_limit (get_max_mapped ());
arch/x86/power/cpu.c +1 -1
@@ -130,7 +130,7 @@ static void __save_processor_state(struct saved_context *ctxt) ctxt->cr0 =read_cr0 (); ctxt->cr2 =read_cr2 (); ctxt->cr3 =read_cr3 (); - ctxt->cr4 =__read_cr4_safe (); + ctxt->cr4 =__read_cr4 ();#ifdef CONFIG_X86_64 ctxt->cr8 =read_cr8 ();#endif
arch/x86/xen/enlighten.c +0 -1
@@ -1237,7 +1237,6 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .write_cr0 = xen_write_cr0, .read_cr4 = native_read_cr4, - .read_cr4_safe = native_read_cr4_safe, .write_cr4 = xen_write_cr4,#ifdef CONFIG_X86_64