1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 3 * arch/hexagon/kernel/kgdb.c - Hexagon KGDB S 4 * 5 * Copyright (c) 2011-2012, The Linux Foundati 6 */ 7 8 #include <linux/irq.h> 9 #include <linux/sched.h> 10 #include <linux/sched/task_stack.h> 11 #include <linux/kdebug.h> 12 #include <linux/kgdb.h> 13 14 /* All registers are 4 bytes, for now */ 15 #define GDB_SIZEOF_REG 4 16 17 /* The register names are used during printing 18 * Keep these at three letters to pretty-print 19 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_N 20 { " r0", GDB_SIZEOF_REG, offsetof(stru 21 { " r1", GDB_SIZEOF_REG, offsetof(stru 22 { " r2", GDB_SIZEOF_REG, offsetof(stru 23 { " r3", GDB_SIZEOF_REG, offsetof(stru 24 { " r4", GDB_SIZEOF_REG, offsetof(stru 25 { " r5", GDB_SIZEOF_REG, offsetof(stru 26 { " r6", GDB_SIZEOF_REG, offsetof(stru 27 { " r7", GDB_SIZEOF_REG, offsetof(stru 28 { " r8", GDB_SIZEOF_REG, offsetof(stru 29 { " r9", GDB_SIZEOF_REG, offsetof(stru 30 { "r10", GDB_SIZEOF_REG, offsetof(stru 31 { "r11", GDB_SIZEOF_REG, offsetof(stru 32 { "r12", GDB_SIZEOF_REG, offsetof(stru 33 { "r13", GDB_SIZEOF_REG, offsetof(stru 34 { "r14", GDB_SIZEOF_REG, offsetof(stru 35 { "r15", GDB_SIZEOF_REG, offsetof(stru 36 { "r16", GDB_SIZEOF_REG, offsetof(stru 37 { "r17", GDB_SIZEOF_REG, offsetof(stru 38 { "r18", GDB_SIZEOF_REG, offsetof(stru 39 { "r19", GDB_SIZEOF_REG, offsetof(stru 40 { "r20", GDB_SIZEOF_REG, offsetof(stru 41 { "r21", GDB_SIZEOF_REG, offsetof(stru 42 { "r22", GDB_SIZEOF_REG, offsetof(stru 43 { "r23", GDB_SIZEOF_REG, offsetof(stru 44 { "r24", GDB_SIZEOF_REG, offsetof(stru 45 { "r25", GDB_SIZEOF_REG, offsetof(stru 46 { "r26", GDB_SIZEOF_REG, offsetof(stru 47 { "r27", GDB_SIZEOF_REG, offsetof(stru 48 { "r28", GDB_SIZEOF_REG, offsetof(stru 49 { "r29", GDB_SIZEOF_REG, offsetof(stru 50 { "r30", GDB_SIZEOF_REG, offsetof(stru 51 { "r31", GDB_SIZEOF_REG, offsetof(stru 52 53 { "usr", GDB_SIZEOF_REG, offsetof(stru 54 { "preds", GDB_SIZEOF_REG, offsetof(st 55 { " m0", GDB_SIZEOF_REG, offsetof(stru 56 { " m1", GDB_SIZEOF_REG, offsetof(stru 57 { "sa0", GDB_SIZEOF_REG, offsetof(stru 58 { "sa1", GDB_SIZEOF_REG, offsetof(stru 59 { "lc0", GDB_SIZEOF_REG, offsetof(stru 60 { "lc1", GDB_SIZEOF_REG, offsetof(stru 61 { " gp", GDB_SIZEOF_REG, offsetof(stru 62 { "ugp", GDB_SIZEOF_REG, offsetof(stru 63 { "cs0", GDB_SIZEOF_REG, offsetof(stru 64 { "cs1", GDB_SIZEOF_REG, offsetof(stru 65 { "psp", GDB_SIZEOF_REG, offsetof(stru 66 { "elr", GDB_SIZEOF_REG, offsetof(stru 67 { "est", GDB_SIZEOF_REG, offsetof(stru 68 { "badva", GDB_SIZEOF_REG, offsetof(st 69 { "restart_r0", GDB_SIZEOF_REG, offset 70 { "syscall_nr", GDB_SIZEOF_REG, offset 71 }; 72 73 const struct kgdb_arch arch_kgdb_ops = { 74 /* trap0(#0xDB) 0x0cdb0054 */ 75 .gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x 76 }; 77 78 char *dbg_get_reg(int regno, void *mem, struct 79 { 80 if (regno >= DBG_MAX_REG_NUM || regno 81 return NULL; 82 83 *((unsigned long *) mem) = *((unsigned 84 dbg_reg_def[regno].offset)); 85 86 return dbg_reg_def[regno].name; 87 } 88 89 int dbg_set_reg(int regno, void *mem, struct p 90 { 91 if (regno >= DBG_MAX_REG_NUM || regno 92 return -EINVAL; 93 94 *((unsigned long *) ((void *)regs + db 95 *((unsigned long *) mem); 96 97 return 0; 98 } 99 100 void kgdb_arch_set_pc(struct pt_regs *regs, un 101 { 102 instruction_pointer(regs) = pc; 103 } 104 105 106 /* Not yet working */ 107 void sleeping_thread_to_gdb_regs(unsigned long 108 struct task_s 109 { 110 struct pt_regs *thread_regs; 111 112 if (task == NULL) 113 return; 114 115 /* Initialize to zero */ 116 memset(gdb_regs, 0, NUMREGBYTES); 117 118 /* Otherwise, we have only some regist 119 thread_regs = task_pt_regs(task); 120 gdb_regs[0] = thread_regs->r00; 121 } 122 123 /** 124 * kgdb_arch_handle_exception - Handle archite 125 * @vector: The error vector of the exception 126 * @signo: The signal number of the exception 127 * @err_code: The error code of the exception 128 * @remcom_in_buffer: The buffer of the packet 129 * @remcom_out_buffer: The buffer of %BUFMAX b 130 * @regs: The &struct pt_regs of the current p 131 * 132 * This function MUST handle the 'c' and 's' c 133 * as well packets to set / remove a hardware 134 * If there are additional packets which the h 135 * they are handled here. The code should ret 136 * process more packets, and a %0 or %1 if it 137 * kgdb callback. 138 * 139 * Not yet working. 140 */ 141 int kgdb_arch_handle_exception(int vector, int 142 char *remcom_in 143 struct pt_regs 144 { 145 switch (remcom_in_buffer[0]) { 146 case 's': 147 case 'c': 148 return 0; 149 } 150 /* Stay in the debugger. */ 151 return -1; 152 } 153 154 static int __kgdb_notify(struct die_args *args 155 { 156 /* cpu roundup */ 157 if (atomic_read(&kgdb_active) != -1) { 158 kgdb_nmicallback(smp_processor 159 return NOTIFY_STOP; 160 } 161 162 if (user_mode(args->regs)) 163 return NOTIFY_DONE; 164 165 if (kgdb_handle_exception(args->trapnr 166 args->regs 167 return NOTIFY_DONE; 168 169 return NOTIFY_STOP; 170 } 171 172 static int 173 kgdb_notify(struct notifier_block *self, unsig 174 { 175 unsigned long flags; 176 int ret; 177 178 local_irq_save(flags); 179 ret = __kgdb_notify(ptr, cmd); 180 local_irq_restore(flags); 181 182 return ret; 183 } 184 185 static struct notifier_block kgdb_notifier = { 186 .notifier_call = kgdb_notify, 187 188 /* 189 * Lowest-prio notifier priority, we w 190 */ 191 .priority = -INT_MAX, 192 }; 193 194 /** 195 * kgdb_arch_init - Perform any architecture s 196 * 197 * This function will handle the initializatio 198 * specific callbacks. 199 */ 200 int kgdb_arch_init(void) 201 { 202 return register_die_notifier(&kgdb_not 203 } 204 205 /** 206 * kgdb_arch_exit - Perform any architecture s 207 * 208 * This function will handle the uninitalizati 209 * specific callbacks, for dynamic registratio 210 */ 211 void kgdb_arch_exit(void) 212 { 213 unregister_die_notifier(&kgdb_notifier 214 } 215
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.