Skip to content

Commit f41f082

Browse files
amlutoKAGA-KOKO
authored andcommitted
x86/entry/xen: Route #DB correctly on Xen PV
On Xen PV, #DB doesn't use IST. It still needs to be correctly routed depending on whether it came from user or kernel mode. Get rid of DECLARE/DEFINE_IDTENTRY_XEN -- it was too hard to follow the logic. Instead, route #DB and NMI through DECLARE/DEFINE_IDTENTRY_RAW on Xen, and do the right thing for #DB. Also add more warnings to the exc_debug* handlers to make this type of failure more obvious. This fixes various forms of corruption that happen when usermode triggers #DB on Xen PV. Fixes: 4c0dcd8 ("x86/entry: Implement user mode C entry points for #DB and #MCE") Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/4163e733cce0b41658e252c6c6b3464f33fdff17.1593795633.git.luto@kernel.org
1 parent 3c73b81 commit f41f082

File tree

4 files changed

+44
-25
lines changed

4 files changed

+44
-25
lines changed

arch/x86/include/asm/idtentry.h

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -398,18 +398,6 @@ __visible noinstr void func(struct pt_regs *regs, \
398398
#define DEFINE_IDTENTRY_DEBUG DEFINE_IDTENTRY_IST
399399
#define DEFINE_IDTENTRY_DEBUG_USER DEFINE_IDTENTRY_NOIST
400400

401-
/**
402-
* DECLARE_IDTENTRY_XEN - Declare functions for XEN redirect IDT entry points
403-
* @vector: Vector number (ignored for C)
404-
* @func: Function name of the entry point
405-
*
406-
* Used for xennmi and xendebug redirections. No DEFINE as this is all ASM
407-
* indirection magic.
408-
*/
409-
#define DECLARE_IDTENTRY_XEN(vector, func) \
410-
asmlinkage void xen_asm_exc_xen##func(void); \
411-
asmlinkage void asm_exc_xen##func(void)
412-
413401
#else /* !__ASSEMBLY__ */
414402

415403
/*
@@ -469,10 +457,6 @@ __visible noinstr void func(struct pt_regs *regs, \
469457
/* No ASM code emitted for NMI */
470458
#define DECLARE_IDTENTRY_NMI(vector, func)
471459

472-
/* XEN NMI and DB wrapper */
473-
#define DECLARE_IDTENTRY_XEN(vector, func) \
474-
idtentry vector asm_exc_xen##func exc_##func has_error_code=0
475-
476460
/*
477461
* ASM code to emit the common vector entry stubs where each stub is
478462
* packed into 8 bytes.
@@ -570,11 +554,15 @@ DECLARE_IDTENTRY_MCE(X86_TRAP_MC, exc_machine_check);
570554

571555
/* NMI */
572556
DECLARE_IDTENTRY_NMI(X86_TRAP_NMI, exc_nmi);
573-
DECLARE_IDTENTRY_XEN(X86_TRAP_NMI, nmi);
557+
#ifdef CONFIG_XEN_PV
558+
DECLARE_IDTENTRY_RAW(X86_TRAP_NMI, xenpv_exc_nmi);
559+
#endif
574560

575561
/* #DB */
576562
DECLARE_IDTENTRY_DEBUG(X86_TRAP_DB, exc_debug);
577-
DECLARE_IDTENTRY_XEN(X86_TRAP_DB, debug);
563+
#ifdef CONFIG_XEN_PV
564+
DECLARE_IDTENTRY_RAW(X86_TRAP_DB, xenpv_exc_debug);
565+
#endif
578566

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

arch/x86/kernel/traps.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,12 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
865865
instrumentation_begin();
866866
trace_hardirqs_off_finish();
867867

868+
/*
869+
* If something gets miswired and we end up here for a user mode
870+
* #DB, we will malfunction.
871+
*/
872+
WARN_ON_ONCE(user_mode(regs));
873+
868874
/*
869875
* Catch SYSENTER with TF set and clear DR_STEP. If this hit a
870876
* watchpoint at the same time then that will still be handled.
@@ -883,6 +889,12 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
883889
static __always_inline void exc_debug_user(struct pt_regs *regs,
884890
unsigned long dr6)
885891
{
892+
/*
893+
* If something gets miswired and we end up here for a kernel mode
894+
* #DB, we will malfunction.
895+
*/
896+
WARN_ON_ONCE(!user_mode(regs));
897+
886898
idtentry_enter_user(regs);
887899
instrumentation_begin();
888900

arch/x86/xen/enlighten_pv.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,26 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
598598
}
599599

600600
#ifdef CONFIG_X86_64
601+
void noist_exc_debug(struct pt_regs *regs);
602+
603+
DEFINE_IDTENTRY_RAW(xenpv_exc_nmi)
604+
{
605+
/* On Xen PV, NMI doesn't use IST. The C part is the sane as native. */
606+
exc_nmi(regs);
607+
}
608+
609+
DEFINE_IDTENTRY_RAW(xenpv_exc_debug)
610+
{
611+
/*
612+
* There's no IST on Xen PV, but we still need to dispatch
613+
* to the correct handler.
614+
*/
615+
if (user_mode(regs))
616+
noist_exc_debug(regs);
617+
else
618+
exc_debug(regs);
619+
}
620+
601621
struct trap_array_entry {
602622
void (*orig)(void);
603623
void (*xen)(void);
@@ -609,18 +629,18 @@ struct trap_array_entry {
609629
.xen = xen_asm_##func, \
610630
.ist_okay = ist_ok }
611631

612-
#define TRAP_ENTRY_REDIR(func, xenfunc, ist_ok) { \
632+
#define TRAP_ENTRY_REDIR(func, ist_ok) { \
613633
.orig = asm_##func, \
614-
.xen = xen_asm_##xenfunc, \
634+
.xen = xen_asm_xenpv_##func, \
615635
.ist_okay = ist_ok }
616636

617637
static struct trap_array_entry trap_array[] = {
618-
TRAP_ENTRY_REDIR(exc_debug, exc_xendebug, true ),
638+
TRAP_ENTRY_REDIR(exc_debug, true ),
619639
TRAP_ENTRY(exc_double_fault, true ),
620640
#ifdef CONFIG_X86_MCE
621641
TRAP_ENTRY(exc_machine_check, true ),
622642
#endif
623-
TRAP_ENTRY_REDIR(exc_nmi, exc_xennmi, true ),
643+
TRAP_ENTRY_REDIR(exc_nmi, true ),
624644
TRAP_ENTRY(exc_int3, false ),
625645
TRAP_ENTRY(exc_overflow, false ),
626646
#ifdef CONFIG_IA32_EMULATION

arch/x86/xen/xen-asm_64.S

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ _ASM_NOKPROBE(xen_\name)
2929
.endm
3030

3131
xen_pv_trap asm_exc_divide_error
32-
xen_pv_trap asm_exc_debug
33-
xen_pv_trap asm_exc_xendebug
32+
xen_pv_trap asm_xenpv_exc_debug
3433
xen_pv_trap asm_exc_int3
35-
xen_pv_trap asm_exc_xennmi
34+
xen_pv_trap asm_xenpv_exc_nmi
3635
xen_pv_trap asm_exc_overflow
3736
xen_pv_trap asm_exc_bounds
3837
xen_pv_trap asm_exc_invalid_op

0 commit comments

Comments
 (0)