1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2bcf5763bSVijaya Kumar K /* 3bcf5763bSVijaya Kumar K * AArch64 KGDB support 4bcf5763bSVijaya Kumar K * 5bcf5763bSVijaya Kumar K * Based on arch/arm/kernel/kgdb.c 6bcf5763bSVijaya Kumar K * 7bcf5763bSVijaya Kumar K * Copyright (C) 2013 Cavium Inc. 8bcf5763bSVijaya Kumar K * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com> 9bcf5763bSVijaya Kumar K */ 10bcf5763bSVijaya Kumar K 1167787b68SAKASHI Takahiro #include <linux/bug.h> 12bcf5763bSVijaya Kumar K #include <linux/irq.h> 13bcf5763bSVijaya Kumar K #include <linux/kdebug.h> 14bcf5763bSVijaya Kumar K #include <linux/kgdb.h> 1544b53f67SPratyush Anand #include <linux/kprobes.h> 1668db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 1768db0cf1SIngo Molnar 1867787b68SAKASHI Takahiro #include <asm/debug-monitors.h> 1967787b68SAKASHI Takahiro #include <asm/insn.h> 20bcf5763bSVijaya Kumar K #include <asm/traps.h> 21bcf5763bSVijaya Kumar K 22bcf5763bSVijaya Kumar K struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { 23bcf5763bSVijaya Kumar K { "x0", 8, offsetof(struct pt_regs, regs[0])}, 24bcf5763bSVijaya Kumar K { "x1", 8, offsetof(struct pt_regs, regs[1])}, 25bcf5763bSVijaya Kumar K { "x2", 8, offsetof(struct pt_regs, regs[2])}, 26bcf5763bSVijaya Kumar K { "x3", 8, offsetof(struct pt_regs, regs[3])}, 27bcf5763bSVijaya Kumar K { "x4", 8, offsetof(struct pt_regs, regs[4])}, 28bcf5763bSVijaya Kumar K { "x5", 8, offsetof(struct pt_regs, regs[5])}, 29bcf5763bSVijaya Kumar K { "x6", 8, offsetof(struct pt_regs, regs[6])}, 30bcf5763bSVijaya Kumar K { "x7", 8, offsetof(struct pt_regs, regs[7])}, 31bcf5763bSVijaya Kumar K { "x8", 8, offsetof(struct pt_regs, regs[8])}, 32bcf5763bSVijaya Kumar K { "x9", 8, offsetof(struct pt_regs, regs[9])}, 33bcf5763bSVijaya Kumar K { "x10", 8, offsetof(struct pt_regs, regs[10])}, 34bcf5763bSVijaya Kumar K { "x11", 8, offsetof(struct pt_regs, regs[11])}, 35bcf5763bSVijaya Kumar K { "x12", 8, offsetof(struct pt_regs, regs[12])}, 36bcf5763bSVijaya Kumar K { "x13", 8, offsetof(struct pt_regs, regs[13])}, 37bcf5763bSVijaya Kumar K { "x14", 8, offsetof(struct pt_regs, regs[14])}, 38bcf5763bSVijaya Kumar K { "x15", 8, offsetof(struct pt_regs, regs[15])}, 39bcf5763bSVijaya Kumar K { "x16", 8, offsetof(struct pt_regs, regs[16])}, 40bcf5763bSVijaya Kumar K { "x17", 8, offsetof(struct pt_regs, regs[17])}, 41bcf5763bSVijaya Kumar K { "x18", 8, offsetof(struct pt_regs, regs[18])}, 42bcf5763bSVijaya Kumar K { "x19", 8, offsetof(struct pt_regs, regs[19])}, 43bcf5763bSVijaya Kumar K { "x20", 8, offsetof(struct pt_regs, regs[20])}, 44bcf5763bSVijaya Kumar K { "x21", 8, offsetof(struct pt_regs, regs[21])}, 45bcf5763bSVijaya Kumar K { "x22", 8, offsetof(struct pt_regs, regs[22])}, 46bcf5763bSVijaya Kumar K { "x23", 8, offsetof(struct pt_regs, regs[23])}, 47bcf5763bSVijaya Kumar K { "x24", 8, offsetof(struct pt_regs, regs[24])}, 48bcf5763bSVijaya Kumar K { "x25", 8, offsetof(struct pt_regs, regs[25])}, 49bcf5763bSVijaya Kumar K { "x26", 8, offsetof(struct pt_regs, regs[26])}, 50bcf5763bSVijaya Kumar K { "x27", 8, offsetof(struct pt_regs, regs[27])}, 51bcf5763bSVijaya Kumar K { "x28", 8, offsetof(struct pt_regs, regs[28])}, 52bcf5763bSVijaya Kumar K { "x29", 8, offsetof(struct pt_regs, regs[29])}, 53bcf5763bSVijaya Kumar K { "x30", 8, offsetof(struct pt_regs, regs[30])}, 54bcf5763bSVijaya Kumar K { "sp", 8, offsetof(struct pt_regs, sp)}, 55bcf5763bSVijaya Kumar K { "pc", 8, offsetof(struct pt_regs, pc)}, 560d15ef67SDaniel Thompson /* 570d15ef67SDaniel Thompson * struct pt_regs thinks PSTATE is 64-bits wide but gdb remote 580d15ef67SDaniel Thompson * protocol disagrees. Therefore we must extract only the lower 590d15ef67SDaniel Thompson * 32-bits. Look for the big comment in asm/kgdb.h for more 600d15ef67SDaniel Thompson * detail. 610d15ef67SDaniel Thompson */ 620d15ef67SDaniel Thompson { "pstate", 4, offsetof(struct pt_regs, pstate) 630d15ef67SDaniel Thompson #ifdef CONFIG_CPU_BIG_ENDIAN 640d15ef67SDaniel Thompson + 4 650d15ef67SDaniel Thompson #endif 660d15ef67SDaniel Thompson }, 67bcf5763bSVijaya Kumar K { "v0", 16, -1 }, 68bcf5763bSVijaya Kumar K { "v1", 16, -1 }, 69bcf5763bSVijaya Kumar K { "v2", 16, -1 }, 70bcf5763bSVijaya Kumar K { "v3", 16, -1 }, 71bcf5763bSVijaya Kumar K { "v4", 16, -1 }, 72bcf5763bSVijaya Kumar K { "v5", 16, -1 }, 73bcf5763bSVijaya Kumar K { "v6", 16, -1 }, 74bcf5763bSVijaya Kumar K { "v7", 16, -1 }, 75bcf5763bSVijaya Kumar K { "v8", 16, -1 }, 76bcf5763bSVijaya Kumar K { "v9", 16, -1 }, 77bcf5763bSVijaya Kumar K { "v10", 16, -1 }, 78bcf5763bSVijaya Kumar K { "v11", 16, -1 }, 79bcf5763bSVijaya Kumar K { "v12", 16, -1 }, 80bcf5763bSVijaya Kumar K { "v13", 16, -1 }, 81bcf5763bSVijaya Kumar K { "v14", 16, -1 }, 82bcf5763bSVijaya Kumar K { "v15", 16, -1 }, 83bcf5763bSVijaya Kumar K { "v16", 16, -1 }, 84bcf5763bSVijaya Kumar K { "v17", 16, -1 }, 85bcf5763bSVijaya Kumar K { "v18", 16, -1 }, 86bcf5763bSVijaya Kumar K { "v19", 16, -1 }, 87bcf5763bSVijaya Kumar K { "v20", 16, -1 }, 88bcf5763bSVijaya Kumar K { "v21", 16, -1 }, 89bcf5763bSVijaya Kumar K { "v22", 16, -1 }, 90bcf5763bSVijaya Kumar K { "v23", 16, -1 }, 91bcf5763bSVijaya Kumar K { "v24", 16, -1 }, 92bcf5763bSVijaya Kumar K { "v25", 16, -1 }, 93bcf5763bSVijaya Kumar K { "v26", 16, -1 }, 94bcf5763bSVijaya Kumar K { "v27", 16, -1 }, 95bcf5763bSVijaya Kumar K { "v28", 16, -1 }, 96bcf5763bSVijaya Kumar K { "v29", 16, -1 }, 97bcf5763bSVijaya Kumar K { "v30", 16, -1 }, 98bcf5763bSVijaya Kumar K { "v31", 16, -1 }, 99bcf5763bSVijaya Kumar K { "fpsr", 4, -1 }, 100bcf5763bSVijaya Kumar K { "fpcr", 4, -1 }, 101bcf5763bSVijaya Kumar K }; 102bcf5763bSVijaya Kumar K 103bcf5763bSVijaya Kumar K char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) 104bcf5763bSVijaya Kumar K { 105bcf5763bSVijaya Kumar K if (regno >= DBG_MAX_REG_NUM || regno < 0) 106bcf5763bSVijaya Kumar K return NULL; 107bcf5763bSVijaya Kumar K 108bcf5763bSVijaya Kumar K if (dbg_reg_def[regno].offset != -1) 109bcf5763bSVijaya Kumar K memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, 110bcf5763bSVijaya Kumar K dbg_reg_def[regno].size); 111bcf5763bSVijaya Kumar K else 112bcf5763bSVijaya Kumar K memset(mem, 0, dbg_reg_def[regno].size); 113bcf5763bSVijaya Kumar K return dbg_reg_def[regno].name; 114bcf5763bSVijaya Kumar K } 115bcf5763bSVijaya Kumar K 116bcf5763bSVijaya Kumar K int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) 117bcf5763bSVijaya Kumar K { 118bcf5763bSVijaya Kumar K if (regno >= DBG_MAX_REG_NUM || regno < 0) 119bcf5763bSVijaya Kumar K return -EINVAL; 120bcf5763bSVijaya Kumar K 121bcf5763bSVijaya Kumar K if (dbg_reg_def[regno].offset != -1) 122bcf5763bSVijaya Kumar K memcpy((void *)regs + dbg_reg_def[regno].offset, mem, 123bcf5763bSVijaya Kumar K dbg_reg_def[regno].size); 124bcf5763bSVijaya Kumar K return 0; 125bcf5763bSVijaya Kumar K } 126bcf5763bSVijaya Kumar K 127bcf5763bSVijaya Kumar K void 128bcf5763bSVijaya Kumar K sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) 129bcf5763bSVijaya Kumar K { 13024153c03SDouglas Anderson struct cpu_context *cpu_context = &task->thread.cpu_context; 131bcf5763bSVijaya Kumar K 132bcf5763bSVijaya Kumar K /* Initialize to zero */ 133bcf5763bSVijaya Kumar K memset((char *)gdb_regs, 0, NUMREGBYTES); 13424153c03SDouglas Anderson 13524153c03SDouglas Anderson gdb_regs[19] = cpu_context->x19; 13624153c03SDouglas Anderson gdb_regs[20] = cpu_context->x20; 13724153c03SDouglas Anderson gdb_regs[21] = cpu_context->x21; 13824153c03SDouglas Anderson gdb_regs[22] = cpu_context->x22; 13924153c03SDouglas Anderson gdb_regs[23] = cpu_context->x23; 14024153c03SDouglas Anderson gdb_regs[24] = cpu_context->x24; 14124153c03SDouglas Anderson gdb_regs[25] = cpu_context->x25; 14224153c03SDouglas Anderson gdb_regs[26] = cpu_context->x26; 14324153c03SDouglas Anderson gdb_regs[27] = cpu_context->x27; 14424153c03SDouglas Anderson gdb_regs[28] = cpu_context->x28; 14524153c03SDouglas Anderson gdb_regs[29] = cpu_context->fp; 14624153c03SDouglas Anderson 14724153c03SDouglas Anderson gdb_regs[31] = cpu_context->sp; 14824153c03SDouglas Anderson gdb_regs[32] = cpu_context->pc; 149bcf5763bSVijaya Kumar K } 150bcf5763bSVijaya Kumar K 151bcf5763bSVijaya Kumar K void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) 152bcf5763bSVijaya Kumar K { 153bcf5763bSVijaya Kumar K regs->pc = pc; 154bcf5763bSVijaya Kumar K } 155bcf5763bSVijaya Kumar K 156bcf5763bSVijaya Kumar K static int compiled_break; 157bcf5763bSVijaya Kumar K 15844679a4fSVijaya Kumar K static void kgdb_arch_update_addr(struct pt_regs *regs, 15944679a4fSVijaya Kumar K char *remcom_in_buffer) 16044679a4fSVijaya Kumar K { 16144679a4fSVijaya Kumar K unsigned long addr; 16244679a4fSVijaya Kumar K char *ptr; 16344679a4fSVijaya Kumar K 16444679a4fSVijaya Kumar K ptr = &remcom_in_buffer[1]; 16544679a4fSVijaya Kumar K if (kgdb_hex2long(&ptr, &addr)) 16644679a4fSVijaya Kumar K kgdb_arch_set_pc(regs, addr); 16744679a4fSVijaya Kumar K else if (compiled_break == 1) 16844679a4fSVijaya Kumar K kgdb_arch_set_pc(regs, regs->pc + 4); 16944679a4fSVijaya Kumar K 17044679a4fSVijaya Kumar K compiled_break = 0; 17144679a4fSVijaya Kumar K } 17244679a4fSVijaya Kumar K 173bcf5763bSVijaya Kumar K int kgdb_arch_handle_exception(int exception_vector, int signo, 174bcf5763bSVijaya Kumar K int err_code, char *remcom_in_buffer, 175bcf5763bSVijaya Kumar K char *remcom_out_buffer, 176bcf5763bSVijaya Kumar K struct pt_regs *linux_regs) 177bcf5763bSVijaya Kumar K { 178bcf5763bSVijaya Kumar K int err; 179bcf5763bSVijaya Kumar K 180bcf5763bSVijaya Kumar K switch (remcom_in_buffer[0]) { 181bcf5763bSVijaya Kumar K case 'D': 182bcf5763bSVijaya Kumar K case 'k': 183bcf5763bSVijaya Kumar K /* 184bcf5763bSVijaya Kumar K * Packet D (Detach), k (kill). No special handling 185bcf5763bSVijaya Kumar K * is required here. Handle same as c packet. 186bcf5763bSVijaya Kumar K */ 187bcf5763bSVijaya Kumar K case 'c': 188bcf5763bSVijaya Kumar K /* 189bcf5763bSVijaya Kumar K * Packet c (Continue) to continue executing. 190bcf5763bSVijaya Kumar K * Set pc to required address. 191bcf5763bSVijaya Kumar K * Try to read optional parameter and set pc. 192bcf5763bSVijaya Kumar K * If this was a compiled breakpoint, we need to move 193bcf5763bSVijaya Kumar K * to the next instruction else we will just breakpoint 194bcf5763bSVijaya Kumar K * over and over again. 195bcf5763bSVijaya Kumar K */ 19644679a4fSVijaya Kumar K kgdb_arch_update_addr(linux_regs, remcom_in_buffer); 19744679a4fSVijaya Kumar K atomic_set(&kgdb_cpu_doing_single_step, -1); 19844679a4fSVijaya Kumar K kgdb_single_step = 0; 199bcf5763bSVijaya Kumar K 20044679a4fSVijaya Kumar K /* 20144679a4fSVijaya Kumar K * Received continue command, disable single step 20244679a4fSVijaya Kumar K */ 20344679a4fSVijaya Kumar K if (kernel_active_single_step()) 20444679a4fSVijaya Kumar K kernel_disable_single_step(); 20544679a4fSVijaya Kumar K 20644679a4fSVijaya Kumar K err = 0; 20744679a4fSVijaya Kumar K break; 20844679a4fSVijaya Kumar K case 's': 20944679a4fSVijaya Kumar K /* 21044679a4fSVijaya Kumar K * Update step address value with address passed 21144679a4fSVijaya Kumar K * with step packet. 21244679a4fSVijaya Kumar K * On debug exception return PC is copied to ELR 21344679a4fSVijaya Kumar K * So just update PC. 21444679a4fSVijaya Kumar K * If no step address is passed, resume from the address 21544679a4fSVijaya Kumar K * pointed by PC. Do not update PC 21644679a4fSVijaya Kumar K */ 21744679a4fSVijaya Kumar K kgdb_arch_update_addr(linux_regs, remcom_in_buffer); 21844679a4fSVijaya Kumar K atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); 21944679a4fSVijaya Kumar K kgdb_single_step = 1; 22044679a4fSVijaya Kumar K 22144679a4fSVijaya Kumar K /* 22244679a4fSVijaya Kumar K * Enable single step handling 22344679a4fSVijaya Kumar K */ 22444679a4fSVijaya Kumar K if (!kernel_active_single_step()) 22544679a4fSVijaya Kumar K kernel_enable_single_step(linux_regs); 226bcf5763bSVijaya Kumar K err = 0; 227bcf5763bSVijaya Kumar K break; 228bcf5763bSVijaya Kumar K default: 229bcf5763bSVijaya Kumar K err = -1; 230bcf5763bSVijaya Kumar K } 231bcf5763bSVijaya Kumar K return err; 232bcf5763bSVijaya Kumar K } 233bcf5763bSVijaya Kumar K 234bcf5763bSVijaya Kumar K static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) 235bcf5763bSVijaya Kumar K { 236bcf5763bSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 2376bd28856SWill Deacon return DBG_HOOK_HANDLED; 238bcf5763bSVijaya Kumar K } 23944b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_brk_fn) 240bcf5763bSVijaya Kumar K 241bcf5763bSVijaya Kumar K static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) 242bcf5763bSVijaya Kumar K { 243bcf5763bSVijaya Kumar K compiled_break = 1; 244bcf5763bSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 245bcf5763bSVijaya Kumar K 2466bd28856SWill Deacon return DBG_HOOK_HANDLED; 247bcf5763bSVijaya Kumar K } 24844b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_compiled_brk_fn); 249bcf5763bSVijaya Kumar K 25044679a4fSVijaya Kumar K static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) 25144679a4fSVijaya Kumar K { 252fb610f2aSWill Deacon if (!kgdb_single_step) 253b66c9870SPratyush Anand return DBG_HOOK_ERROR; 254b66c9870SPratyush Anand 25544679a4fSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 2566bd28856SWill Deacon return DBG_HOOK_HANDLED; 25744679a4fSVijaya Kumar K } 25844b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_step_brk_fn); 25944679a4fSVijaya Kumar K 260bcf5763bSVijaya Kumar K static struct break_hook kgdb_brkpt_hook = { 26126a04d84SWill Deacon .fn = kgdb_brk_fn, 26226a04d84SWill Deacon .imm = KGDB_DYN_DBG_BRK_IMM, 263bcf5763bSVijaya Kumar K }; 264bcf5763bSVijaya Kumar K 265bcf5763bSVijaya Kumar K static struct break_hook kgdb_compiled_brkpt_hook = { 26626a04d84SWill Deacon .fn = kgdb_compiled_brk_fn, 26726a04d84SWill Deacon .imm = KGDB_COMPILED_DBG_BRK_IMM, 268bcf5763bSVijaya Kumar K }; 269bcf5763bSVijaya Kumar K 27044679a4fSVijaya Kumar K static struct step_hook kgdb_step_hook = { 27144679a4fSVijaya Kumar K .fn = kgdb_step_brk_fn 27244679a4fSVijaya Kumar K }; 27344679a4fSVijaya Kumar K 274bcf5763bSVijaya Kumar K static int __kgdb_notify(struct die_args *args, unsigned long cmd) 275bcf5763bSVijaya Kumar K { 276bcf5763bSVijaya Kumar K struct pt_regs *regs = args->regs; 277bcf5763bSVijaya Kumar K 278bcf5763bSVijaya Kumar K if (kgdb_handle_exception(1, args->signr, cmd, regs)) 279bcf5763bSVijaya Kumar K return NOTIFY_DONE; 280bcf5763bSVijaya Kumar K return NOTIFY_STOP; 281bcf5763bSVijaya Kumar K } 282bcf5763bSVijaya Kumar K 283bcf5763bSVijaya Kumar K static int 284bcf5763bSVijaya Kumar K kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) 285bcf5763bSVijaya Kumar K { 286bcf5763bSVijaya Kumar K unsigned long flags; 287bcf5763bSVijaya Kumar K int ret; 288bcf5763bSVijaya Kumar K 289bcf5763bSVijaya Kumar K local_irq_save(flags); 290bcf5763bSVijaya Kumar K ret = __kgdb_notify(ptr, cmd); 291bcf5763bSVijaya Kumar K local_irq_restore(flags); 292bcf5763bSVijaya Kumar K 293bcf5763bSVijaya Kumar K return ret; 294bcf5763bSVijaya Kumar K } 295bcf5763bSVijaya Kumar K 296bcf5763bSVijaya Kumar K static struct notifier_block kgdb_notifier = { 297bcf5763bSVijaya Kumar K .notifier_call = kgdb_notify, 298bcf5763bSVijaya Kumar K /* 299bcf5763bSVijaya Kumar K * Want to be lowest priority 300bcf5763bSVijaya Kumar K */ 301bcf5763bSVijaya Kumar K .priority = -INT_MAX, 302bcf5763bSVijaya Kumar K }; 303bcf5763bSVijaya Kumar K 304bcf5763bSVijaya Kumar K /* 305ef769e32SAdam Buchbinder * kgdb_arch_init - Perform any architecture specific initialization. 306ef769e32SAdam Buchbinder * This function will handle the initialization of any architecture 307bcf5763bSVijaya Kumar K * specific callbacks. 308bcf5763bSVijaya Kumar K */ 309bcf5763bSVijaya Kumar K int kgdb_arch_init(void) 310bcf5763bSVijaya Kumar K { 311bcf5763bSVijaya Kumar K int ret = register_die_notifier(&kgdb_notifier); 312bcf5763bSVijaya Kumar K 313bcf5763bSVijaya Kumar K if (ret != 0) 314bcf5763bSVijaya Kumar K return ret; 315bcf5763bSVijaya Kumar K 31626a04d84SWill Deacon register_kernel_break_hook(&kgdb_brkpt_hook); 31726a04d84SWill Deacon register_kernel_break_hook(&kgdb_compiled_brkpt_hook); 31826a04d84SWill Deacon register_kernel_step_hook(&kgdb_step_hook); 319bcf5763bSVijaya Kumar K return 0; 320bcf5763bSVijaya Kumar K } 321bcf5763bSVijaya Kumar K 322bcf5763bSVijaya Kumar K /* 323bcf5763bSVijaya Kumar K * kgdb_arch_exit - Perform any architecture specific uninitalization. 324bcf5763bSVijaya Kumar K * This function will handle the uninitalization of any architecture 325bcf5763bSVijaya Kumar K * specific callbacks, for dynamic registration and unregistration. 326bcf5763bSVijaya Kumar K */ 327bcf5763bSVijaya Kumar K void kgdb_arch_exit(void) 328bcf5763bSVijaya Kumar K { 32926a04d84SWill Deacon unregister_kernel_break_hook(&kgdb_brkpt_hook); 33026a04d84SWill Deacon unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook); 33126a04d84SWill Deacon unregister_kernel_step_hook(&kgdb_step_hook); 332bcf5763bSVijaya Kumar K unregister_die_notifier(&kgdb_notifier); 333bcf5763bSVijaya Kumar K } 334bcf5763bSVijaya Kumar K 335cc028297SChristophe Leroy const struct kgdb_arch arch_kgdb_ops; 33667787b68SAKASHI Takahiro 33767787b68SAKASHI Takahiro int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) 33867787b68SAKASHI Takahiro { 33967787b68SAKASHI Takahiro int err; 34067787b68SAKASHI Takahiro 34167787b68SAKASHI Takahiro BUILD_BUG_ON(AARCH64_INSN_SIZE != BREAK_INSTR_SIZE); 34267787b68SAKASHI Takahiro 34367787b68SAKASHI Takahiro err = aarch64_insn_read((void *)bpt->bpt_addr, (u32 *)bpt->saved_instr); 34467787b68SAKASHI Takahiro if (err) 34567787b68SAKASHI Takahiro return err; 34667787b68SAKASHI Takahiro 34767787b68SAKASHI Takahiro return aarch64_insn_write((void *)bpt->bpt_addr, 34867787b68SAKASHI Takahiro (u32)AARCH64_BREAK_KGDB_DYN_DBG); 349bcf5763bSVijaya Kumar K } 35067787b68SAKASHI Takahiro 35167787b68SAKASHI Takahiro int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) 35267787b68SAKASHI Takahiro { 35367787b68SAKASHI Takahiro return aarch64_insn_write((void *)bpt->bpt_addr, 35467787b68SAKASHI Takahiro *(u32 *)bpt->saved_instr); 35567787b68SAKASHI Takahiro } 356