Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  Originally written by Glenn Engel, Lake Stevens Instrument Division
0003  *
0004  *  Contributed by HP Systems
0005  *
0006  *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
0007  *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
0008  *
0009  *  Copyright (C) 1995 Andreas Busse
0010  *
0011  *  Copyright (C) 2003 MontaVista Software Inc.
0012  *  Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
0013  *
0014  *  Copyright (C) 2004-2005 MontaVista Software Inc.
0015  *  Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com
0016  *
0017  *  Copyright (C) 2007-2008 Wind River Systems, Inc.
0018  *  Author/Maintainer: Jason Wessel, jason.wessel@windriver.com
0019  *
0020  *  This file is licensed under the terms of the GNU General Public License
0021  *  version 2. This program is licensed "as is" without any warranty of any
0022  *  kind, whether express or implied.
0023  */
0024 
0025 #include <linux/ptrace.h>       /* for linux pt_regs struct */
0026 #include <linux/kgdb.h>
0027 #include <linux/kdebug.h>
0028 #include <linux/sched.h>
0029 #include <linux/smp.h>
0030 #include <asm/inst.h>
0031 #include <asm/fpu.h>
0032 #include <asm/cacheflush.h>
0033 #include <asm/processor.h>
0034 #include <asm/sigcontext.h>
0035 #include <asm/irq_regs.h>
0036 
0037 static struct hard_trap_info {
0038     unsigned char tt;   /* Trap type code for MIPS R3xxx and R4xxx */
0039     unsigned char signo;    /* Signal that we map this trap into */
0040 } hard_trap_info[] = {
0041     { 6, SIGBUS },      /* instruction bus error */
0042     { 7, SIGBUS },      /* data bus error */
0043     { 9, SIGTRAP },     /* break */
0044 /*  { 11, SIGILL }, */  /* CPU unusable */
0045     { 12, SIGFPE },     /* overflow */
0046     { 13, SIGTRAP },    /* trap */
0047     { 14, SIGSEGV },    /* virtual instruction cache coherency */
0048     { 15, SIGFPE },     /* floating point exception */
0049     { 23, SIGSEGV },    /* watch */
0050     { 31, SIGSEGV },    /* virtual data cache coherency */
0051     { 0, 0}         /* Must be last */
0052 };
0053 
0054 struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
0055 {
0056     { "zero", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[0]) },
0057     { "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[1]) },
0058     { "v0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[2]) },
0059     { "v1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[3]) },
0060     { "a0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[4]) },
0061     { "a1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[5]) },
0062     { "a2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[6]) },
0063     { "a3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[7]) },
0064     { "t0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[8]) },
0065     { "t1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[9]) },
0066     { "t2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[10]) },
0067     { "t3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[11]) },
0068     { "t4", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[12]) },
0069     { "t5", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[13]) },
0070     { "t6", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[14]) },
0071     { "t7", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[15]) },
0072     { "s0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[16]) },
0073     { "s1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[17]) },
0074     { "s2", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[18]) },
0075     { "s3", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[19]) },
0076     { "s4", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[20]) },
0077     { "s5", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[21]) },
0078     { "s6", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[22]) },
0079     { "s7", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[23]) },
0080     { "t8", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[24]) },
0081     { "t9", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[25]) },
0082     { "k0", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[26]) },
0083     { "k1", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[27]) },
0084     { "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[28]) },
0085     { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[29]) },
0086     { "s8", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[30]) },
0087     { "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[31]) },
0088     { "sr", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_status) },
0089     { "lo", GDB_SIZEOF_REG, offsetof(struct pt_regs, lo) },
0090     { "hi", GDB_SIZEOF_REG, offsetof(struct pt_regs, hi) },
0091     { "bad", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_badvaddr) },
0092     { "cause", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_cause) },
0093     { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, cp0_epc) },
0094     { "f0", GDB_SIZEOF_REG, 0 },
0095     { "f1", GDB_SIZEOF_REG, 1 },
0096     { "f2", GDB_SIZEOF_REG, 2 },
0097     { "f3", GDB_SIZEOF_REG, 3 },
0098     { "f4", GDB_SIZEOF_REG, 4 },
0099     { "f5", GDB_SIZEOF_REG, 5 },
0100     { "f6", GDB_SIZEOF_REG, 6 },
0101     { "f7", GDB_SIZEOF_REG, 7 },
0102     { "f8", GDB_SIZEOF_REG, 8 },
0103     { "f9", GDB_SIZEOF_REG, 9 },
0104     { "f10", GDB_SIZEOF_REG, 10 },
0105     { "f11", GDB_SIZEOF_REG, 11 },
0106     { "f12", GDB_SIZEOF_REG, 12 },
0107     { "f13", GDB_SIZEOF_REG, 13 },
0108     { "f14", GDB_SIZEOF_REG, 14 },
0109     { "f15", GDB_SIZEOF_REG, 15 },
0110     { "f16", GDB_SIZEOF_REG, 16 },
0111     { "f17", GDB_SIZEOF_REG, 17 },
0112     { "f18", GDB_SIZEOF_REG, 18 },
0113     { "f19", GDB_SIZEOF_REG, 19 },
0114     { "f20", GDB_SIZEOF_REG, 20 },
0115     { "f21", GDB_SIZEOF_REG, 21 },
0116     { "f22", GDB_SIZEOF_REG, 22 },
0117     { "f23", GDB_SIZEOF_REG, 23 },
0118     { "f24", GDB_SIZEOF_REG, 24 },
0119     { "f25", GDB_SIZEOF_REG, 25 },
0120     { "f26", GDB_SIZEOF_REG, 26 },
0121     { "f27", GDB_SIZEOF_REG, 27 },
0122     { "f28", GDB_SIZEOF_REG, 28 },
0123     { "f29", GDB_SIZEOF_REG, 29 },
0124     { "f30", GDB_SIZEOF_REG, 30 },
0125     { "f31", GDB_SIZEOF_REG, 31 },
0126     { "fsr", GDB_SIZEOF_REG, 0 },
0127     { "fir", GDB_SIZEOF_REG, 0 },
0128 };
0129 
0130 int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
0131 {
0132     int fp_reg;
0133 
0134     if (regno < 0 || regno >= DBG_MAX_REG_NUM)
0135         return -EINVAL;
0136 
0137     if (dbg_reg_def[regno].offset != -1 && regno < 38) {
0138         memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
0139                dbg_reg_def[regno].size);
0140     } else if (current && dbg_reg_def[regno].offset != -1 && regno < 72) {
0141         /* FP registers 38 -> 69 */
0142         if (!(regs->cp0_status & ST0_CU1))
0143             return 0;
0144         if (regno == 70) {
0145             /* Process the fcr31/fsr (register 70) */
0146             memcpy((void *)&current->thread.fpu.fcr31, mem,
0147                    dbg_reg_def[regno].size);
0148             goto out_save;
0149         } else if (regno == 71) {
0150             /* Ignore the fir (register 71) */
0151             goto out_save;
0152         }
0153         fp_reg = dbg_reg_def[regno].offset;
0154         memcpy((void *)&current->thread.fpu.fpr[fp_reg], mem,
0155                dbg_reg_def[regno].size);
0156 out_save:
0157         restore_fp(current);
0158     }
0159 
0160     return 0;
0161 }
0162 
0163 char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
0164 {
0165     int fp_reg;
0166 
0167     if (regno >= DBG_MAX_REG_NUM || regno < 0)
0168         return NULL;
0169 
0170     if (dbg_reg_def[regno].offset != -1 && regno < 38) {
0171         /* First 38 registers */
0172         memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
0173                dbg_reg_def[regno].size);
0174     } else if (current && dbg_reg_def[regno].offset != -1 && regno < 72) {
0175         /* FP registers 38 -> 69 */
0176         if (!(regs->cp0_status & ST0_CU1))
0177             goto out;
0178         save_fp(current);
0179         if (regno == 70) {
0180             /* Process the fcr31/fsr (register 70) */
0181             memcpy(mem, (void *)&current->thread.fpu.fcr31,
0182                    dbg_reg_def[regno].size);
0183             goto out;
0184         } else if (regno == 71) {
0185             /* Ignore the fir (register 71) */
0186             memset(mem, 0, dbg_reg_def[regno].size);
0187             goto out;
0188         }
0189         fp_reg = dbg_reg_def[regno].offset;
0190         memcpy(mem, (void *)&current->thread.fpu.fpr[fp_reg],
0191                dbg_reg_def[regno].size);
0192     }
0193 
0194 out:
0195     return dbg_reg_def[regno].name;
0196 
0197 }
0198 
0199 void arch_kgdb_breakpoint(void)
0200 {
0201     __asm__ __volatile__(
0202         ".globl breakinst\n\t"
0203         ".set\tnoreorder\n\t"
0204         "nop\n"
0205         "breakinst:\tbreak\n\t"
0206         "nop\n\t"
0207         ".set\treorder");
0208 }
0209 
0210 static int compute_signal(int tt)
0211 {
0212     struct hard_trap_info *ht;
0213 
0214     for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
0215         if (ht->tt == tt)
0216             return ht->signo;
0217 
0218     return SIGHUP;      /* default for things we don't know about */
0219 }
0220 
0221 /*
0222  * Similar to regs_to_gdb_regs() except that process is sleeping and so
0223  * we may not be able to get all the info.
0224  */
0225 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
0226 {
0227     int reg;
0228 #if (KGDB_GDB_REG_SIZE == 32)
0229     u32 *ptr = (u32 *)gdb_regs;
0230 #else
0231     u64 *ptr = (u64 *)gdb_regs;
0232 #endif
0233 
0234     for (reg = 0; reg < 16; reg++)
0235         *(ptr++) = 0;
0236 
0237     /* S0 - S7 */
0238     *(ptr++) = p->thread.reg16;
0239     *(ptr++) = p->thread.reg17;
0240     *(ptr++) = p->thread.reg18;
0241     *(ptr++) = p->thread.reg19;
0242     *(ptr++) = p->thread.reg20;
0243     *(ptr++) = p->thread.reg21;
0244     *(ptr++) = p->thread.reg22;
0245     *(ptr++) = p->thread.reg23;
0246 
0247     for (reg = 24; reg < 28; reg++)
0248         *(ptr++) = 0;
0249 
0250     /* GP, SP, FP, RA */
0251     *(ptr++) = (long)p;
0252     *(ptr++) = p->thread.reg29;
0253     *(ptr++) = p->thread.reg30;
0254     *(ptr++) = p->thread.reg31;
0255 
0256     *(ptr++) = p->thread.cp0_status;
0257 
0258     /* lo, hi */
0259     *(ptr++) = 0;
0260     *(ptr++) = 0;
0261 
0262     /*
0263      * BadVAddr, Cause
0264      * Ideally these would come from the last exception frame up the stack
0265      * but that requires unwinding, otherwise we can't know much for sure.
0266      */
0267     *(ptr++) = 0;
0268     *(ptr++) = 0;
0269 
0270     /*
0271      * PC
0272      * use return address (RA), i.e. the moment after return from resume()
0273      */
0274     *(ptr++) = p->thread.reg31;
0275 }
0276 
0277 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
0278 {
0279     regs->cp0_epc = pc;
0280 }
0281 
0282 /*
0283  * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
0284  * then try to fall into the debugger
0285  */
0286 static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
0287                 void *ptr)
0288 {
0289     struct die_args *args = (struct die_args *)ptr;
0290     struct pt_regs *regs = args->regs;
0291     int trap = (regs->cp0_cause & 0x7c) >> 2;
0292 
0293 #ifdef CONFIG_KPROBES
0294     /*
0295      * Return immediately if the kprobes fault notifier has set
0296      * DIE_PAGE_FAULT.
0297      */
0298     if (cmd == DIE_PAGE_FAULT)
0299         return NOTIFY_DONE;
0300 #endif /* CONFIG_KPROBES */
0301 
0302     /* Userspace events, ignore. */
0303     if (user_mode(regs))
0304         return NOTIFY_DONE;
0305 
0306     if (atomic_read(&kgdb_active) != -1)
0307         kgdb_nmicallback(smp_processor_id(), regs);
0308 
0309     if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs))
0310         return NOTIFY_DONE;
0311 
0312     if (atomic_read(&kgdb_setting_breakpoint))
0313         if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst))
0314             regs->cp0_epc += 4;
0315 
0316     /* In SMP mode, __flush_cache_all does IPI */
0317     local_irq_enable();
0318     __flush_cache_all();
0319 
0320     return NOTIFY_STOP;
0321 }
0322 
0323 #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
0324 int kgdb_ll_trap(int cmd, const char *str,
0325          struct pt_regs *regs, long err, int trap, int sig)
0326 {
0327     struct die_args args = {
0328         .regs   = regs,
0329         .str    = str,
0330         .err    = err,
0331         .trapnr = trap,
0332         .signr  = sig,
0333 
0334     };
0335 
0336     if (!kgdb_io_module_registered)
0337         return NOTIFY_DONE;
0338 
0339     return kgdb_mips_notify(NULL, cmd, &args);
0340 }
0341 #endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
0342 
0343 static struct notifier_block kgdb_notifier = {
0344     .notifier_call = kgdb_mips_notify,
0345 };
0346 
0347 /*
0348  * Handle the 'c' command
0349  */
0350 int kgdb_arch_handle_exception(int vector, int signo, int err_code,
0351                    char *remcom_in_buffer, char *remcom_out_buffer,
0352                    struct pt_regs *regs)
0353 {
0354     char *ptr;
0355     unsigned long address;
0356 
0357     switch (remcom_in_buffer[0]) {
0358     case 'c':
0359         /* handle the optional parameter */
0360         ptr = &remcom_in_buffer[1];
0361         if (kgdb_hex2long(&ptr, &address))
0362             regs->cp0_epc = address;
0363 
0364         return 0;
0365     }
0366 
0367     return -1;
0368 }
0369 
0370 const struct kgdb_arch arch_kgdb_ops = {
0371 #ifdef CONFIG_CPU_BIG_ENDIAN
0372     .gdb_bpt_instr = { spec_op << 2, 0x00, 0x00, break_op },
0373 #else
0374     .gdb_bpt_instr = { break_op, 0x00, 0x00, spec_op << 2 },
0375 #endif
0376 };
0377 
0378 int kgdb_arch_init(void)
0379 {
0380     register_die_notifier(&kgdb_notifier);
0381 
0382     return 0;
0383 }
0384 
0385 /*
0386  *  kgdb_arch_exit - Perform any architecture specific uninitalization.
0387  *
0388  *  This function will handle the uninitalization of any architecture
0389  *  specific callbacks, for dynamic registration and unregistration.
0390  */
0391 void kgdb_arch_exit(void)
0392 {
0393     unregister_die_notifier(&kgdb_notifier);
0394 }