kgdb.c revision dcc7871128e99458ca86186b7bc8bf27ff0c47b5
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> 29631330f5847b3f8a7ea67d689e9f7c56833ccaa6Ralf Baechle#include <linux/smp.h> 308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/inst.h> 318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/fpu.h> 328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/cacheflush.h> 338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/processor.h> 348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#include <asm/sigcontext.h> 358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic struct hard_trap_info { 378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned char tt; /* Trap type code for MIPS R3xxx and R4xxx */ 388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned char signo; /* Signal that we map this trap into */ 398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} hard_trap_info[] = { 408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 6, SIGBUS }, /* instruction bus error */ 418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 7, SIGBUS }, /* data bus error */ 428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 9, SIGTRAP }, /* break */ 438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* { 11, SIGILL }, */ /* CPU unusable */ 448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 12, SIGFPE }, /* overflow */ 458854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 13, SIGTRAP }, /* trap */ 468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 14, SIGSEGV }, /* virtual instruction cache coherency */ 478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 15, SIGFPE }, /* floating point exception */ 488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 23, SIGSEGV }, /* watch */ 498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 31, SIGSEGV }, /* virtual data cache coherency */ 508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel { 0, 0} /* Must be last */ 518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel}; 528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid arch_kgdb_breakpoint(void) 548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel __asm__ __volatile__( 568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".globl breakinst\n\t" 578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".set\tnoreorder\n\t" 588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "nop\n" 598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "breakinst:\tbreak\n\t" 608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel "nop\n\t" 618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ".set\treorder"); 628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic void kgdb_call_nmi_hook(void *ignored) 658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 669391d6bbedfd28c20531be75a3929c62bb43676eRalf Baechle kgdb_nmicallback(raw_smp_processor_id(), NULL); 678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid kgdb_roundup_cpus(unsigned long flags) 708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 718854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_enable(); 72e522b7ccd26a9774cac9379476ae3c6e005c88beRalf Baechle smp_call_function(kgdb_call_nmi_hook, NULL, 0); 738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_disable(); 748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic int compute_signal(int tt) 778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct hard_trap_info *ht; 798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (ht = hard_trap_info; ht->tt && ht->signo; ht++) 818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (ht->tt == tt) 828854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return ht->signo; 838854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 848854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return SIGHUP; /* default for things we don't know about */ 858854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 868854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 878854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) 888854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 898854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 908854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 918854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 928854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u32 *ptr = (u32 *)gdb_regs; 938854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 948854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u64 *ptr = (u64 *)gdb_regs; 958854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 968854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 978854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 988854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 998854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1008854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_status; 1018854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->lo; 1028854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->hi; 1038854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_badvaddr; 1048854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_cause; 1058854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_epc; 1068854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1078854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* FP REGS */ 1088854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (!(current && (regs->cp0_status & ST0_CU1))) 1098854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return; 1108854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1118854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel save_fp(current); 1128854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1138854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = current->thread.fpu.fpr[reg]; 1148854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1158854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1168854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) 1178854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1188854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 1198854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1208854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 1218854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel const u32 *ptr = (u32 *)gdb_regs; 1228854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 1238854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel const u64 *ptr = (u64 *)gdb_regs; 1248854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 1258854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1268854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1278854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->regs[reg] = *(ptr++); 1288854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1298854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_status = *(ptr++); 1308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->lo = *(ptr++); 1318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->hi = *(ptr++); 1328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_badvaddr = *(ptr++); 1338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_cause = *(ptr++); 1348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc = *(ptr++); 1358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* FP REGS from current */ 1378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (!(current && (regs->cp0_status & ST0_CU1))) 1388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return; 1398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 32; reg++) 1418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel current->thread.fpu.fpr[reg] = *(ptr++); 1428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel restore_fp(current); 1438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1458854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 1468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Similar to regs_to_gdb_regs() except that process is sleeping and so 1478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * we may not be able to get all the info. 1488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 1498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) 1508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int reg; 1528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct thread_info *ti = task_thread_info(p); 1538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32; 1548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs = (struct pt_regs *)ksp - 1; 1558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#if (KGDB_GDB_REG_SIZE == 32) 1568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u32 *ptr = (u32 *)gdb_regs; 1578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#else 1588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel u64 *ptr = (u64 *)gdb_regs; 1598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel#endif 1608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 0; reg < 16; reg++) 1628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* S0 - S7 */ 1658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 16; reg < 24; reg++) 1668854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 24; reg < 28; reg++) 1698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = 0; 1708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1718854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* GP, SP, FP, RA */ 1728854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel for (reg = 28; reg < 32; reg++) 1738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->regs[reg]; 1748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_status; 1768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->lo; 1778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->hi; 1788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_badvaddr; 1798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_cause; 1808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel *(ptr++) = regs->cp0_epc; 1818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 1828854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 183dcc7871128e99458ca86186b7bc8bf27ff0c47b5Jason Wesselvoid kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) 184dcc7871128e99458ca86186b7bc8bf27ff0c47b5Jason Wessel{ 185dcc7871128e99458ca86186b7bc8bf27ff0c47b5Jason Wessel regs->cp0_epc = pc; 186dcc7871128e99458ca86186b7bc8bf27ff0c47b5Jason Wessel} 187dcc7871128e99458ca86186b7bc8bf27ff0c47b5Jason Wessel 1888854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 1898854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Calls linux_debug_hook before the kernel dies. If KGDB is enabled, 1908854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * then try to fall into the debugger 1918854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 1928854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, 1938854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel void *ptr) 1948854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 1958854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct die_args *args = (struct die_args *)ptr; 1968854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs = args->regs; 1978854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int trap = (regs->cp0_cause & 0x7c) >> 2; 1988854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 1998854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* Userpace events, ignore. */ 2008854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (user_mode(regs)) 2018854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_DONE; 2028854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2038854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (atomic_read(&kgdb_active) != -1) 2048854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel kgdb_nmicallback(smp_processor_id(), regs); 2058854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2068854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs)) 2078854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_DONE; 2088854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2098854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (atomic_read(&kgdb_setting_breakpoint)) 2108854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if ((trap == 9) && (regs->cp0_epc == (unsigned long)breakinst)) 2118854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc += 4; 2128854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2138854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* In SMP mode, __flush_cache_all does IPI */ 2148854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel local_irq_enable(); 2158854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel __flush_cache_all(); 2168854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2178854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return NOTIFY_STOP; 2188854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2198854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2208854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstatic struct notifier_block kgdb_notifier = { 2218854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .notifier_call = kgdb_mips_notify, 2228854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel}; 2238854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2248854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2258854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * Handle the 's' and 'c' commands 2268854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2278854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselint kgdb_arch_handle_exception(int vector, int signo, int err_code, 2288854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel char *remcom_in_buffer, char *remcom_out_buffer, 2298854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel struct pt_regs *regs) 2308854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2318854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel char *ptr; 2328854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unsigned long address; 2338854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel int cpu = smp_processor_id(); 2348854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2358854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel switch (remcom_in_buffer[0]) { 2368854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel case 's': 2378854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel case 'c': 2388854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel /* handle the optional parameter */ 2398854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel ptr = &remcom_in_buffer[1]; 2408854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (kgdb_hex2long(&ptr, &address)) 2418854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel regs->cp0_epc = address; 2428854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2438854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel atomic_set(&kgdb_cpu_doing_single_step, -1); 2448854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel if (remcom_in_buffer[0] == 's') 245d7161a65341556bacb5e6654e133803f46f51063Jason Wessel atomic_set(&kgdb_cpu_doing_single_step, cpu); 2468854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2478854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return 0; 2488854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel } 2498854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2508854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return -1; 2518854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2528854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2538854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselstruct kgdb_arch arch_kgdb_ops; 2548854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2558854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2568854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * We use kgdb_early_setup so that functions we need to call now don't 2578854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * cause trouble when called again later. 2588854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2598854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselint kgdb_arch_init(void) 2608854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2618854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel union mips_instruction insn = { 2628854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .r_format = { 2638854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .opcode = spec_op, 2648854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel .func = break_op, 2658854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel } 2668854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel }; 2678854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel memcpy(arch_kgdb_ops.gdb_bpt_instr, insn.byte, BREAK_INSTR_SIZE); 2688854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2698854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel register_die_notifier(&kgdb_notifier); 2708854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2718854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel return 0; 2728854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 2738854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel 2748854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel/* 2758854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * kgdb_arch_exit - Perform any architecture specific uninitalization. 2768854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * 2778854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * This function will handle the uninitalization of any architecture 2788854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel * specific callbacks, for dynamic registration and unregistration. 2798854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel */ 2808854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wesselvoid kgdb_arch_exit(void) 2818854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel{ 2828854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel unregister_die_notifier(&kgdb_notifier); 2838854700115ecf8aa6f087aa915b7b6cf18090d39Jason Wessel} 284