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: 7030a7e9321166eef44c811fe4af4d460360d424 x86/cpu/amd: Remove an unneeded condition in srat_detect_node()
Misc changes:
- fix lguest bug
- fix /proc/meminfo output on certain configs
- fix pvclock bug
- fix reboot on certain iMacs by adding new reboot quirk
- fix bootup crash
- fix FPU boot line option parsing
- add more x86 self-tests
- small cleanups, documentation improvements, etc.
out-of-topic modifications in x86-urgent-for-linus:
-----------------------------------------------------
drivers/lguest/core.c # e27d90e8be08: lguest: Map switcher text R/
tools/testing/selftests/x86/Makefile# 65cacec1ba90: selftests/x86: Test __kernel
# 0f672809f91a: selftests/x86: Disable the l
tools/testing/selftests/x86/vdso_restorer.c# 65cacec1ba90: selftests/x86: Test __kernel
Thanks,
Ingo
------------------>
Andy Lutomirski (5):
x86/mm: Add barriers and document switch_mm()-vs-flush synchronization selftests/x86: Disable the ldt_gdt_64 test for now selftests/x86: Test __kernel_sigreturn and __kernel_rt_sigreturn x86/mm: Improve switch_mm() barrier comments x86/vdso/pvclock: Protect STABLE check with the seqcount
Borislav Petkov (1):
x86/boot: Hide local labels in verify_cpu()
Dan Carpenter (1):
x86/cpu/amd: Remove an unneeded condition in srat_detect_node()
Dave Jones (1):
x86/mm/pat: Make split_page_count() check for empty levels to fix /proc/meminfo output
H.J. Lu (1):
x86/boot: Double BOOT_HEAP_SIZE to 64KB
Kefeng Wang (1):
x86/mm: Use PAGE_ALIGNED instead of IS_ALIGNED
Mario Kleiner (1):
x86/reboot/quirks: Add iMac10,1 to pci_reboot_dmi_table[]
Rusty Russell (1):
lguest: Map switcher text R/O
yu-cheng yu (4):
x86/fpu: Fix early FPU command-line parsing
x86/fpu: Disable XGETBV1 when no XSAVE
x86/fpu: Disable MPX when eagerfpu is off
x86/fpu: Disable AVX when eagerfpu is off
arch/x86/entry/vdso/vclock_gettime.c | 12 +-- arch/x86/include/asm/boot.h | 2 +- arch/x86/include/asm/fpu/internal.h | 1 + arch/x86/include/asm/fpu/xstate.h | 11 +- arch/x86/include/asm/lguest.h | 4 +- arch/x86/include/asm/mmu_context.h | 34 +++++- arch/x86/kernel/cpu/amd.c | 3 +- arch/x86/kernel/fpu/init.c | 161 ++++++++++++++-------------- arch/x86/kernel/fpu/xstate.c | 4 +- arch/x86/kernel/reboot.c | 8 ++ arch/x86/kernel/verify_cpu.S | 50 ++++----- arch/x86/mm/init_64.c | 3 +- arch/x86/mm/pageattr.c | 3 + arch/x86/mm/tlb.c | 29 ++++- drivers/lguest/core.c | 74 +++++++++---- tools/testing/selftests/x86/Makefile | 6 +- tools/testing/selftests/x86/vdso_restorer.c | 88 +++++++++++++++ 17 files changed, 342 insertions(+), 151 deletions(-) create mode 100644 tools/testing/selftests/x86/vdso_restorer.c
arch/x86/entry/vdso/vclock_gettime.c +6 -6
@@ -126,23 +126,23 @@ static notrace cycle_t vread_pvclock(int *mode)* * On Xen, we don't appear to have that guarantee, but Xen still * supplies a valid seqlock using the version field. - +* * We only do pvclock vdso timing at all if * PVCLOCK_TSC_STABLE_BIT is set, and we interpret that bit to * mean that all vCPUs have matching pvti and that the TSC is * synced, so we can just look at vCPU 0's pvti. */ -if (unlikely (!(pvti->flags &PVCLOCK_TSC_STABLE_BIT ))) { - *mode =VCLOCK_NONE ; -return 0 ; - } - do { version = pvti->version; smp_rmb(); + if (unlikely(!(pvti->flags & PVCLOCK_TSC_STABLE_BIT))) { + *mode = VCLOCK_NONE; + return 0; + } + tsc = rdtsc_ordered(); pvti_tsc_to_system_mul = pvti->tsc_to_system_mul; pvti_tsc_shift = pvti->tsc_shift;
arch/x86/include/asm/boot.h +1 -1
@@ -27,7 +27,7 @@#define BOOT_HEAP_SIZE 0x400000#else /* !CONFIG_KERNEL_BZIP2 */ -#define BOOT_HEAP_SIZE 0x8000 +#define BOOT_HEAP_SIZE 0x10000#endif /* !CONFIG_KERNEL_BZIP2 */
arch/x86/include/asm/fpu/internal.h +1 -0
@@ -42,6 +42,7 @@ extern void fpu__init_cpu_xstate(void);extern void fpu__init_system (struct cpuinfo_x86 *c);extern void fpu__init_check_bugs (void );extern void fpu__resume_cpu (void ); +extern u64 fpu__get_supported_xfeatures_mask (void );/* * Debugging facility:
arch/x86/include/asm/fpu/xstate.h +6 -5
@@ -20,15 +20,16 @@/* Supported features which support lazy state saving */ #define XFEATURE_MASK_LAZY (XFEATURE_MASK_FP | \ - XFEATURE_MASK_SSE | \ + XFEATURE_MASK_SSE) + +/* Supported features which require eager state saving */ +#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | \ + XFEATURE_MASK_BNDCSR | \ XFEATURE_MASK_YMM | \ - XFEATURE_MASK_OPMASK | \ + XFEATURE_MASK_OPMASK | \ XFEATURE_MASK_ZMM_Hi256 | \ XFEATURE_MASK_Hi16_ZMM) -/* Supported features which require eager state saving */ -#define XFEATURE_MASK_EAGER (XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR) -/* All currently supported features */ #define XCNTXT_MASK (XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
arch/x86/include/asm/lguest.h +3 -1
@@ -12,7 +12,9 @@#define GUEST_PL 1/* Page for Switcher text itself, then two pages per cpu */ -#define TOTAL_SWITCHER_PAGES (1 + 2 * nr_cpu_ids) +#define SWITCHER_TEXT_PAGES (1) +#define SWITCHER_STACK_PAGES (2 * nr_cpu_ids) +#define TOTAL_SWITCHER_PAGES (SWITCHER_TEXT_PAGES + SWITCHER_STACK_PAGES)/* Where we map the Switcher, in both Host and Guest. */ extern unsigned long switcher_addr;
arch/x86/include/asm/mmu_context.h +33 -1
@@ -116,8 +116,36 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,#endif cpumask_set_cpu (cpu,mm_cpumask (next)); -/* Re-load page tables */ +/* +* Re-load page tables. +* +* This logic has an ordering constraint: +* +* CPU 0: Write to a PTE for 'next' +* CPU 0: load bit 1 in mm_cpumask. if nonzero, send IPI. +* CPU 1: set bit 1 in next's mm_cpumask +* CPU 1: load from the PTE that CPU 0 writes (implicit) +* +* We need to prevent an outcome in which CPU 1 observes +* the new PTE value and CPU 0 observes bit 1 clear in +* mm_cpumask. (If that occurs, then the IPI will never +* be sent, and CPU 0's TLB will contain a stale entry.) +* +* The bad outcome can occur if either CPU's load is +* reordered before that CPU's store, so both CPUs must +* execute full barriers to prevent this from happening. +* +* Thus, switch_mm needs a full barrier between the +* store to mm_cpumask and any operation that could load +* from next->pgd. TLB fills are special and can happen +* due to instruction fetches or for no reason at all, +* and neither LOCK nor MFENCE orders them. +* Fortunately, load_cr3() is serializing and gives the +* ordering guarantee we need. +* +*/ load_cr3 (next->pgd); +trace_tlb_flush (TLB_FLUSH_ON_TASK_SWITCH ,TLB_FLUSH_ALL );/* Stop flush ipis for the previous mm */
@@ -156,10 +184,14 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,* schedule, protecting us from simultaneous changes. */ cpumask_set_cpu (cpu,mm_cpumask (next)); +/* * We were in lazy tlb mode and leave_mm disabled * tlb flush IPI delivery. We must reload CR3 * to make sure to use no freed page tables. +* +* As above, load_cr3() is serializing and orders TLB +* fills with respect to the mm_cpumask write. */ load_cr3 (next->pgd);trace_tlb_flush (TLB_FLUSH_ON_TASK_SWITCH ,TLB_FLUSH_ALL );
arch/x86/kernel/cpu/amd.c +1 -2
@@ -434,8 +434,7 @@ static void srat_detect_node(struct cpuinfo_x86 *c)*/ int ht_nodeid = c->initial_apicid; -if (ht_nodeid >=0 && - __apicid_to_node[ht_nodeid] !=NUMA_NO_NODE ) +if (__apicid_to_node[ht_nodeid] !=NUMA_NO_NODE ) node = __apicid_to_node[ht_nodeid];/* Pick a nearby node */ if (!node_online (node))
arch/x86/kernel/fpu/init.c +83 -78
203 lines not on this page · raw message
arch/x86/kernel/fpu/xstate.c +2 -2
@@ -52,6 +52,7 @@ void fpu__xstate_clear_all_cpu_caps(void)setup_clear_cpu_cap (X86_FEATURE_AVX512ER );setup_clear_cpu_cap (X86_FEATURE_AVX512CD );setup_clear_cpu_cap (X86_FEATURE_MPX ); +setup_clear_cpu_cap (X86_FEATURE_XGETBV1 ); }/*
@@ -632,8 +633,7 @@ void __init fpu__init_system_xstate(void)BUG (); } -/* Support only the state known to the OS: */ - xfeatures_mask = xfeatures_mask &XCNTXT_MASK ; + xfeatures_mask &=fpu__get_supported_xfeatures_mask ();/* Enable xstate instructions to be able to continue with initialization: */ fpu__init_cpu_xstate ();
arch/x86/kernel/reboot.c +8 -0
@@ -182,6 +182,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"), }, }, + { /* Handle problems with rebooting on the iMac10,1. */ + .callback = set_pci_reboot, + .ident = "Apple iMac10,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac10,1"), + }, + },/* ASRock */ {/* Handle problems with rebooting on ASRock Q1900DC-ITX */
arch/x86/kernel/verify_cpu.S +25 -25
115 lines not on this page · raw message
arch/x86/mm/init_64.c +1 -2
@@ -814,8 +814,7 @@ remove_pte_table(pte_t *pte_start, unsigned long addr, unsigned long end,if (phys_addr < (phys_addr_t )0x40000000 )return ; -if (IS_ALIGNED (addr,PAGE_SIZE ) && -IS_ALIGNED (next,PAGE_SIZE )) { +if (PAGE_ALIGNED (addr) &&PAGE_ALIGNED (next)) {/* * Do not free direct mapping pages since they were * freed when offlining, or simplely not in use.
arch/x86/mm/pageattr.c +3 -0
@@ -66,6 +66,9 @@ void update_page_count(int level, unsigned long pages)static void split_page_count (int level) { +if (direct_pages_count[level] ==0 ) +return ; + direct_pages_count[level]--; direct_pages_count[level -1 ] +=PTRS_PER_PTE ; }
arch/x86/mm/tlb.c +26 -3
@@ -161,7 +161,10 @@ void flush_tlb_current_task(void)preempt_disable ();count_vm_tlb_event (NR_TLB_LOCAL_FLUSH_ALL ); + +/* This is an implicit full barrier that synchronizes with switch_mm. */ local_flush_tlb (); +trace_tlb_flush (TLB_LOCAL_SHOOTDOWN ,TLB_FLUSH_ALL );if (cpumask_any_but (mm_cpumask (mm),smp_processor_id ()) < nr_cpu_ids)flush_tlb_others (mm_cpumask (mm), mm,0UL ,TLB_FLUSH_ALL );
@@ -188,17 +191,29 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,unsigned long base_pages_to_flush =TLB_FLUSH_ALL ;preempt_disable (); -if (current->active_mm != mm) +if (current->active_mm != mm) { +/* Synchronize with switch_mm. */ +smp_mb (); + goto out; + }if (!current->mm) {leave_mm (smp_processor_id ()); + +/* Synchronize with switch_mm. */ +smp_mb (); + goto out; }if ((end !=TLB_FLUSH_ALL ) && !(vmflag &VM_HUGETLB )) base_pages_to_flush = (end - start) >>PAGE_SHIFT ; +/* +* Both branches below are implicit full barriers (MOV to CR or +* INVLPG) that synchronize with switch_mm. +*/ if (base_pages_to_flush > tlb_single_page_flush_ceiling) { base_pages_to_flush =TLB_FLUSH_ALL ;count_vm_tlb_event (NR_TLB_LOCAL_FLUSH_ALL );
@@ -228,10 +243,18 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start)preempt_disable ();if (current->active_mm == mm) { -if (current->mm) +if (current->mm) { +/* +* Implicit full barrier (INVLPG) that synchronizes +* with switch_mm. +*/ __flush_tlb_one (start); -else + }else {leave_mm (smp_processor_id ()); + +/* Synchronize with switch_mm. */ +smp_mb (); + } }if (cpumask_any_but (mm_cpumask (mm),smp_processor_id ()) < nr_cpu_ids)
drivers/lguest/core.c +51 -23
119 lines not on this page · raw message
tools/testing/selftests/x86/Makefile +4 -2
@@ -4,9 +4,11 @@ include ../lib.mk .PHONY: all all_32 all_64 warn_32bit_failure clean -TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt ptrace_syscall +TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \ - test_FCMOV test_FCOMI test_FISTTP + test_FCMOV test_FCOMI test_FISTTP \ + ldt_gdt \ + vdso_restorer TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
tools/testing/selftests/x86/vdso_restorer.c new file +88 -0
88 lines not on this page · raw message