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