]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
ARM: Fix kgdb breakpoint for Thumb2
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Wed, 16 Feb 2022 15:37:38 +0000 (15:37 +0000)
committerPaolo Pisati <paolo.pisati@canonical.com>
Wed, 9 Mar 2022 14:17:55 +0000 (15:17 +0100)
BugLink: https://bugs.launchpad.net/bugs/1964361
commit d920eaa4c4559f59be7b4c2d26fa0a2e1aaa3da9 upstream.

The kgdb code needs to register an undef hook for the Thumb UDF
instruction that will fault in order to be functional on Thumb2
platforms.

Reported-by: Johannes Stezenbach <js@sig21.net>
Tested-by: Johannes Stezenbach <js@sig21.net>
Fixes: 5cbad0ebf45c ("kgdb: support for ARCH=arm")
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
arch/arm/kernel/kgdb.c

index 7bd30c0a4280d9a6e029c05c49e8fb2d9b373b00..22f937e6f3ffb12a7e854179b73ea2a77c0eb06b 100644 (file)
@@ -154,22 +154,38 @@ static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
        return 0;
 }
 
-static struct undef_hook kgdb_brkpt_hook = {
+static struct undef_hook kgdb_brkpt_arm_hook = {
        .instr_mask             = 0xffffffff,
        .instr_val              = KGDB_BREAKINST,
-       .cpsr_mask              = MODE_MASK,
+       .cpsr_mask              = PSR_T_BIT | MODE_MASK,
        .cpsr_val               = SVC_MODE,
        .fn                     = kgdb_brk_fn
 };
 
-static struct undef_hook kgdb_compiled_brkpt_hook = {
+static struct undef_hook kgdb_brkpt_thumb_hook = {
+       .instr_mask             = 0xffff,
+       .instr_val              = KGDB_BREAKINST & 0xffff,
+       .cpsr_mask              = PSR_T_BIT | MODE_MASK,
+       .cpsr_val               = PSR_T_BIT | SVC_MODE,
+       .fn                     = kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_arm_hook = {
        .instr_mask             = 0xffffffff,
        .instr_val              = KGDB_COMPILED_BREAK,
-       .cpsr_mask              = MODE_MASK,
+       .cpsr_mask              = PSR_T_BIT | MODE_MASK,
        .cpsr_val               = SVC_MODE,
        .fn                     = kgdb_compiled_brk_fn
 };
 
+static struct undef_hook kgdb_compiled_brkpt_thumb_hook = {
+       .instr_mask             = 0xffff,
+       .instr_val              = KGDB_COMPILED_BREAK & 0xffff,
+       .cpsr_mask              = PSR_T_BIT | MODE_MASK,
+       .cpsr_val               = PSR_T_BIT | SVC_MODE,
+       .fn                     = kgdb_compiled_brk_fn
+};
+
 static int __kgdb_notify(struct die_args *args, unsigned long cmd)
 {
        struct pt_regs *regs = args->regs;
@@ -210,8 +226,10 @@ int kgdb_arch_init(void)
        if (ret != 0)
                return ret;
 
-       register_undef_hook(&kgdb_brkpt_hook);
-       register_undef_hook(&kgdb_compiled_brkpt_hook);
+       register_undef_hook(&kgdb_brkpt_arm_hook);
+       register_undef_hook(&kgdb_brkpt_thumb_hook);
+       register_undef_hook(&kgdb_compiled_brkpt_arm_hook);
+       register_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
 
        return 0;
 }
@@ -224,8 +242,10 @@ int kgdb_arch_init(void)
  */
 void kgdb_arch_exit(void)
 {
-       unregister_undef_hook(&kgdb_brkpt_hook);
-       unregister_undef_hook(&kgdb_compiled_brkpt_hook);
+       unregister_undef_hook(&kgdb_brkpt_arm_hook);
+       unregister_undef_hook(&kgdb_brkpt_thumb_hook);
+       unregister_undef_hook(&kgdb_compiled_brkpt_arm_hook);
+       unregister_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
        unregister_die_notifier(&kgdb_notifier);
 }