x86 fixes
Subsystems (5)
Linus,
Please pull the latest x86-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-urgent-for-linus
# HEAD: dc4fac84f8e66b147921ebdc385e767d5def7422 x86/mm: Switch from TASK_SIZE to TASK_SIZE_MAX in the page fault code
Misc fixes: EFI, entry code, pkeys and MPX fixes, TASK_SIZE cleanups and a tsc frequency table fix.
Thanks,
Ingo
------------------>
Andy Lutomirski (2):
x86/fsgsbase/64: Use TASK_SIZE_MAX for FSBASE/GSBASE upper limits x86/mm: Switch from TASK_SIZE to TASK_SIZE_MAX in the page fault code
Dave Hansen (2):
x86/cpufeature, x86/mm/pkeys: Fix broken compile-time disabling of pkeys x86/mm/mpx: Work around MPX erratum SKD046
Jeremy Compostella (1):
x86/tsc: Add missing Cherrytrail frequency to the table
Josh Poimboeuf (1):
x86/entry/64: Fix stack return address retrieval in thunk
Linus Torvalds (1):
x86/efi: Fix 7-parameter efi_call()s
arch/x86/entry/thunk_64.S | 11 +++++----- arch/x86/include/asm/bugs.h | 8 +++++++ arch/x86/include/asm/cpufeature.h | 12 +++++------ arch/x86/include/asm/disabled-features.h | 6 +++--- arch/x86/kernel/cpu/common.c | 7 ++++++ arch/x86/kernel/cpu/intel.c | 37 ++++++++++++++++++++++++++++++++ arch/x86/kernel/process_64.c | 4 ++-- arch/x86/kernel/ptrace.c | 4 ++-- arch/x86/kernel/tsc_msr.c | 3 +++ arch/x86/mm/fault.c | 11 +++++++--- arch/x86/platform/efi/efi_stub_64.S | 9 ++++---- 11 files changed, 85 insertions(+), 27 deletions(-)
arch/x86/entry/thunk_64.S +5 -6
@@ -8,16 +8,15 @@ #include <linux/linkage.h> #include "calling.h" #include <asm/asm.h> -#include <asm/frame.h> /* rdi: arg1 ... normal C conventions. rax is saved/restored. */ .macro THUNK name, func, put_ret_addr_in_rdi=0 .globl \name .type \name, @function \name: - FRAME_BEGIN + pushq %rbp + movq %rsp, %rbp - /* this one pushes 9 elems, the next one would be %rIP */ pushq %rdi pushq %rsi pushq %rdx
@@ -29,8 +28,8 @@ pushq %r11 .if \put_ret_addr_in_rdi - /* 9*8(%rsp) is return addr on stack */ - movq 9*8(%rsp), %rdi + /* 8(%rbp) is return addr on stack */ + movq 8(%rbp), %rdi .endif call \func
@@ -65,7 +64,7 @@ popq %rdx popq %rsi popq %rdi - FRAME_END + popq %rbp ret _ASM_NOKPROBE(restore) #endif
arch/x86/include/asm/bugs.h +8 -0
@@ -1,8 +1,16 @@#ifndef _ASM_X86_BUGS_H#define _ASM_X86_BUGS_H +#include <asm/processor.h> +extern void check_bugs (void ); +#if defined(CONFIG_CPU_SUP_INTEL ) +void check_mpx_erratum (struct cpuinfo_x86 *c); +#else +static inline void check_mpx_erratum (struct cpuinfo_x86 *c) {} +#endif +#if defined(CONFIG_CPU_SUP_INTEL ) && defined(CONFIG_X86_32 )int ppro_with_ram_bug (void );#else
arch/x86/include/asm/cpufeature.h +6 -6
@@ -64,9 +64,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) || \ (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) || \ (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK16)) ) + (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) || \ + (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) || \ + (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) )#define DISABLED_MASK_BIT_SET (bit) \ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & DISABLED_MASK0 )) || \
@@ -83,9 +83,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) || \ (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) || \ (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ - (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ - (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK16)) ) + (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) || \ + (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) || \ + (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) )#define cpu_has (c, bit) \ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
arch/x86/include/asm/disabled-features.h +3 -3
@@ -29,11 +29,11 @@#endif /* CONFIG_X86_64 */ #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS -# define DISABLE_PKU (1<<(X86_FEATURE_PKU)) -# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE)) -#else # define DISABLE_PKU 0# define DISABLE_OSPKE 0 +#else +# define DISABLE_PKU (1<<(X86_FEATURE_PKU & 31)) +# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31))#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */ /*
arch/x86/kernel/cpu/common.c +7 -0
@@ -37,6 +37,7 @@#include <asm/mtrr.h> #include <linux/numa.h> #include <asm/asm.h> +#include <asm/bugs.h> #include <asm/cpu.h> #include <asm/mce.h> #include <asm/msr.h>
@@ -270,6 +271,8 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c)static __init int setup_disable_smep (char *arg) {setup_clear_cpu_cap (X86_FEATURE_SMEP ); +/* Check for things that depend on SMEP being enabled: */ +check_mpx_erratum (&boot_cpu_data);return 1 ; }__setup ("nosmep" , setup_disable_smep);
@@ -310,6 +313,10 @@ static bool pku_disabled; static __always_inline void setup_pku(struct cpuinfo_x86 *c) { +/* check the boot processor, plus compile options for PKU: */ +if (!cpu_feature_enabled (X86_FEATURE_PKU )) +return ; +/* checks the actual processor's cpuid bits: */ if (!cpu_has (c,X86_FEATURE_PKU ))return ;if (pku_disabled)
arch/x86/kernel/cpu/intel.c +37 -0
@@ -25,6 +25,41 @@#include <asm/apic.h> #endif +/* +* Just in case our CPU detection goes bad, or you have a weird system, +* allow a way to override the automatic disabling of MPX. +*/ +static int forcempx; + +static int __init forcempx_setup (char *__unused) +{ + forcempx =1 ; + +return 1 ; +} +__setup ("intel-skd-046-workaround=disable" , forcempx_setup); + +void check_mpx_erratum (struct cpuinfo_x86 *c) +{ +if (forcempx) +return ; +/* +* Turn off the MPX feature on CPUs where SMEP is not +* available or disabled. +* +* Works around Intel Erratum SKD046: "Branch Instructions +* May Initialize MPX Bound Registers Incorrectly". +* +* This might falsely disable MPX on systems without +* SMEP, like Atom processors without SMEP. But there +* is no such hardware known at the moment. +*/ +if (cpu_has (c,X86_FEATURE_MPX ) && !cpu_has (c,X86_FEATURE_SMEP )) { +setup_clear_cpu_cap (X86_FEATURE_MPX ); +pr_warn ("x86/mpx: Disabling MPX since SMEP not present\n" ); + } +} +static void early_init_intel (struct cpuinfo_x86 *c) {u64 misc_enable;
@@ -173,6 +208,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)if (edx & (1U <<28 )) c->x86_coreid_bits =get_count_order ((ebx >>16 ) &0xff ); } + +check_mpx_erratum (c); }#ifdef CONFIG_X86_32
arch/x86/kernel/process_64.c +2 -2
@@ -532,7 +532,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)switch (code) {case ARCH_SET_GS : -if (addr >=TASK_SIZE_OF (task)) +if (addr >=TASK_SIZE_MAX )return -EPERM ; cpu =get_cpu (); task->thread.gsindex =0 ;
@@ -546,7 +546,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)case ARCH_SET_FS :/* Not strictly needed for fs, but do it for symmetry with gs */ -if (addr >=TASK_SIZE_OF (task)) +if (addr >=TASK_SIZE_MAX )return -EPERM ; cpu =get_cpu (); task->thread.fsindex =0 ;
arch/x86/kernel/ptrace.c +2 -2
@@ -392,7 +392,7 @@ static int putreg(struct task_struct *child,#ifdef CONFIG_X86_64 case offsetof(struct user_regs_struct ,fs_base): -if (value >=TASK_SIZE_OF (child)) +if (value >=TASK_SIZE_MAX )return -EIO ;/* * When changing the segment base, use do_arch_prctl
@@ -406,7 +406,7 @@ static int putreg(struct task_struct *child,/* * Exactly the same here as the %fs handling above. */ -if (value >=TASK_SIZE_OF (child)) +if (value >=TASK_SIZE_MAX )return -EIO ;if (child->thread.gsbase != value)return do_arch_prctl (child,ARCH_SET_GS , value);
arch/x86/kernel/tsc_msr.c +3 -0
@@ -23,6 +23,7 @@#include <asm/param.h> /* CPU reference clock frequency: in KHz */ +#define FREQ_80 80000#define FREQ_83 83200#define FREQ_100 99840#define FREQ_133 133200
@@ -56,6 +57,8 @@ static struct freq_desc freq_desc_tables[] = { { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },/* ANN */ { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, +/* AIRMONT */ + { 6, 0x4c, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, FREQ_80, 0, 0, 0 } }, };static int match_cpu (u8 family,u8 model)
arch/x86/mm/fault.c +8 -3
@@ -292,7 +292,7 @@ void vmalloc_sync_all(void)return ;for (address =VMALLOC_START &PMD_MASK ; - address >=TASK_SIZE && address <FIXADDR_TOP ; + address >=TASK_SIZE_MAX && address <FIXADDR_TOP ; address +=PMD_SIZE ) {struct page *page;
@@ -854,8 +854,13 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, return; }#endif -/* Kernel addresses are always protection faults: */ -if (address >=TASK_SIZE ) + +/* +* To avoid leaking information about the kernel page table +* layout, pretend that user-mode accesses to kernel addresses +* are always protection faults. +*/ +if (address >=TASK_SIZE_MAX ) error_code |=PF_PROT ;if (likely (show_unhandled_signals))
arch/x86/platform/efi/efi_stub_64.S +4 -5
@@ -11,7 +11,6 @@ #include <asm/msr.h> #include <asm/processor-flags.h> #include <asm/page_types.h> -#include <asm/frame.h> #define SAVE_XMM \ mov %rsp, %rax; \
@@ -40,10 +39,10 @@ mov (%rsp), %rsp ENTRY(efi_call) - FRAME_BEGIN + pushq %rbp + movq %rsp, %rbp SAVE_XMM - mov (%rsp), %rax - mov 8(%rax), %rax + mov 16(%rbp), %rax subq $48, %rsp mov %r9, 32(%rsp) mov %rax, 40(%rsp)
@@ -53,6 +52,6 @@ ENTRY(efi_call) call *%rdi addq $48, %rsp RESTORE_XMM - FRAME_END + popq %rbp ret ENDPROC(efi_call)