Skip to contentSkip to conversation

x86 fixes

GIT PULL Ingo Molnar 1 participant 1 message Jan 14, 2016

Subsystems (5)
x86 Kselftest x86 MM x86 entry code +1 more subsystems
lore
Share & tools
lore
#0 lore raw

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
index 8602f06c759f..1a50e09c945b 100644
@@ -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
index 4fa687a47a62..6b8d6e8cd449 100644
@@ -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
index eadcdd5bb946..0fd440df63f1 100644
@@ -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
index 3a6c89b70307..af30fdeb140d 100644
@@ -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
index 3bbc07a57a31..73d0c9b92087 100644
@@ -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
index 379cd3658799..bfd9b2a35a0b 100644
@@ -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
index e678ddeed030..a07956a08936 100644
@@ -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
index 40f100285984..d425cda5ae6d 100644
@@ -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
index d64889aa2d46..ab0adc0fa5db 100644
@@ -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
index ec081fe0ce2c..8829482d69ec 100644
@@ -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
index 6000ad7f560c..fc6a4c8f6e2a 100644
@@ -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
index 8ddb5d0d66fb..8f4cc3dfac32 100644
@@ -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
index eabcff411984..d0c473f65850 100644
@@ -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