kgdb.c revision e522b7ccd26a9774cac9379476ae3c6e005c88be
18854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 28854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Originally written by Glenn Engel, Lake Stevens Instrument Division 38854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 48854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Contributed by HP Systems 58854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 68854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Modified for Linux/MIPS (and MIPS in general) by Andreas Busse 78854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Send complaints, suggestions etc. to <andy@waldorf-gmbh.de> 88854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 98854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Copyright (C) 1995 Andreas Busse 108854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 118854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Copyright (C) 2003 MontaVista Software Inc. 128854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 138854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 148854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Copyright (C) 2004-2005 MontaVista Software Inc. 158854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Author: Manish Lachwani, mlachwani@mvista.com or manish@koffee-break.com 168854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 178854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Copyright (C) 2007-2008 Wind River Systems, Inc. 188854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Author/Maintainer: Jason Wessel, jason.wessel@windriver.com 198854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 208854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * This file is licensed under the terms of the GNU General Public License 218854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * version 2. This program is licensed "as is" without any warranty of any 228854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * kind, whether express or implied. 238854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 248854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 258854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <linux/ptrace.h> /* for linux pt_regs struct */ 268854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <linux/kgdb.h> 278854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <linux/kdebug.h> 288854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <linux/sched.h> 298854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/inst.h> 308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/fpu.h> 318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/cacheflush.h> 328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/processor.h> 338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/sigcontext.h> 348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic struct hard_trap_info { 368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ 378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned char signo; /* Signal that we map this trap into */ 388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} hard_trap_info[] = { 398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 6, SIGBUS }, /* instruction bus error */ 408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 7, SIGBUS }, /* data bus error */ 418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 9, SIGTRAP }, /* break */ 428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* { 11, SIGILL }, */ /* CPU unusable */ 438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 12, SIGFPE }, /* overflow */ 448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 13, SIGTRAP }, /* trap */ 458854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 14, SIGSEGV }, /* virtual instruction cache coherency */ 468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 15, SIGFPE }, /* floating point exception */ 478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 23, SIGSEGV }, /* watch */ 488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 31, SIGSEGV }, /* virtual data cache coherency */ 498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 0, 0} /* Must be last */ 508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel}; 518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid arch_kgdb_breakpoint(void) 538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel __asm__ __volatile__( 558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".globl breakinst\n\t" 568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".set\tnoreorder\n\t" 578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "nop\n" 588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "breakinst:\tbreak\n\t" 598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "nop\n\t" 608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".set\treorder"); 618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic void kgdb_call_nmi_hook(void *ignored) 648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel kgdb_nmicallback(raw_smp_processor_id(), (void *)0); 668854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid kgdb_roundup_cpus(unsigned long flags) 698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_enable(); 71e522b7ccd26a9774cac9379476ae3c6e005c88beRalf Baechle smp_call_function(kgdb_call_nmi_hook, NULL, 0); 728854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_disable(); 738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic int compute_signal(int tt) 768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct hard_trap_info *ht; 788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (ht = hard_trap_info; ht->tt && ht->signo; ht++) 808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (ht->tt == tt) 818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return ht->signo; 828854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 838854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return SIGHUP; /* default for things we don't know about */ 848854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 858854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 868854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) 878854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 888854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 898854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 908854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 918854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u32 *ptr = (u32 *)gdb_regs; 928854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 938854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u64 *ptr = (u64 *)gdb_regs; 948854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 958854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 968854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 978854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 988854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 998854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_status; 1008854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->lo; 1018854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->hi; 1028854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_badvaddr; 1038854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_cause; 1048854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_epc; 1058854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1068854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* FP REGS */ 1078854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (!(current && (regs->cp0_status & ST0_CU1))) 1088854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return; 1098854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1108854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel save_fp(current); 1118854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1128854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = current->thread.fpu.fpr[reg]; 1138854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1148854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1158854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) 1168854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1178854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 1188854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1198854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 1208854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel const u32 *ptr = (u32 *)gdb_regs; 1218854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 1228854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel const u64 *ptr = (u64 *)gdb_regs; 1238854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 1248854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1258854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1268854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->regs[reg] = *(ptr++); 1278854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1288854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_status = *(ptr++); 1298854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->lo = *(ptr++); 1308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->hi = *(ptr++); 1318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_badvaddr = *(ptr++); 1328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_cause = *(ptr++); 1338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc = *(ptr++); 1348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* FP REGS from current */ 1368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (!(current && (regs->cp0_status & ST0_CU1))) 1378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return; 1388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel current->thread.fpu.fpr[reg] = *(ptr++); 1418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel restore_fp(current); 1428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 1458854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Similar to regs_to_gdb_regs() except that process is sleeping and so 1468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * we may not be able to get all the info. 1478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 1488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) 1498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 1518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct thread_info *ti = task_thread_info(p); 1528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; 1538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs = (struct pt_regs *)ksp - 1; 1548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 1558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u32 *ptr = (u32 *)gdb_regs; 1568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 1578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u64 *ptr = (u64 *)gdb_regs; 1588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 1598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 16; reg++) 1618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* S0 - S7 */ 1648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 16; reg < 24; reg++) 1658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1668854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 24; reg < 28; reg++) 1688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = 0; 1698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* GP, SP, FP, RA */ 1718854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 28; reg < 32; reg++) 1728854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_status; 1758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->lo; 1768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->hi; 1778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_badvaddr; 1788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_cause; 1798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_epc; 1808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1828854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 1838854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, 1848854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * then try to fall into the debugger 1858854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 1868854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, 1878854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel void *ptr) 1888854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1898854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct die_args *args = (struct die_args *)ptr; 1908854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs = args->regs; 1918854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int trap = (regs->cp0_cause & 0x7c) >> 2; 1928854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1938854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (fixup_exception(regs)) 1948854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_DONE; 1958854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1968854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* Userpace events, ignore. */ 1978854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (user_mode(regs)) 1988854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_DONE; 1998854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2008854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (atomic_read(&kgdb_active) != -1) 2018854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel kgdb_nmicallback(smp_processor_id(), regs); 2028854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2038854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs)) 2048854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_DONE; 2058854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2068854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (atomic_read(&kgdb_setting_breakpoint)) 2078854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) 2088854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc += 4; 2098854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2108854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* In SMP mode, __flush_cache_all does IPI */ 2118854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_enable(); 2128854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel __flush_cache_all(); 2138854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2148854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_STOP; 2158854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2168854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2178854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic struct notifier_block kgdb_notifier = { 2188854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .notifier_call = kgdb_mips_notify, 2198854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel}; 2208854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2218854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2228854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Handle the 's' and 'c' commands 2238854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2248854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselint kgdb_arch_handle_exception(int vector, int signo, int err_code, 2258854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel char *remcom_in_buffer, char *remcom_out_buffer, 2268854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs) 2278854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2288854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel char *ptr; 2298854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned long address; 2308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int cpu = smp_processor_id(); 2318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel switch (remcom_in_buffer[0]) { 2338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel case 's': 2348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel case 'c': 2358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* handle the optional parameter */ 2368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ptr = &remcom_in_buffer[1]; 2378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (kgdb_hex2long(&ptr, &address)) 2388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc = address; 2398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel atomic_set(&kgdb_cpu_doing_single_step, -1); 2418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (remcom_in_buffer[0] == 's') 2428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (kgdb_contthread) 2438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel atomic_set(&kgdb_cpu_doing_single_step, cpu); 2448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2458854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return 0; 2468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel } 2478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return -1; 2498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstruct kgdb_arch arch_kgdb_ops; 2528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * We use kgdb_early_setup so that functions we need to call now don't 2558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * cause trouble when called again later. 2568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselint kgdb_arch_init(void) 2588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel union mips_instruction insn = { 2608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .r_format = { 2618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .opcode = spec_op, 2628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .func = break_op, 2638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel } 2648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel }; 2658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel memcpy(arch_kgdb_ops.gdb_bpt_instr, insn.byte, BREAK_INSTR_SIZE); 2668854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel register_die_notifier(&kgdb_notifier); 2688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return 0; 2708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2718854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2728854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * kgdb_arch_exit - Perform any architecture specific uninitalization. 2748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 2758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * This function will handle the uninitalization of any architecture 2768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * specific callbacks, for dynamic registration and unregistration. 2778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid kgdb_arch_exit(void) 2798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unregister_die_notifier(&kgdb_notifier); 2818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 282