@@ -729,20 +729,9 @@ static bool is_sysenter_singlestep(struct pt_regs *regs)
729
729
#endif
730
730
}
731
731
732
- static __always_inline void debug_enter ( unsigned long * dr6 , unsigned long * dr7 )
732
+ static __always_inline unsigned long debug_read_clear_dr6 ( void )
733
733
{
734
- /*
735
- * Disable breakpoints during exception handling; recursive exceptions
736
- * are exceedingly 'fun'.
737
- *
738
- * Since this function is NOKPROBE, and that also applies to
739
- * HW_BREAKPOINT_X, we can't hit a breakpoint before this (XXX except a
740
- * HW_BREAKPOINT_W on our stack)
741
- *
742
- * Entry text is excluded for HW_BP_X and cpu_entry_area, which
743
- * includes the entry stack is excluded for everything.
744
- */
745
- * dr7 = local_db_save ();
734
+ unsigned long dr6 ;
746
735
747
736
/*
748
737
* The Intel SDM says:
@@ -755,15 +744,12 @@ static __always_inline void debug_enter(unsigned long *dr6, unsigned long *dr7)
755
744
*
756
745
* Keep it simple: clear DR6 immediately.
757
746
*/
758
- get_debugreg (* dr6 , 6 );
747
+ get_debugreg (dr6 , 6 );
759
748
set_debugreg (0 , 6 );
760
749
/* Filter out all the reserved bits which are preset to 1 */
761
- * dr6 &= ~DR6_RESERVED ;
762
- }
750
+ dr6 &= ~DR6_RESERVED ;
763
751
764
- static __always_inline void debug_exit (unsigned long dr7 )
765
- {
766
- local_db_restore (dr7 );
752
+ return dr6 ;
767
753
}
768
754
769
755
/*
@@ -863,6 +849,18 @@ static void handle_debug(struct pt_regs *regs, unsigned long dr6, bool user)
863
849
static __always_inline void exc_debug_kernel (struct pt_regs * regs ,
864
850
unsigned long dr6 )
865
851
{
852
+ /*
853
+ * Disable breakpoints during exception handling; recursive exceptions
854
+ * are exceedingly 'fun'.
855
+ *
856
+ * Since this function is NOKPROBE, and that also applies to
857
+ * HW_BREAKPOINT_X, we can't hit a breakpoint before this (XXX except a
858
+ * HW_BREAKPOINT_W on our stack)
859
+ *
860
+ * Entry text is excluded for HW_BP_X and cpu_entry_area, which
861
+ * includes the entry stack is excluded for everything.
862
+ */
863
+ unsigned long dr7 = local_db_save ();
866
864
bool irq_state = idtentry_enter_nmi (regs );
867
865
instrumentation_begin ();
868
866
@@ -883,6 +881,8 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,
883
881
884
882
instrumentation_end ();
885
883
idtentry_exit_nmi (regs , irq_state );
884
+
885
+ local_db_restore (dr7 );
886
886
}
887
887
888
888
static __always_inline void exc_debug_user (struct pt_regs * regs ,
@@ -894,6 +894,15 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
894
894
*/
895
895
WARN_ON_ONCE (!user_mode (regs ));
896
896
897
+ /*
898
+ * NB: We can't easily clear DR7 here because
899
+ * idtentry_exit_to_usermode() can invoke ptrace, schedule, access
900
+ * user memory, etc. This means that a recursive #DB is possible. If
901
+ * this happens, that #DB will hit exc_debug_kernel() and clear DR7.
902
+ * Since we're not on the IST stack right now, everything will be
903
+ * fine.
904
+ */
905
+
897
906
irqentry_enter_from_user_mode (regs );
898
907
instrumentation_begin ();
899
908
@@ -907,36 +916,24 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
907
916
/* IST stack entry */
908
917
DEFINE_IDTENTRY_DEBUG (exc_debug )
909
918
{
910
- unsigned long dr6 , dr7 ;
911
-
912
- debug_enter (& dr6 , & dr7 );
913
- exc_debug_kernel (regs , dr6 );
914
- debug_exit (dr7 );
919
+ exc_debug_kernel (regs , debug_read_clear_dr6 ());
915
920
}
916
921
917
922
/* User entry, runs on regular task stack */
918
923
DEFINE_IDTENTRY_DEBUG_USER (exc_debug )
919
924
{
920
- unsigned long dr6 , dr7 ;
921
-
922
- debug_enter (& dr6 , & dr7 );
923
- exc_debug_user (regs , dr6 );
924
- debug_exit (dr7 );
925
+ exc_debug_user (regs , debug_read_clear_dr6 ());
925
926
}
926
927
#else
927
928
/* 32 bit does not have separate entry points. */
928
929
DEFINE_IDTENTRY_RAW (exc_debug )
929
930
{
930
- unsigned long dr6 , dr7 ;
931
-
932
- debug_enter (& dr6 , & dr7 );
931
+ unsigned long dr6 = debug_read_clear_dr6 ();
933
932
934
933
if (user_mode (regs ))
935
934
exc_debug_user (regs , dr6 );
936
935
else
937
936
exc_debug_kernel (regs , dr6 );
938
-
939
- debug_exit (dr7 );
940
937
}
941
938
#endif
942
939
0 commit comments