On Mon, Dec 19, 2022 at 10:36:44PM -0800, Xin Li wrote: > +static __always_inline void debug_kernel_common(struct pt_regs *regs, > + unsigned long dr6) > { > - /* > - * Disable breakpoints during exception handling; recursive exceptions > - * are exceedingly 'fun'. > - * > - * Since this function is NOKPROBE, and that also applies to > - * HW_BREAKPOINT_X, we can't hit a breakpoint before this (XXX except a > - * HW_BREAKPOINT_W on our stack) > - * > - * Entry text is excluded for HW_BP_X and cpu_entry_area, which > - * includes the entry stack is excluded for everything. > - */ > - unsigned long dr7 = local_db_save(); > - irqentry_state_t irq_state = irqentry_nmi_enter(regs); > instrumentation_begin(); > > /* > @@ -1062,7 +1050,8 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs, > * Catch SYSENTER with TF set and clear DR_STEP. If this hit a > * watchpoint at the same time then that will still be handled. > */ > - if ((dr6 & DR_STEP) && is_sysenter_singlestep(regs)) > + if (!cpu_feature_enabled(X86_FEATURE_FRED) && > + (dr6 & DR_STEP) && is_sysenter_singlestep(regs)) > dr6 &= ~DR_STEP; > > /* > @@ -1089,8 +1078,28 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs, > regs->flags &= ~X86_EFLAGS_TF; > out: > instrumentation_end(); > - irqentry_nmi_exit(regs, irq_state); > +} Why doesn't the FRED handler get to to use irqentry_nmi_{enter,exit}() ? > @@ -1179,6 +1188,24 @@ DEFINE_IDTENTRY_DEBUG_USER(exc_debug) > { > exc_debug_user(regs, debug_read_clear_dr6()); > } > + > +# ifdef CONFIG_X86_FRED > +DEFINE_FRED_HANDLER(fred_exc_debug) > +{ > + /* > + * The FRED debug information saved onto stack differs from > + * DR6 in both stickiness and polarity; it is exactly what > + * debug_read_clear_dr6() returns. > + */ > + unsigned long dr6 = fred_event_data(regs); > + > + if (user_mode(regs)) > + exc_debug_user(regs, dr6); > + else > + debug_kernel_common(regs, dr6); > +} > +# endif /* CONFIG_X86_FRED */