1bcf5763bSVijaya Kumar K /* 2bcf5763bSVijaya Kumar K * AArch64 KGDB support 3bcf5763bSVijaya Kumar K * 4bcf5763bSVijaya Kumar K * Based on arch/arm/kernel/kgdb.c 5bcf5763bSVijaya Kumar K * 6bcf5763bSVijaya Kumar K * Copyright (C) 2013 Cavium Inc. 7bcf5763bSVijaya Kumar K * Author: Vijaya Kumar K <vijaya.kumar@caviumnetworks.com> 8bcf5763bSVijaya Kumar K * 9bcf5763bSVijaya Kumar K * This program is free software; you can redistribute it and/or modify 10bcf5763bSVijaya Kumar K * it under the terms of the GNU General Public License version 2 as 11bcf5763bSVijaya Kumar K * published by the Free Software Foundation. 12bcf5763bSVijaya Kumar K * 13bcf5763bSVijaya Kumar K * This program is distributed in the hope that it will be useful, 14bcf5763bSVijaya Kumar K * but WITHOUT ANY WARRANTY; without even the implied warranty of 15bcf5763bSVijaya Kumar K * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16bcf5763bSVijaya Kumar K * GNU General Public License for more details. 17bcf5763bSVijaya Kumar K * 18bcf5763bSVijaya Kumar K * You should have received a copy of the GNU General Public License 19bcf5763bSVijaya Kumar K * along with this program. If not, see <http://www.gnu.org/licenses/>. 20bcf5763bSVijaya Kumar K */ 21bcf5763bSVijaya Kumar K 2267787b68SAKASHI Takahiro #include <linux/bug.h> 23bcf5763bSVijaya Kumar K #include <linux/irq.h> 24bcf5763bSVijaya Kumar K #include <linux/kdebug.h> 25bcf5763bSVijaya Kumar K #include <linux/kgdb.h> 2644b53f67SPratyush Anand #include <linux/kprobes.h> 2768db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 2868db0cf1SIngo Molnar 2967787b68SAKASHI Takahiro #include <asm/debug-monitors.h> 3067787b68SAKASHI Takahiro #include <asm/insn.h> 31bcf5763bSVijaya Kumar K #include <asm/traps.h> 32bcf5763bSVijaya Kumar K 33bcf5763bSVijaya Kumar K struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { 34bcf5763bSVijaya Kumar K { "x0", 8, offsetof(struct pt_regs, regs[0])}, 35bcf5763bSVijaya Kumar K { "x1", 8, offsetof(struct pt_regs, regs[1])}, 36bcf5763bSVijaya Kumar K { "x2", 8, offsetof(struct pt_regs, regs[2])}, 37bcf5763bSVijaya Kumar K { "x3", 8, offsetof(struct pt_regs, regs[3])}, 38bcf5763bSVijaya Kumar K { "x4", 8, offsetof(struct pt_regs, regs[4])}, 39bcf5763bSVijaya Kumar K { "x5", 8, offsetof(struct pt_regs, regs[5])}, 40bcf5763bSVijaya Kumar K { "x6", 8, offsetof(struct pt_regs, regs[6])}, 41bcf5763bSVijaya Kumar K { "x7", 8, offsetof(struct pt_regs, regs[7])}, 42bcf5763bSVijaya Kumar K { "x8", 8, offsetof(struct pt_regs, regs[8])}, 43bcf5763bSVijaya Kumar K { "x9", 8, offsetof(struct pt_regs, regs[9])}, 44bcf5763bSVijaya Kumar K { "x10", 8, offsetof(struct pt_regs, regs[10])}, 45bcf5763bSVijaya Kumar K { "x11", 8, offsetof(struct pt_regs, regs[11])}, 46bcf5763bSVijaya Kumar K { "x12", 8, offsetof(struct pt_regs, regs[12])}, 47bcf5763bSVijaya Kumar K { "x13", 8, offsetof(struct pt_regs, regs[13])}, 48bcf5763bSVijaya Kumar K { "x14", 8, offsetof(struct pt_regs, regs[14])}, 49bcf5763bSVijaya Kumar K { "x15", 8, offsetof(struct pt_regs, regs[15])}, 50bcf5763bSVijaya Kumar K { "x16", 8, offsetof(struct pt_regs, regs[16])}, 51bcf5763bSVijaya Kumar K { "x17", 8, offsetof(struct pt_regs, regs[17])}, 52bcf5763bSVijaya Kumar K { "x18", 8, offsetof(struct pt_regs, regs[18])}, 53bcf5763bSVijaya Kumar K { "x19", 8, offsetof(struct pt_regs, regs[19])}, 54bcf5763bSVijaya Kumar K { "x20", 8, offsetof(struct pt_regs, regs[20])}, 55bcf5763bSVijaya Kumar K { "x21", 8, offsetof(struct pt_regs, regs[21])}, 56bcf5763bSVijaya Kumar K { "x22", 8, offsetof(struct pt_regs, regs[22])}, 57bcf5763bSVijaya Kumar K { "x23", 8, offsetof(struct pt_regs, regs[23])}, 58bcf5763bSVijaya Kumar K { "x24", 8, offsetof(struct pt_regs, regs[24])}, 59bcf5763bSVijaya Kumar K { "x25", 8, offsetof(struct pt_regs, regs[25])}, 60bcf5763bSVijaya Kumar K { "x26", 8, offsetof(struct pt_regs, regs[26])}, 61bcf5763bSVijaya Kumar K { "x27", 8, offsetof(struct pt_regs, regs[27])}, 62bcf5763bSVijaya Kumar K { "x28", 8, offsetof(struct pt_regs, regs[28])}, 63bcf5763bSVijaya Kumar K { "x29", 8, offsetof(struct pt_regs, regs[29])}, 64bcf5763bSVijaya Kumar K { "x30", 8, offsetof(struct pt_regs, regs[30])}, 65bcf5763bSVijaya Kumar K { "sp", 8, offsetof(struct pt_regs, sp)}, 66bcf5763bSVijaya Kumar K { "pc", 8, offsetof(struct pt_regs, pc)}, 670d15ef67SDaniel Thompson /* 680d15ef67SDaniel Thompson * struct pt_regs thinks PSTATE is 64-bits wide but gdb remote 690d15ef67SDaniel Thompson * protocol disagrees. Therefore we must extract only the lower 700d15ef67SDaniel Thompson * 32-bits. Look for the big comment in asm/kgdb.h for more 710d15ef67SDaniel Thompson * detail. 720d15ef67SDaniel Thompson */ 730d15ef67SDaniel Thompson { "pstate", 4, offsetof(struct pt_regs, pstate) 740d15ef67SDaniel Thompson #ifdef CONFIG_CPU_BIG_ENDIAN 750d15ef67SDaniel Thompson + 4 760d15ef67SDaniel Thompson #endif 770d15ef67SDaniel Thompson }, 78bcf5763bSVijaya Kumar K { "v0", 16, -1 }, 79bcf5763bSVijaya Kumar K { "v1", 16, -1 }, 80bcf5763bSVijaya Kumar K { "v2", 16, -1 }, 81bcf5763bSVijaya Kumar K { "v3", 16, -1 }, 82bcf5763bSVijaya Kumar K { "v4", 16, -1 }, 83bcf5763bSVijaya Kumar K { "v5", 16, -1 }, 84bcf5763bSVijaya Kumar K { "v6", 16, -1 }, 85bcf5763bSVijaya Kumar K { "v7", 16, -1 }, 86bcf5763bSVijaya Kumar K { "v8", 16, -1 }, 87bcf5763bSVijaya Kumar K { "v9", 16, -1 }, 88bcf5763bSVijaya Kumar K { "v10", 16, -1 }, 89bcf5763bSVijaya Kumar K { "v11", 16, -1 }, 90bcf5763bSVijaya Kumar K { "v12", 16, -1 }, 91bcf5763bSVijaya Kumar K { "v13", 16, -1 }, 92bcf5763bSVijaya Kumar K { "v14", 16, -1 }, 93bcf5763bSVijaya Kumar K { "v15", 16, -1 }, 94bcf5763bSVijaya Kumar K { "v16", 16, -1 }, 95bcf5763bSVijaya Kumar K { "v17", 16, -1 }, 96bcf5763bSVijaya Kumar K { "v18", 16, -1 }, 97bcf5763bSVijaya Kumar K { "v19", 16, -1 }, 98bcf5763bSVijaya Kumar K { "v20", 16, -1 }, 99bcf5763bSVijaya Kumar K { "v21", 16, -1 }, 100bcf5763bSVijaya Kumar K { "v22", 16, -1 }, 101bcf5763bSVijaya Kumar K { "v23", 16, -1 }, 102bcf5763bSVijaya Kumar K { "v24", 16, -1 }, 103bcf5763bSVijaya Kumar K { "v25", 16, -1 }, 104bcf5763bSVijaya Kumar K { "v26", 16, -1 }, 105bcf5763bSVijaya Kumar K { "v27", 16, -1 }, 106bcf5763bSVijaya Kumar K { "v28", 16, -1 }, 107bcf5763bSVijaya Kumar K { "v29", 16, -1 }, 108bcf5763bSVijaya Kumar K { "v30", 16, -1 }, 109bcf5763bSVijaya Kumar K { "v31", 16, -1 }, 110bcf5763bSVijaya Kumar K { "fpsr", 4, -1 }, 111bcf5763bSVijaya Kumar K { "fpcr", 4, -1 }, 112bcf5763bSVijaya Kumar K }; 113bcf5763bSVijaya Kumar K 114bcf5763bSVijaya Kumar K char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) 115bcf5763bSVijaya Kumar K { 116bcf5763bSVijaya Kumar K if (regno >= DBG_MAX_REG_NUM || regno < 0) 117bcf5763bSVijaya Kumar K return NULL; 118bcf5763bSVijaya Kumar K 119bcf5763bSVijaya Kumar K if (dbg_reg_def[regno].offset != -1) 120bcf5763bSVijaya Kumar K memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, 121bcf5763bSVijaya Kumar K dbg_reg_def[regno].size); 122bcf5763bSVijaya Kumar K else 123bcf5763bSVijaya Kumar K memset(mem, 0, dbg_reg_def[regno].size); 124bcf5763bSVijaya Kumar K return dbg_reg_def[regno].name; 125bcf5763bSVijaya Kumar K } 126bcf5763bSVijaya Kumar K 127bcf5763bSVijaya Kumar K int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) 128bcf5763bSVijaya Kumar K { 129bcf5763bSVijaya Kumar K if (regno >= DBG_MAX_REG_NUM || regno < 0) 130bcf5763bSVijaya Kumar K return -EINVAL; 131bcf5763bSVijaya Kumar K 132bcf5763bSVijaya Kumar K if (dbg_reg_def[regno].offset != -1) 133bcf5763bSVijaya Kumar K memcpy((void *)regs + dbg_reg_def[regno].offset, mem, 134bcf5763bSVijaya Kumar K dbg_reg_def[regno].size); 135bcf5763bSVijaya Kumar K return 0; 136bcf5763bSVijaya Kumar K } 137bcf5763bSVijaya Kumar K 138bcf5763bSVijaya Kumar K void 139bcf5763bSVijaya Kumar K sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) 140bcf5763bSVijaya Kumar K { 14124153c03SDouglas Anderson struct cpu_context *cpu_context = &task->thread.cpu_context; 142bcf5763bSVijaya Kumar K 143bcf5763bSVijaya Kumar K /* Initialize to zero */ 144bcf5763bSVijaya Kumar K memset((char *)gdb_regs, 0, NUMREGBYTES); 14524153c03SDouglas Anderson 14624153c03SDouglas Anderson gdb_regs[19] = cpu_context->x19; 14724153c03SDouglas Anderson gdb_regs[20] = cpu_context->x20; 14824153c03SDouglas Anderson gdb_regs[21] = cpu_context->x21; 14924153c03SDouglas Anderson gdb_regs[22] = cpu_context->x22; 15024153c03SDouglas Anderson gdb_regs[23] = cpu_context->x23; 15124153c03SDouglas Anderson gdb_regs[24] = cpu_context->x24; 15224153c03SDouglas Anderson gdb_regs[25] = cpu_context->x25; 15324153c03SDouglas Anderson gdb_regs[26] = cpu_context->x26; 15424153c03SDouglas Anderson gdb_regs[27] = cpu_context->x27; 15524153c03SDouglas Anderson gdb_regs[28] = cpu_context->x28; 15624153c03SDouglas Anderson gdb_regs[29] = cpu_context->fp; 15724153c03SDouglas Anderson 15824153c03SDouglas Anderson gdb_regs[31] = cpu_context->sp; 15924153c03SDouglas Anderson gdb_regs[32] = cpu_context->pc; 160bcf5763bSVijaya Kumar K } 161bcf5763bSVijaya Kumar K 162bcf5763bSVijaya Kumar K void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) 163bcf5763bSVijaya Kumar K { 164bcf5763bSVijaya Kumar K regs->pc = pc; 165bcf5763bSVijaya Kumar K } 166bcf5763bSVijaya Kumar K 167bcf5763bSVijaya Kumar K static int compiled_break; 168bcf5763bSVijaya Kumar K 16944679a4fSVijaya Kumar K static void kgdb_arch_update_addr(struct pt_regs *regs, 17044679a4fSVijaya Kumar K char *remcom_in_buffer) 17144679a4fSVijaya Kumar K { 17244679a4fSVijaya Kumar K unsigned long addr; 17344679a4fSVijaya Kumar K char *ptr; 17444679a4fSVijaya Kumar K 17544679a4fSVijaya Kumar K ptr = &remcom_in_buffer[1]; 17644679a4fSVijaya Kumar K if (kgdb_hex2long(&ptr, &addr)) 17744679a4fSVijaya Kumar K kgdb_arch_set_pc(regs, addr); 17844679a4fSVijaya Kumar K else if (compiled_break == 1) 17944679a4fSVijaya Kumar K kgdb_arch_set_pc(regs, regs->pc + 4); 18044679a4fSVijaya Kumar K 18144679a4fSVijaya Kumar K compiled_break = 0; 18244679a4fSVijaya Kumar K } 18344679a4fSVijaya Kumar K 184bcf5763bSVijaya Kumar K int kgdb_arch_handle_exception(int exception_vector, int signo, 185bcf5763bSVijaya Kumar K int err_code, char *remcom_in_buffer, 186bcf5763bSVijaya Kumar K char *remcom_out_buffer, 187bcf5763bSVijaya Kumar K struct pt_regs *linux_regs) 188bcf5763bSVijaya Kumar K { 189bcf5763bSVijaya Kumar K int err; 190bcf5763bSVijaya Kumar K 191bcf5763bSVijaya Kumar K switch (remcom_in_buffer[0]) { 192bcf5763bSVijaya Kumar K case 'D': 193bcf5763bSVijaya Kumar K case 'k': 194bcf5763bSVijaya Kumar K /* 195bcf5763bSVijaya Kumar K * Packet D (Detach), k (kill). No special handling 196bcf5763bSVijaya Kumar K * is required here. Handle same as c packet. 197bcf5763bSVijaya Kumar K */ 198bcf5763bSVijaya Kumar K case 'c': 199bcf5763bSVijaya Kumar K /* 200bcf5763bSVijaya Kumar K * Packet c (Continue) to continue executing. 201bcf5763bSVijaya Kumar K * Set pc to required address. 202bcf5763bSVijaya Kumar K * Try to read optional parameter and set pc. 203bcf5763bSVijaya Kumar K * If this was a compiled breakpoint, we need to move 204bcf5763bSVijaya Kumar K * to the next instruction else we will just breakpoint 205bcf5763bSVijaya Kumar K * over and over again. 206bcf5763bSVijaya Kumar K */ 20744679a4fSVijaya Kumar K kgdb_arch_update_addr(linux_regs, remcom_in_buffer); 20844679a4fSVijaya Kumar K atomic_set(&kgdb_cpu_doing_single_step, -1); 20944679a4fSVijaya Kumar K kgdb_single_step = 0; 210bcf5763bSVijaya Kumar K 21144679a4fSVijaya Kumar K /* 21244679a4fSVijaya Kumar K * Received continue command, disable single step 21344679a4fSVijaya Kumar K */ 21444679a4fSVijaya Kumar K if (kernel_active_single_step()) 21544679a4fSVijaya Kumar K kernel_disable_single_step(); 21644679a4fSVijaya Kumar K 21744679a4fSVijaya Kumar K err = 0; 21844679a4fSVijaya Kumar K break; 21944679a4fSVijaya Kumar K case 's': 22044679a4fSVijaya Kumar K /* 22144679a4fSVijaya Kumar K * Update step address value with address passed 22244679a4fSVijaya Kumar K * with step packet. 22344679a4fSVijaya Kumar K * On debug exception return PC is copied to ELR 22444679a4fSVijaya Kumar K * So just update PC. 22544679a4fSVijaya Kumar K * If no step address is passed, resume from the address 22644679a4fSVijaya Kumar K * pointed by PC. Do not update PC 22744679a4fSVijaya Kumar K */ 22844679a4fSVijaya Kumar K kgdb_arch_update_addr(linux_regs, remcom_in_buffer); 22944679a4fSVijaya Kumar K atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); 23044679a4fSVijaya Kumar K kgdb_single_step = 1; 23144679a4fSVijaya Kumar K 23244679a4fSVijaya Kumar K /* 23344679a4fSVijaya Kumar K * Enable single step handling 23444679a4fSVijaya Kumar K */ 23544679a4fSVijaya Kumar K if (!kernel_active_single_step()) 23644679a4fSVijaya Kumar K kernel_enable_single_step(linux_regs); 237bcf5763bSVijaya Kumar K err = 0; 238bcf5763bSVijaya Kumar K break; 239bcf5763bSVijaya Kumar K default: 240bcf5763bSVijaya Kumar K err = -1; 241bcf5763bSVijaya Kumar K } 242bcf5763bSVijaya Kumar K return err; 243bcf5763bSVijaya Kumar K } 244bcf5763bSVijaya Kumar K 245bcf5763bSVijaya Kumar K static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) 246bcf5763bSVijaya Kumar K { 247bcf5763bSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 2486bd28856SWill Deacon return DBG_HOOK_HANDLED; 249bcf5763bSVijaya Kumar K } 25044b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_brk_fn) 251bcf5763bSVijaya Kumar K 252bcf5763bSVijaya Kumar K static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) 253bcf5763bSVijaya Kumar K { 254bcf5763bSVijaya Kumar K compiled_break = 1; 255bcf5763bSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 256bcf5763bSVijaya Kumar K 2576bd28856SWill Deacon return DBG_HOOK_HANDLED; 258bcf5763bSVijaya Kumar K } 25944b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_compiled_brk_fn); 260bcf5763bSVijaya Kumar K 26144679a4fSVijaya Kumar K static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) 26244679a4fSVijaya Kumar K { 263fb610f2aSWill Deacon if (!kgdb_single_step) 264b66c9870SPratyush Anand return DBG_HOOK_ERROR; 265b66c9870SPratyush Anand 26644679a4fSVijaya Kumar K kgdb_handle_exception(1, SIGTRAP, 0, regs); 2676bd28856SWill Deacon return DBG_HOOK_HANDLED; 26844679a4fSVijaya Kumar K } 26944b53f67SPratyush Anand NOKPROBE_SYMBOL(kgdb_step_brk_fn); 27044679a4fSVijaya Kumar K 271bcf5763bSVijaya Kumar K static struct break_hook kgdb_brkpt_hook = { 27226a04d84SWill Deacon .fn = kgdb_brk_fn, 27326a04d84SWill Deacon .imm = KGDB_DYN_DBG_BRK_IMM, 274bcf5763bSVijaya Kumar K }; 275bcf5763bSVijaya Kumar K 276bcf5763bSVijaya Kumar K static struct break_hook kgdb_compiled_brkpt_hook = { 27726a04d84SWill Deacon .fn = kgdb_compiled_brk_fn, 27826a04d84SWill Deacon .imm = KGDB_COMPILED_DBG_BRK_IMM, 279bcf5763bSVijaya Kumar K }; 280bcf5763bSVijaya Kumar K 28144679a4fSVijaya Kumar K static struct step_hook kgdb_step_hook = { 28244679a4fSVijaya Kumar K .fn = kgdb_step_brk_fn 28344679a4fSVijaya Kumar K }; 28444679a4fSVijaya Kumar K 285bcf5763bSVijaya Kumar K static int __kgdb_notify(struct die_args *args, unsigned long cmd) 286bcf5763bSVijaya Kumar K { 287bcf5763bSVijaya Kumar K struct pt_regs *regs = args->regs; 288bcf5763bSVijaya Kumar K 289bcf5763bSVijaya Kumar K if (kgdb_handle_exception(1, args->signr, cmd, regs)) 290bcf5763bSVijaya Kumar K return NOTIFY_DONE; 291bcf5763bSVijaya Kumar K return NOTIFY_STOP; 292bcf5763bSVijaya Kumar K } 293bcf5763bSVijaya Kumar K 294bcf5763bSVijaya Kumar K static int 295bcf5763bSVijaya Kumar K kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) 296bcf5763bSVijaya Kumar K { 297bcf5763bSVijaya Kumar K unsigned long flags; 298bcf5763bSVijaya Kumar K int ret; 299bcf5763bSVijaya Kumar K 300bcf5763bSVijaya Kumar K local_irq_save(flags); 301bcf5763bSVijaya Kumar K ret = __kgdb_notify(ptr, cmd); 302bcf5763bSVijaya Kumar K local_irq_restore(flags); 303bcf5763bSVijaya Kumar K 304bcf5763bSVijaya Kumar K return ret; 305bcf5763bSVijaya Kumar K } 306bcf5763bSVijaya Kumar K 307bcf5763bSVijaya Kumar K static struct notifier_block kgdb_notifier = { 308bcf5763bSVijaya Kumar K .notifier_call = kgdb_notify, 309bcf5763bSVijaya Kumar K /* 310bcf5763bSVijaya Kumar K * Want to be lowest priority 311bcf5763bSVijaya Kumar K */ 312bcf5763bSVijaya Kumar K .priority = -INT_MAX, 313bcf5763bSVijaya Kumar K }; 314bcf5763bSVijaya Kumar K 315bcf5763bSVijaya Kumar K /* 316ef769e32SAdam Buchbinder * kgdb_arch_init - Perform any architecture specific initialization. 317ef769e32SAdam Buchbinder * This function will handle the initialization of any architecture 318bcf5763bSVijaya Kumar K * specific callbacks. 319bcf5763bSVijaya Kumar K */ 320bcf5763bSVijaya Kumar K int kgdb_arch_init(void) 321bcf5763bSVijaya Kumar K { 322bcf5763bSVijaya Kumar K int ret = register_die_notifier(&kgdb_notifier); 323bcf5763bSVijaya Kumar K 324bcf5763bSVijaya Kumar K if (ret != 0) 325bcf5763bSVijaya Kumar K return ret; 326bcf5763bSVijaya Kumar K 32726a04d84SWill Deacon register_kernel_break_hook(&kgdb_brkpt_hook); 32826a04d84SWill Deacon register_kernel_break_hook(&kgdb_compiled_brkpt_hook); 32926a04d84SWill Deacon register_kernel_step_hook(&kgdb_step_hook); 330bcf5763bSVijaya Kumar K return 0; 331bcf5763bSVijaya Kumar K } 332bcf5763bSVijaya Kumar K 333bcf5763bSVijaya Kumar K /* 334bcf5763bSVijaya Kumar K * kgdb_arch_exit - Perform any architecture specific uninitalization. 335bcf5763bSVijaya Kumar K * This function will handle the uninitalization of any architecture 336bcf5763bSVijaya Kumar K * specific callbacks, for dynamic registration and unregistration. 337bcf5763bSVijaya Kumar K */ 338bcf5763bSVijaya Kumar K void kgdb_arch_exit(void) 339bcf5763bSVijaya Kumar K { 34026a04d84SWill Deacon unregister_kernel_break_hook(&kgdb_brkpt_hook); 34126a04d84SWill Deacon unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook); 34226a04d84SWill Deacon unregister_kernel_step_hook(&kgdb_step_hook); 343bcf5763bSVijaya Kumar K unregister_die_notifier(&kgdb_notifier); 344bcf5763bSVijaya Kumar K } 345bcf5763bSVijaya Kumar K 346cc028297SChristophe Leroy const struct kgdb_arch arch_kgdb_ops; 34767787b68SAKASHI Takahiro 34867787b68SAKASHI Takahiro int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) 34967787b68SAKASHI Takahiro { 35067787b68SAKASHI Takahiro int err; 35167787b68SAKASHI Takahiro 35267787b68SAKASHI Takahiro BUILD_BUG_ON(AARCH64_INSN_SIZE != BREAK_INSTR_SIZE); 35367787b68SAKASHI Takahiro 35467787b68SAKASHI Takahiro err = aarch64_insn_read((void *)bpt->bpt_addr, (u32 *)bpt->saved_instr); 35567787b68SAKASHI Takahiro if (err) 35667787b68SAKASHI Takahiro return err; 35767787b68SAKASHI Takahiro 35867787b68SAKASHI Takahiro return aarch64_insn_write((void *)bpt->bpt_addr, 35967787b68SAKASHI Takahiro (u32)AARCH64_BREAK_KGDB_DYN_DBG); 360bcf5763bSVijaya Kumar K } 36167787b68SAKASHI Takahiro 36267787b68SAKASHI Takahiro int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) 36367787b68SAKASHI Takahiro { 36467787b68SAKASHI Takahiro return aarch64_insn_write((void *)bpt->bpt_addr, 36567787b68SAKASHI Takahiro *(u32 *)bpt->saved_instr); 36667787b68SAKASHI Takahiro } 367