Commit c29c775a authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

x86/entry: Convert double fault exception to IDTENTRY_DF



Convert #DF to IDTENTRY_DF
  - Implement the C entry point with DEFINE_IDTENTRY_DF
  - Emit the ASM stub with DECLARE_IDTENTRY_DF on 64bit
  - Remove the ASM idtentry in 64bit
  - Adjust the 32bit shim code
  - Fixup the XEN/PV code
  - Remove the old prototypes

No functional change.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarAlexandre Chartre <alexandre.chartre@oracle.com>
Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
Acked-by: default avatarAndy Lutomirski <luto@kernel.org>
Link: https://lkml.kernel.org/r/20200505135315.583415264@linutronix.de

parent 6a8dfa8e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1488,7 +1488,7 @@ ret_to_user:
	jmp	restore_all_switch_stack
SYM_CODE_END(handle_exception)

SYM_CODE_START(double_fault)
SYM_CODE_START(asm_exc_double_fault)
1:
	/*
	 * This is a task gate handler, not an interrupt gate handler.
@@ -1526,7 +1526,7 @@ SYM_CODE_START(double_fault)
1:
	hlt
	jmp 1b
SYM_CODE_END(double_fault)
SYM_CODE_END(asm_exc_double_fault)

/*
 * NMI is doubly nasty.  It can happen on the first instruction of
+1 −9
Original line number Diff line number Diff line
@@ -680,15 +680,9 @@ SYM_CODE_START(\asmsym)
	call	paranoid_entry
	UNWIND_HINT_REGS

	/* Read CR2 early */
	GET_CR2_INTO(%r12);

	TRACE_IRQS_OFF

	movq	%rsp, %rdi		/* pt_regs pointer into first argument */
	movq	ORIG_RAX(%rsp), %rsi	/* get error code into 2nd argument*/
	movq	$-1, ORIG_RAX(%rsp)	/* no syscall to restart */
	movq	%r12, %rdx		/* Move CR2 into 3rd argument */
	call	\cfunc

	jmp	paranoid_exit
@@ -918,7 +912,7 @@ SYM_INNER_LABEL(native_irq_return_iret, SYM_L_GLOBAL)
	/*
	 * This may fault.  Non-paranoid faults on return to userspace are
	 * handled by fixup_bad_iret.  These include #SS, #GP, and #NP.
	 * Double-faults due to espfix64 are handled in do_double_fault.
	 * Double-faults due to espfix64 are handled in exc_double_fault.
	 * Other faults here are fatal.
	 */
	iretq
@@ -1073,8 +1067,6 @@ apicinterrupt IRQ_WORK_VECTOR irq_work_interrupt smp_irq_work_interrupt

idtentry	X86_TRAP_PF		page_fault		do_page_fault			has_error_code=1

idtentry_df	X86_TRAP_DF		double_fault		do_double_fault

#ifdef CONFIG_XEN_PV
idtentry	512 /* dummy */		hypervisor_callback	xen_do_hypervisor_callback	has_error_code=0
#endif
+3 −0
Original line number Diff line number Diff line
@@ -368,4 +368,7 @@ DECLARE_IDTENTRY_XEN(X86_TRAP_NMI, nmi);
DECLARE_IDTENTRY_DEBUG(X86_TRAP_DB,	exc_debug);
DECLARE_IDTENTRY_XEN(X86_TRAP_DB,	debug);

/* #DF */
DECLARE_IDTENTRY_DF(X86_TRAP_DF,	exc_double_fault);

#endif
+0 −5
Original line number Diff line number Diff line
@@ -11,18 +11,13 @@

#define dotraplinkage __visible

#ifdef CONFIG_X86_64
asmlinkage void double_fault(void);
#endif
asmlinkage void page_fault(void);
asmlinkage void async_page_fault(void);

#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
asmlinkage void xen_double_fault(void);
asmlinkage void xen_page_fault(void);
#endif

dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsigned long cr2);
dotraplinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address);

#ifdef CONFIG_X86_64
+4 −6
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@
#include <asm/desc.h>
#include <asm/traps.h>

extern void double_fault(void);
#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM)

#define TSS(x) this_cpu_read(cpu_tss_rw.x86_tss.x)
@@ -21,7 +20,7 @@ static void set_df_gdt_entry(unsigned int cpu);
 * Called by double_fault with CR0.TS and EFLAGS.NT cleared.  The CPU thinks
 * we're running the doublefault task.  Cannot return.
 */
asmlinkage notrace void __noreturn doublefault_shim(void)
asmlinkage noinstr void __noreturn doublefault_shim(void)
{
	unsigned long cr2;
	struct pt_regs regs;
@@ -40,7 +39,7 @@ asmlinkage notrace void __noreturn doublefault_shim(void)
	 * Fill in pt_regs.  A downside of doing this in C is that the unwinder
	 * won't see it (no ENCODE_FRAME_POINTER), so a nested stack dump
	 * won't successfully unwind to the source of the double fault.
	 * The main dump from do_double_fault() is fine, though, since it
	 * The main dump from exc_double_fault() is fine, though, since it
	 * uses these regs directly.
	 *
	 * If anyone ever cares, this could be moved to asm.
@@ -70,7 +69,7 @@ asmlinkage notrace void __noreturn doublefault_shim(void)
	regs.cx		= TSS(cx);
	regs.bx		= TSS(bx);

	do_double_fault(&regs, 0, cr2);
	exc_double_fault(&regs, 0, cr2);

	/*
	 * x86_32 does not save the original CR3 anywhere on a task switch.
@@ -84,7 +83,6 @@ asmlinkage notrace void __noreturn doublefault_shim(void)
	 */
	panic("cannot return from double fault\n");
}
NOKPROBE_SYMBOL(doublefault_shim);

DEFINE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack) = {
	.tss = {
@@ -95,7 +93,7 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack) = {
		.ldt		= 0,
	.io_bitmap_base	= IO_BITMAP_OFFSET_INVALID,

		.ip		= (unsigned long) double_fault,
		.ip		= (unsigned long) asm_exc_double_fault,
		.flags		= X86_EFLAGS_FIXED,
		.es		= __USER_DS,
		.cs		= __KERNEL_CS,
Loading