Commit e5b3fc12 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:
 "Various fixes:

   - Fix the PAT performance regression that downgraded write-combining
     device memory regions to uncached.

   - There's been a number of bugs in 32-bit double fault handling -
     hopefully all fixed now.

   - Fix an LDT crash

   - Fix an FPU over-optimization that broke with GCC9 code
     optimizations.

   - Misc cleanups"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm/pat: Fix off-by-one bugs in interval tree search
  x86/ioperm: Save an indentation level in tss_update_io_bitmap()
  x86/fpu: Don't cache access to fpu_fpregs_owner_ctx
  x86/entry/32: Remove unused 'restore_all_notrace' local label
  x86/ptrace: Document FSBASE and GSBASE ABI oddities
  x86/ptrace: Remove set_segment_reg() implementations for current
  x86/traps: die() instead of panicking on a double fault
  x86/doublefault/32: Rewrite the x86_32 #DF handler and unify with 64-bit
  x86/doublefault/32: Move #DF stack and TSS to cpu_entry_area
  x86/doublefault/32: Rename doublefault.c to doublefault_32.c
  x86/traps: Disentangle the 32-bit and 64-bit doublefault code
  lkdtm: Add a DOUBLE_FAULT crash type on x86
  selftests/x86/single_step_syscall: Check SYSENTER directly
  x86/mm/32: Sync only to VMALLOC_END in vmalloc_sync_all()
parents b7fcf31f 91298f1a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ config DEBUG_WX

config DOUBLEFAULT
	default y
	bool "Enable doublefault exception handler" if EXPERT
	bool "Enable doublefault exception handler" if EXPERT && X86_32
	---help---
	  This option allows trapping of rare doublefault exceptions that
	  would otherwise cause a system to silently reboot. Disabling this
+42 −1
Original line number Diff line number Diff line
@@ -1090,7 +1090,6 @@ SYM_FUNC_START(entry_INT80_32)
restore_all:
	TRACE_IRQS_IRET
	SWITCH_TO_ENTRY_STACK
.Lrestore_all_notrace:
	CHECK_AND_APPLY_ESPFIX
.Lrestore_nocheck:
	/* Switch back to user CR3 */
@@ -1537,6 +1536,48 @@ SYM_CODE_START(debug)
	jmp	common_exception
SYM_CODE_END(debug)

#ifdef CONFIG_DOUBLEFAULT
SYM_CODE_START(double_fault)
1:
	/*
	 * This is a task gate handler, not an interrupt gate handler.
	 * The error code is on the stack, but the stack is otherwise
	 * empty.  Interrupts are off.  Our state is sane with the following
	 * exceptions:
	 *
	 *  - CR0.TS is set.  "TS" literally means "task switched".
	 *  - EFLAGS.NT is set because we're a "nested task".
	 *  - The doublefault TSS has back_link set and has been marked busy.
	 *  - TR points to the doublefault TSS and the normal TSS is busy.
	 *  - CR3 is the normal kernel PGD.  This would be delightful, except
	 *    that the CPU didn't bother to save the old CR3 anywhere.  This
	 *    would make it very awkward to return back to the context we came
	 *    from.
	 *
	 * The rest of EFLAGS is sanitized for us, so we don't need to
	 * worry about AC or DF.
	 *
	 * Don't even bother popping the error code.  It's always zero,
	 * and ignoring it makes us a bit more robust against buggy
	 * hypervisor task gate implementations.
	 *
	 * We will manually undo the task switch instead of doing a
	 * task-switching IRET.
	 */

	clts				/* clear CR0.TS */
	pushl	$X86_EFLAGS_FIXED
	popfl				/* clear EFLAGS.NT */

	call	doublefault_shim

	/* We don't support returning, so we have no IRET here. */
1:
	hlt
	jmp 1b
SYM_CODE_END(double_fault)
#endif

/*
 * NMI is doubly nasty.  It can happen on the first instruction of
 * entry_SYSENTER_32 (just like #DB), but it can also interrupt the beginning
+12 −0
Original line number Diff line number Diff line
@@ -65,6 +65,13 @@ enum exception_stack_ordering {

#endif

#ifdef CONFIG_X86_32
struct doublefault_stack {
	unsigned long stack[(PAGE_SIZE - sizeof(struct x86_hw_tss)) / sizeof(unsigned long)];
	struct x86_hw_tss tss;
} __aligned(PAGE_SIZE);
#endif

/*
 * cpu_entry_area is a percpu region that contains things needed by the CPU
 * and early entry/exit code.  Real types aren't used for all fields here
@@ -86,6 +93,11 @@ struct cpu_entry_area {
#endif
	struct entry_stack_page entry_stack_page;

#ifdef CONFIG_X86_32
	char guard_doublefault_stack[PAGE_SIZE];
	struct doublefault_stack doublefault_stack;
#endif

	/*
	 * On x86_64, the TSS is mapped RO.  On x86_32, it's mapped RW because
	 * we need task switches to work, and task switches write to the TSS.
+13 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_DOUBLEFAULT_H
#define _ASM_X86_DOUBLEFAULT_H

#if defined(CONFIG_X86_32) && defined(CONFIG_DOUBLEFAULT)
extern void doublefault_init_cpu_tss(void);
#else
static inline void doublefault_init_cpu_tss(void)
{
}
#endif

#endif /* _ASM_X86_DOUBLEFAULT_H */
+1 −1
Original line number Diff line number Diff line
@@ -509,7 +509,7 @@ static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu)

static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
{
	return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
	return fpu == this_cpu_read(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
}

/*
Loading