diff mbox series

[v2,4/8] arm64: debug: Separate debug hooks based on target exception level

Message ID 20190405124048.3287-5-will.deacon@arm.com (mailing list archive)
State Mainlined, archived
Commit 26a04d84bc5311d7785b229b353f327e866ab61a
Headers show
Series Rework debug exception handling code | expand

Commit Message

Will Deacon April 5, 2019, 12:40 p.m. UTC
Mixing kernel and user debug hooks together is highly error-prone as it
relies on all of the hooks to figure out whether the exception came from
kernel or user, and then to act accordingly.

Make our debug hook code a little more robust by maintaining separate
hook lists for user and kernel, with separate registration functions
to force callers to be explicit about the exception levels that they
care about.

Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/include/asm/brk-imm.h        |  1 +
 arch/arm64/include/asm/debug-monitors.h | 18 ++++---
 arch/arm64/kernel/debug-monitors.c      | 85 +++++++++++++++++++++++----------
 arch/arm64/kernel/kgdb.c                | 22 ++++-----
 arch/arm64/kernel/probes/uprobes.c      |  7 ++-
 arch/arm64/kernel/traps.c               | 20 ++++----
 6 files changed, 95 insertions(+), 58 deletions(-)

Comments

Mark Rutland April 8, 2019, 4:28 p.m. UTC | #1
On Fri, Apr 05, 2019 at 01:40:44PM +0100, Will Deacon wrote:
> Mixing kernel and user debug hooks together is highly error-prone as it
> relies on all of the hooks to figure out whether the exception came from
> kernel or user, and then to act accordingly.
> 
> Make our debug hook code a little more robust by maintaining separate
> hook lists for user and kernel, with separate registration functions
> to force callers to be explicit about the exception levels that they
> care about.
> 
> Signed-off-by: Will Deacon <will.deacon@arm.com>

One minor comment below, but either way this looks good to me:

Reviewed-by: Mark Rutland <mark.rutland@arm.com>

> ---
>  arch/arm64/include/asm/brk-imm.h        |  1 +
>  arch/arm64/include/asm/debug-monitors.h | 18 ++++---
>  arch/arm64/kernel/debug-monitors.c      | 85 +++++++++++++++++++++++----------
>  arch/arm64/kernel/kgdb.c                | 22 ++++-----
>  arch/arm64/kernel/probes/uprobes.c      |  7 ++-
>  arch/arm64/kernel/traps.c               | 20 ++++----
>  6 files changed, 95 insertions(+), 58 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
> index 2945fe6cd863..fec9e1384641 100644
> --- a/arch/arm64/include/asm/brk-imm.h
> +++ b/arch/arm64/include/asm/brk-imm.h
> @@ -23,5 +23,6 @@
>  #define KGDB_COMPILED_DBG_BRK_IMM	0x401
>  #define BUG_BRK_IMM			0x800
>  #define KASAN_BRK_IMM			0x900
> +#define KASAN_BRK_MASK			0x0ff
>  
>  #endif
> diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
> index a44cf5225429..7d37cfa5cc16 100644
> --- a/arch/arm64/include/asm/debug-monitors.h
> +++ b/arch/arm64/include/asm/debug-monitors.h
> @@ -94,18 +94,24 @@ struct step_hook {
>  	int (*fn)(struct pt_regs *regs, unsigned int esr);
>  };
>  
> -void register_step_hook(struct step_hook *hook);
> -void unregister_step_hook(struct step_hook *hook);
> +void register_user_step_hook(struct step_hook *hook);
> +void unregister_user_step_hook(struct step_hook *hook);
> +
> +void register_kernel_step_hook(struct step_hook *hook);
> +void unregister_kernel_step_hook(struct step_hook *hook);
>  
>  struct break_hook {
>  	struct list_head node;
> -	u32 esr_val;
> -	u32 esr_mask;
>  	int (*fn)(struct pt_regs *regs, unsigned int esr);
> +	u16 imm;
> +	u16 mask; /* These bits are ignored when comparing with imm */

It might make sense to call this imm_mask, but that's not a big deal
either way.

Mark.

>  };
>  
> -void register_break_hook(struct break_hook *hook);
> -void unregister_break_hook(struct break_hook *hook);
> +void register_user_break_hook(struct break_hook *hook);
> +void unregister_user_break_hook(struct break_hook *hook);
> +
> +void register_kernel_break_hook(struct break_hook *hook);
> +void unregister_kernel_break_hook(struct break_hook *hook);
>  
>  u8 debug_monitors_arch(void);
>  
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 744229d10ca8..9b3fd7fa5b43 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -163,25 +163,46 @@ static void clear_regs_spsr_ss(struct pt_regs *regs)
>  }
>  NOKPROBE_SYMBOL(clear_regs_spsr_ss);
>  
> -/* EL1 Single Step Handler hooks */
> -static LIST_HEAD(step_hook);
> -static DEFINE_SPINLOCK(step_hook_lock);
> +static DEFINE_SPINLOCK(debug_hook_lock);
> +static LIST_HEAD(user_step_hook);
> +static LIST_HEAD(kernel_step_hook);
>  
> -void register_step_hook(struct step_hook *hook)
> +static void register_debug_hook(struct list_head *node, struct list_head *list)
>  {
> -	spin_lock(&step_hook_lock);
> -	list_add_rcu(&hook->node, &step_hook);
> -	spin_unlock(&step_hook_lock);
> +	spin_lock(&debug_hook_lock);
> +	list_add_rcu(node, list);
> +	spin_unlock(&debug_hook_lock);
> +
>  }
>  
> -void unregister_step_hook(struct step_hook *hook)
> +static void unregister_debug_hook(struct list_head *node)
>  {
> -	spin_lock(&step_hook_lock);
> -	list_del_rcu(&hook->node);
> -	spin_unlock(&step_hook_lock);
> +	spin_lock(&debug_hook_lock);
> +	list_del_rcu(node);
> +	spin_unlock(&debug_hook_lock);
>  	synchronize_rcu();
>  }
>  
> +void register_user_step_hook(struct step_hook *hook)
> +{
> +	register_debug_hook(&hook->node, &user_step_hook);
> +}
> +
> +void unregister_user_step_hook(struct step_hook *hook)
> +{
> +	unregister_debug_hook(&hook->node);
> +}
> +
> +void register_kernel_step_hook(struct step_hook *hook)
> +{
> +	register_debug_hook(&hook->node, &kernel_step_hook);
> +}
> +
> +void unregister_kernel_step_hook(struct step_hook *hook)
> +{
> +	unregister_debug_hook(&hook->node);
> +}
> +
>  /*
>   * Call registered single step handlers
>   * There is no Syndrome info to check for determining the handler.
> @@ -191,11 +212,14 @@ void unregister_step_hook(struct step_hook *hook)
>  static int call_step_hook(struct pt_regs *regs, unsigned int esr)
>  {
>  	struct step_hook *hook;
> +	struct list_head *list;
>  	int retval = DBG_HOOK_ERROR;
>  
> +	list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
> +
>  	rcu_read_lock();
>  
> -	list_for_each_entry_rcu(hook, &step_hook, node)	{
> +	list_for_each_entry_rcu(hook, list, node)	{
>  		retval = hook->fn(regs, esr);
>  		if (retval == DBG_HOOK_HANDLED)
>  			break;
> @@ -264,33 +288,44 @@ static int single_step_handler(unsigned long unused, unsigned int esr,
>  }
>  NOKPROBE_SYMBOL(single_step_handler);
>  
> -static LIST_HEAD(break_hook);
> -static DEFINE_SPINLOCK(break_hook_lock);
> +static LIST_HEAD(user_break_hook);
> +static LIST_HEAD(kernel_break_hook);
>  
> -void register_break_hook(struct break_hook *hook)
> +void register_user_break_hook(struct break_hook *hook)
>  {
> -	spin_lock(&break_hook_lock);
> -	list_add_rcu(&hook->node, &break_hook);
> -	spin_unlock(&break_hook_lock);
> +	register_debug_hook(&hook->node, &user_break_hook);
>  }
>  
> -void unregister_break_hook(struct break_hook *hook)
> +void unregister_user_break_hook(struct break_hook *hook)
>  {
> -	spin_lock(&break_hook_lock);
> -	list_del_rcu(&hook->node);
> -	spin_unlock(&break_hook_lock);
> -	synchronize_rcu();
> +	unregister_debug_hook(&hook->node);
> +}
> +
> +void register_kernel_break_hook(struct break_hook *hook)
> +{
> +	register_debug_hook(&hook->node, &kernel_break_hook);
> +}
> +
> +void unregister_kernel_break_hook(struct break_hook *hook)
> +{
> +	unregister_debug_hook(&hook->node);
>  }
>  
>  static int call_break_hook(struct pt_regs *regs, unsigned int esr)
>  {
>  	struct break_hook *hook;
> +	struct list_head *list;
>  	int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL;
>  
> +	list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
> +
>  	rcu_read_lock();
> -	list_for_each_entry_rcu(hook, &break_hook, node)
> -		if ((esr & hook->esr_mask) == hook->esr_val)
> +	list_for_each_entry_rcu(hook, list, node) {
> +		unsigned int comment = esr & BRK64_ESR_MASK;
> +
> +		if ((comment & ~hook->mask) == hook->imm)
>  			fn = hook->fn;
> +	}
>  	rcu_read_unlock();
>  
>  	return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
> diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
> index 691854b77c7f..4c01f299aeb2 100644
> --- a/arch/arm64/kernel/kgdb.c
> +++ b/arch/arm64/kernel/kgdb.c
> @@ -275,15 +275,13 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
>  NOKPROBE_SYMBOL(kgdb_step_brk_fn);
>  
>  static struct break_hook kgdb_brkpt_hook = {
> -	.esr_mask	= 0xffffffff,
> -	.esr_val	= (u32)ESR_ELx_VAL_BRK64(KGDB_DYN_DBG_BRK_IMM),
> -	.fn		= kgdb_brk_fn
> +	.fn		= kgdb_brk_fn,
> +	.imm		= KGDB_DYN_DBG_BRK_IMM,
>  };
>  
>  static struct break_hook kgdb_compiled_brkpt_hook = {
> -	.esr_mask	= 0xffffffff,
> -	.esr_val	= (u32)ESR_ELx_VAL_BRK64(KGDB_COMPILED_DBG_BRK_IMM),
> -	.fn		= kgdb_compiled_brk_fn
> +	.fn		= kgdb_compiled_brk_fn,
> +	.imm		= KGDB_COMPILED_DBG_BRK_IMM,
>  };
>  
>  static struct step_hook kgdb_step_hook = {
> @@ -332,9 +330,9 @@ int kgdb_arch_init(void)
>  	if (ret != 0)
>  		return ret;
>  
> -	register_break_hook(&kgdb_brkpt_hook);
> -	register_break_hook(&kgdb_compiled_brkpt_hook);
> -	register_step_hook(&kgdb_step_hook);
> +	register_kernel_break_hook(&kgdb_brkpt_hook);
> +	register_kernel_break_hook(&kgdb_compiled_brkpt_hook);
> +	register_kernel_step_hook(&kgdb_step_hook);
>  	return 0;
>  }
>  
> @@ -345,9 +343,9 @@ int kgdb_arch_init(void)
>   */
>  void kgdb_arch_exit(void)
>  {
> -	unregister_break_hook(&kgdb_brkpt_hook);
> -	unregister_break_hook(&kgdb_compiled_brkpt_hook);
> -	unregister_step_hook(&kgdb_step_hook);
> +	unregister_kernel_break_hook(&kgdb_brkpt_hook);
> +	unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook);
> +	unregister_kernel_step_hook(&kgdb_step_hook);
>  	unregister_die_notifier(&kgdb_notifier);
>  }
>  
> diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
> index 636ca0119c0e..7d6ea88796a6 100644
> --- a/arch/arm64/kernel/probes/uprobes.c
> +++ b/arch/arm64/kernel/probes/uprobes.c
> @@ -195,8 +195,7 @@ static int uprobe_single_step_handler(struct pt_regs *regs,
>  
>  /* uprobe breakpoint handler hook */
>  static struct break_hook uprobes_break_hook = {
> -	.esr_mask = BRK64_ESR_MASK,
> -	.esr_val = BRK64_ESR_UPROBES,
> +	.imm = BRK64_ESR_UPROBES,
>  	.fn = uprobe_breakpoint_handler,
>  };
>  
> @@ -207,8 +206,8 @@ static struct step_hook uprobes_step_hook = {
>  
>  static int __init arch_init_uprobes(void)
>  {
> -	register_break_hook(&uprobes_break_hook);
> -	register_step_hook(&uprobes_step_hook);
> +	register_user_break_hook(&uprobes_break_hook);
> +	register_user_step_hook(&uprobes_step_hook);
>  
>  	return 0;
>  }
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 8ad119c3f665..85fdc3d7c556 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -969,9 +969,8 @@ static int bug_handler(struct pt_regs *regs, unsigned int esr)
>  }
>  
>  static struct break_hook bug_break_hook = {
> -	.esr_val = 0xf2000000 | BUG_BRK_IMM,
> -	.esr_mask = 0xffffffff,
>  	.fn = bug_handler,
> +	.imm = BUG_BRK_IMM,
>  };
>  
>  #ifdef CONFIG_KASAN_SW_TAGS
> @@ -1016,13 +1015,10 @@ static int kasan_handler(struct pt_regs *regs, unsigned int esr)
>  	return DBG_HOOK_HANDLED;
>  }
>  
> -#define KASAN_ESR_VAL (0xf2000000 | KASAN_BRK_IMM)
> -#define KASAN_ESR_MASK 0xffffff00
> -
>  static struct break_hook kasan_break_hook = {
> -	.esr_val = KASAN_ESR_VAL,
> -	.esr_mask = KASAN_ESR_MASK,
> -	.fn = kasan_handler,
> +	.fn	= kasan_handler,
> +	.imm	= KASAN_BRK_IMM,
> +	.mask	= KASAN_BRK_MASK,
>  };
>  #endif
>  
> @@ -1034,7 +1030,9 @@ int __init early_brk64(unsigned long addr, unsigned int esr,
>  		struct pt_regs *regs)
>  {
>  #ifdef CONFIG_KASAN_SW_TAGS
> -	if ((esr & KASAN_ESR_MASK) == KASAN_ESR_VAL)
> +	unsigned int comment = esr & BRK64_ESR_MASK;
> +
> +	if ((comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
>  		return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
>  #endif
>  	return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
> @@ -1043,8 +1041,8 @@ int __init early_brk64(unsigned long addr, unsigned int esr,
>  /* This registration must happen early, before debug_traps_init(). */
>  void __init trap_init(void)
>  {
> -	register_break_hook(&bug_break_hook);
> +	register_kernel_break_hook(&bug_break_hook);
>  #ifdef CONFIG_KASAN_SW_TAGS
> -	register_break_hook(&kasan_break_hook);
> +	register_kernel_break_hook(&kasan_break_hook);
>  #endif
>  }
> -- 
> 2.11.0
>
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
index 2945fe6cd863..fec9e1384641 100644
--- a/arch/arm64/include/asm/brk-imm.h
+++ b/arch/arm64/include/asm/brk-imm.h
@@ -23,5 +23,6 @@ 
 #define KGDB_COMPILED_DBG_BRK_IMM	0x401
 #define BUG_BRK_IMM			0x800
 #define KASAN_BRK_IMM			0x900
+#define KASAN_BRK_MASK			0x0ff
 
 #endif
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
index a44cf5225429..7d37cfa5cc16 100644
--- a/arch/arm64/include/asm/debug-monitors.h
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -94,18 +94,24 @@  struct step_hook {
 	int (*fn)(struct pt_regs *regs, unsigned int esr);
 };
 
-void register_step_hook(struct step_hook *hook);
-void unregister_step_hook(struct step_hook *hook);
+void register_user_step_hook(struct step_hook *hook);
+void unregister_user_step_hook(struct step_hook *hook);
+
+void register_kernel_step_hook(struct step_hook *hook);
+void unregister_kernel_step_hook(struct step_hook *hook);
 
 struct break_hook {
 	struct list_head node;
-	u32 esr_val;
-	u32 esr_mask;
 	int (*fn)(struct pt_regs *regs, unsigned int esr);
+	u16 imm;
+	u16 mask; /* These bits are ignored when comparing with imm */
 };
 
-void register_break_hook(struct break_hook *hook);
-void unregister_break_hook(struct break_hook *hook);
+void register_user_break_hook(struct break_hook *hook);
+void unregister_user_break_hook(struct break_hook *hook);
+
+void register_kernel_break_hook(struct break_hook *hook);
+void unregister_kernel_break_hook(struct break_hook *hook);
 
 u8 debug_monitors_arch(void);
 
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 744229d10ca8..9b3fd7fa5b43 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -163,25 +163,46 @@  static void clear_regs_spsr_ss(struct pt_regs *regs)
 }
 NOKPROBE_SYMBOL(clear_regs_spsr_ss);
 
-/* EL1 Single Step Handler hooks */
-static LIST_HEAD(step_hook);
-static DEFINE_SPINLOCK(step_hook_lock);
+static DEFINE_SPINLOCK(debug_hook_lock);
+static LIST_HEAD(user_step_hook);
+static LIST_HEAD(kernel_step_hook);
 
-void register_step_hook(struct step_hook *hook)
+static void register_debug_hook(struct list_head *node, struct list_head *list)
 {
-	spin_lock(&step_hook_lock);
-	list_add_rcu(&hook->node, &step_hook);
-	spin_unlock(&step_hook_lock);
+	spin_lock(&debug_hook_lock);
+	list_add_rcu(node, list);
+	spin_unlock(&debug_hook_lock);
+
 }
 
-void unregister_step_hook(struct step_hook *hook)
+static void unregister_debug_hook(struct list_head *node)
 {
-	spin_lock(&step_hook_lock);
-	list_del_rcu(&hook->node);
-	spin_unlock(&step_hook_lock);
+	spin_lock(&debug_hook_lock);
+	list_del_rcu(node);
+	spin_unlock(&debug_hook_lock);
 	synchronize_rcu();
 }
 
+void register_user_step_hook(struct step_hook *hook)
+{
+	register_debug_hook(&hook->node, &user_step_hook);
+}
+
+void unregister_user_step_hook(struct step_hook *hook)
+{
+	unregister_debug_hook(&hook->node);
+}
+
+void register_kernel_step_hook(struct step_hook *hook)
+{
+	register_debug_hook(&hook->node, &kernel_step_hook);
+}
+
+void unregister_kernel_step_hook(struct step_hook *hook)
+{
+	unregister_debug_hook(&hook->node);
+}
+
 /*
  * Call registered single step handlers
  * There is no Syndrome info to check for determining the handler.
@@ -191,11 +212,14 @@  void unregister_step_hook(struct step_hook *hook)
 static int call_step_hook(struct pt_regs *regs, unsigned int esr)
 {
 	struct step_hook *hook;
+	struct list_head *list;
 	int retval = DBG_HOOK_ERROR;
 
+	list = user_mode(regs) ? &user_step_hook : &kernel_step_hook;
+
 	rcu_read_lock();
 
-	list_for_each_entry_rcu(hook, &step_hook, node)	{
+	list_for_each_entry_rcu(hook, list, node)	{
 		retval = hook->fn(regs, esr);
 		if (retval == DBG_HOOK_HANDLED)
 			break;
@@ -264,33 +288,44 @@  static int single_step_handler(unsigned long unused, unsigned int esr,
 }
 NOKPROBE_SYMBOL(single_step_handler);
 
-static LIST_HEAD(break_hook);
-static DEFINE_SPINLOCK(break_hook_lock);
+static LIST_HEAD(user_break_hook);
+static LIST_HEAD(kernel_break_hook);
 
-void register_break_hook(struct break_hook *hook)
+void register_user_break_hook(struct break_hook *hook)
 {
-	spin_lock(&break_hook_lock);
-	list_add_rcu(&hook->node, &break_hook);
-	spin_unlock(&break_hook_lock);
+	register_debug_hook(&hook->node, &user_break_hook);
 }
 
-void unregister_break_hook(struct break_hook *hook)
+void unregister_user_break_hook(struct break_hook *hook)
 {
-	spin_lock(&break_hook_lock);
-	list_del_rcu(&hook->node);
-	spin_unlock(&break_hook_lock);
-	synchronize_rcu();
+	unregister_debug_hook(&hook->node);
+}
+
+void register_kernel_break_hook(struct break_hook *hook)
+{
+	register_debug_hook(&hook->node, &kernel_break_hook);
+}
+
+void unregister_kernel_break_hook(struct break_hook *hook)
+{
+	unregister_debug_hook(&hook->node);
 }
 
 static int call_break_hook(struct pt_regs *regs, unsigned int esr)
 {
 	struct break_hook *hook;
+	struct list_head *list;
 	int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL;
 
+	list = user_mode(regs) ? &user_break_hook : &kernel_break_hook;
+
 	rcu_read_lock();
-	list_for_each_entry_rcu(hook, &break_hook, node)
-		if ((esr & hook->esr_mask) == hook->esr_val)
+	list_for_each_entry_rcu(hook, list, node) {
+		unsigned int comment = esr & BRK64_ESR_MASK;
+
+		if ((comment & ~hook->mask) == hook->imm)
 			fn = hook->fn;
+	}
 	rcu_read_unlock();
 
 	return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 691854b77c7f..4c01f299aeb2 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -275,15 +275,13 @@  static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
 NOKPROBE_SYMBOL(kgdb_step_brk_fn);
 
 static struct break_hook kgdb_brkpt_hook = {
-	.esr_mask	= 0xffffffff,
-	.esr_val	= (u32)ESR_ELx_VAL_BRK64(KGDB_DYN_DBG_BRK_IMM),
-	.fn		= kgdb_brk_fn
+	.fn		= kgdb_brk_fn,
+	.imm		= KGDB_DYN_DBG_BRK_IMM,
 };
 
 static struct break_hook kgdb_compiled_brkpt_hook = {
-	.esr_mask	= 0xffffffff,
-	.esr_val	= (u32)ESR_ELx_VAL_BRK64(KGDB_COMPILED_DBG_BRK_IMM),
-	.fn		= kgdb_compiled_brk_fn
+	.fn		= kgdb_compiled_brk_fn,
+	.imm		= KGDB_COMPILED_DBG_BRK_IMM,
 };
 
 static struct step_hook kgdb_step_hook = {
@@ -332,9 +330,9 @@  int kgdb_arch_init(void)
 	if (ret != 0)
 		return ret;
 
-	register_break_hook(&kgdb_brkpt_hook);
-	register_break_hook(&kgdb_compiled_brkpt_hook);
-	register_step_hook(&kgdb_step_hook);
+	register_kernel_break_hook(&kgdb_brkpt_hook);
+	register_kernel_break_hook(&kgdb_compiled_brkpt_hook);
+	register_kernel_step_hook(&kgdb_step_hook);
 	return 0;
 }
 
@@ -345,9 +343,9 @@  int kgdb_arch_init(void)
  */
 void kgdb_arch_exit(void)
 {
-	unregister_break_hook(&kgdb_brkpt_hook);
-	unregister_break_hook(&kgdb_compiled_brkpt_hook);
-	unregister_step_hook(&kgdb_step_hook);
+	unregister_kernel_break_hook(&kgdb_brkpt_hook);
+	unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook);
+	unregister_kernel_step_hook(&kgdb_step_hook);
 	unregister_die_notifier(&kgdb_notifier);
 }
 
diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
index 636ca0119c0e..7d6ea88796a6 100644
--- a/arch/arm64/kernel/probes/uprobes.c
+++ b/arch/arm64/kernel/probes/uprobes.c
@@ -195,8 +195,7 @@  static int uprobe_single_step_handler(struct pt_regs *regs,
 
 /* uprobe breakpoint handler hook */
 static struct break_hook uprobes_break_hook = {
-	.esr_mask = BRK64_ESR_MASK,
-	.esr_val = BRK64_ESR_UPROBES,
+	.imm = BRK64_ESR_UPROBES,
 	.fn = uprobe_breakpoint_handler,
 };
 
@@ -207,8 +206,8 @@  static struct step_hook uprobes_step_hook = {
 
 static int __init arch_init_uprobes(void)
 {
-	register_break_hook(&uprobes_break_hook);
-	register_step_hook(&uprobes_step_hook);
+	register_user_break_hook(&uprobes_break_hook);
+	register_user_step_hook(&uprobes_step_hook);
 
 	return 0;
 }
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8ad119c3f665..85fdc3d7c556 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -969,9 +969,8 @@  static int bug_handler(struct pt_regs *regs, unsigned int esr)
 }
 
 static struct break_hook bug_break_hook = {
-	.esr_val = 0xf2000000 | BUG_BRK_IMM,
-	.esr_mask = 0xffffffff,
 	.fn = bug_handler,
+	.imm = BUG_BRK_IMM,
 };
 
 #ifdef CONFIG_KASAN_SW_TAGS
@@ -1016,13 +1015,10 @@  static int kasan_handler(struct pt_regs *regs, unsigned int esr)
 	return DBG_HOOK_HANDLED;
 }
 
-#define KASAN_ESR_VAL (0xf2000000 | KASAN_BRK_IMM)
-#define KASAN_ESR_MASK 0xffffff00
-
 static struct break_hook kasan_break_hook = {
-	.esr_val = KASAN_ESR_VAL,
-	.esr_mask = KASAN_ESR_MASK,
-	.fn = kasan_handler,
+	.fn	= kasan_handler,
+	.imm	= KASAN_BRK_IMM,
+	.mask	= KASAN_BRK_MASK,
 };
 #endif
 
@@ -1034,7 +1030,9 @@  int __init early_brk64(unsigned long addr, unsigned int esr,
 		struct pt_regs *regs)
 {
 #ifdef CONFIG_KASAN_SW_TAGS
-	if ((esr & KASAN_ESR_MASK) == KASAN_ESR_VAL)
+	unsigned int comment = esr & BRK64_ESR_MASK;
+
+	if ((comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
 		return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
 #endif
 	return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
@@ -1043,8 +1041,8 @@  int __init early_brk64(unsigned long addr, unsigned int esr,
 /* This registration must happen early, before debug_traps_init(). */
 void __init trap_init(void)
 {
-	register_break_hook(&bug_break_hook);
+	register_kernel_break_hook(&bug_break_hook);
 #ifdef CONFIG_KASAN_SW_TAGS
-	register_break_hook(&kasan_break_hook);
+	register_kernel_break_hook(&kasan_break_hook);
 #endif
 }