• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/powerpc/kernel/
1/*
2 * PowerPC backend to the KGDB stub.
3 *
4 * 1998 (c) Michael AK Tesch (tesch@cs.wisc.edu)
5 * Copyright (C) 2003 Timesys Corporation.
6 * Copyright (C) 2004-2006 MontaVista Software, Inc.
7 * PPC64 Mods (C) 2005 Frank Rowand (frowand@mvista.com)
8 * PPC32 support restored by Vitaly Wool <vwool@ru.mvista.com> and
9 * Sergei Shtylyov <sshtylyov@ru.mvista.com>
10 * Copyright (C) 2007-2008 Wind River Systems, Inc.
11 *
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program as licensed "as is" without any warranty of any
14 * kind, whether express or implied.
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/kgdb.h>
20#include <linux/smp.h>
21#include <linux/signal.h>
22#include <linux/ptrace.h>
23#include <linux/kdebug.h>
24#include <asm/current.h>
25#include <asm/processor.h>
26#include <asm/machdep.h>
27
28/*
29 * This table contains the mapping between PowerPC hardware trap types, and
30 * signals, which are primarily what GDB understands.  GDB and the kernel
31 * don't always agree on values, so we use constants taken from gdb-6.2.
32 */
33static struct hard_trap_info
34{
35	unsigned int tt;		/* Trap type code for powerpc */
36	unsigned char signo;		/* Signal that we map this trap into */
37} hard_trap_info[] = {
38	{ 0x0100, 0x02 /* SIGINT */  },		/* system reset */
39	{ 0x0200, 0x0b /* SIGSEGV */ },		/* machine check */
40	{ 0x0300, 0x0b /* SIGSEGV */ },		/* data access */
41	{ 0x0400, 0x0b /* SIGSEGV */ },		/* instruction access */
42	{ 0x0500, 0x02 /* SIGINT */  },		/* external interrupt */
43	{ 0x0600, 0x0a /* SIGBUS */  },		/* alignment */
44	{ 0x0700, 0x05 /* SIGTRAP */ },		/* program check */
45	{ 0x0800, 0x08 /* SIGFPE */  },		/* fp unavailable */
46	{ 0x0900, 0x0e /* SIGALRM */ },		/* decrementer */
47	{ 0x0c00, 0x14 /* SIGCHLD */ },		/* system call */
48#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
49	{ 0x2002, 0x05 /* SIGTRAP */ },		/* debug */
50#if defined(CONFIG_FSL_BOOKE)
51	{ 0x2010, 0x08 /* SIGFPE */  },		/* spe unavailable */
52	{ 0x2020, 0x08 /* SIGFPE */  },		/* spe unavailable */
53	{ 0x2030, 0x08 /* SIGFPE */  },		/* spe fp data */
54	{ 0x2040, 0x08 /* SIGFPE */  },		/* spe fp data */
55	{ 0x2050, 0x08 /* SIGFPE */  },		/* spe fp round */
56	{ 0x2060, 0x0e /* SIGILL */  },		/* performance monitor */
57	{ 0x2900, 0x08 /* SIGFPE */  },		/* apu unavailable */
58	{ 0x3100, 0x0e /* SIGALRM */ },		/* fixed interval timer */
59	{ 0x3200, 0x02 /* SIGINT */  }, 	/* watchdog */
60#else /* ! CONFIG_FSL_BOOKE */
61	{ 0x1000, 0x0e /* SIGALRM */ },		/* prog interval timer */
62	{ 0x1010, 0x0e /* SIGALRM */ },		/* fixed interval timer */
63	{ 0x1020, 0x02 /* SIGINT */  }, 	/* watchdog */
64	{ 0x2010, 0x08 /* SIGFPE */  },		/* fp unavailable */
65	{ 0x2020, 0x08 /* SIGFPE */  },		/* ap unavailable */
66#endif
67#else /* ! (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) */
68	{ 0x0d00, 0x05 /* SIGTRAP */ },		/* single-step */
69#if defined(CONFIG_8xx)
70	{ 0x1000, 0x04 /* SIGILL */  },		/* software emulation */
71#else /* ! CONFIG_8xx */
72	{ 0x0f00, 0x04 /* SIGILL */  },		/* performance monitor */
73	{ 0x0f20, 0x08 /* SIGFPE */  },		/* altivec unavailable */
74	{ 0x1300, 0x05 /* SIGTRAP */ }, 	/* instruction address break */
75#if defined(CONFIG_PPC64)
76	{ 0x1200, 0x05 /* SIGILL */  },		/* system error */
77	{ 0x1500, 0x04 /* SIGILL */  },		/* soft patch */
78	{ 0x1600, 0x04 /* SIGILL */  },		/* maintenance */
79	{ 0x1700, 0x08 /* SIGFPE */  },		/* altivec assist */
80	{ 0x1800, 0x04 /* SIGILL */  },		/* thermal */
81#else /* ! CONFIG_PPC64 */
82	{ 0x1400, 0x02 /* SIGINT */  },		/* SMI */
83	{ 0x1600, 0x08 /* SIGFPE */  },		/* altivec assist */
84	{ 0x1700, 0x04 /* SIGILL */  },		/* TAU */
85	{ 0x2000, 0x05 /* SIGTRAP */ },		/* run mode */
86#endif
87#endif
88#endif
89	{ 0x0000, 0x00 }			/* Must be last */
90};
91
92static int computeSignal(unsigned int tt)
93{
94	struct hard_trap_info *ht;
95
96	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
97		if (ht->tt == tt)
98			return ht->signo;
99
100	return SIGHUP;		/* default for things we don't know about */
101}
102
103static int kgdb_call_nmi_hook(struct pt_regs *regs)
104{
105	kgdb_nmicallback(raw_smp_processor_id(), regs);
106	return 0;
107}
108
109#ifdef CONFIG_SMP
110void kgdb_roundup_cpus(unsigned long flags)
111{
112	smp_send_debugger_break(MSG_ALL_BUT_SELF);
113}
114#endif
115
116/* KGDB functions to use existing PowerPC64 hooks. */
117static int kgdb_debugger(struct pt_regs *regs)
118{
119	return !kgdb_handle_exception(1, computeSignal(TRAP(regs)),
120				      DIE_OOPS, regs);
121}
122
123static int kgdb_handle_breakpoint(struct pt_regs *regs)
124{
125	if (user_mode(regs))
126		return 0;
127
128	if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
129		return 0;
130
131	if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
132		regs->nip += BREAK_INSTR_SIZE;
133
134	return 1;
135}
136
137static int kgdb_singlestep(struct pt_regs *regs)
138{
139	struct thread_info *thread_info, *exception_thread_info;
140
141	if (user_mode(regs))
142		return 0;
143
144	thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
145	exception_thread_info = current_thread_info();
146
147	if (thread_info != exception_thread_info)
148		memcpy(exception_thread_info, thread_info, sizeof *thread_info);
149
150	kgdb_handle_exception(0, SIGTRAP, 0, regs);
151
152	if (thread_info != exception_thread_info)
153		memcpy(thread_info, exception_thread_info, sizeof *thread_info);
154
155	return 1;
156}
157
158static int kgdb_iabr_match(struct pt_regs *regs)
159{
160	if (user_mode(regs))
161		return 0;
162
163	if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
164		return 0;
165	return 1;
166}
167
168static int kgdb_dabr_match(struct pt_regs *regs)
169{
170	if (user_mode(regs))
171		return 0;
172
173	if (kgdb_handle_exception(0, computeSignal(TRAP(regs)), 0, regs) != 0)
174		return 0;
175	return 1;
176}
177
178#define PACK64(ptr, src) do { *(ptr++) = (src); } while (0)
179
180#define PACK32(ptr, src) do {          \
181	u32 *ptr32;                   \
182	ptr32 = (u32 *)ptr;           \
183	*(ptr32++) = (src);           \
184	ptr = (unsigned long *)ptr32; \
185	} while (0)
186
187
188void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
189{
190	unsigned long *ptr = gdb_regs;
191	int reg;
192
193	memset(gdb_regs, 0, NUMREGBYTES);
194
195	for (reg = 0; reg < 32; reg++)
196		PACK64(ptr, regs->gpr[reg]);
197
198#ifdef CONFIG_FSL_BOOKE
199#ifdef CONFIG_SPE
200	for (reg = 0; reg < 32; reg++)
201		PACK64(ptr, current->thread.evr[reg]);
202#else
203	ptr += 32;
204#endif
205#else
206	/* fp registers not used by kernel, leave zero */
207	ptr += 32 * 8 / sizeof(long);
208#endif
209
210	PACK64(ptr, regs->nip);
211	PACK64(ptr, regs->msr);
212	PACK32(ptr, regs->ccr);
213	PACK64(ptr, regs->link);
214	PACK64(ptr, regs->ctr);
215	PACK32(ptr, regs->xer);
216
217	BUG_ON((unsigned long)ptr >
218	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
219}
220
221void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
222{
223	struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
224						  STACK_FRAME_OVERHEAD);
225	unsigned long *ptr = gdb_regs;
226	int reg;
227
228	memset(gdb_regs, 0, NUMREGBYTES);
229
230	/* Regs GPR0-2 */
231	for (reg = 0; reg < 3; reg++)
232		PACK64(ptr, regs->gpr[reg]);
233
234	/* Regs GPR3-13 are caller saved, not in regs->gpr[] */
235	ptr += 11;
236
237	/* Regs GPR14-31 */
238	for (reg = 14; reg < 32; reg++)
239		PACK64(ptr, regs->gpr[reg]);
240
241#ifdef CONFIG_FSL_BOOKE
242#ifdef CONFIG_SPE
243	for (reg = 0; reg < 32; reg++)
244		PACK64(ptr, p->thread.evr[reg]);
245#else
246	ptr += 32;
247#endif
248#else
249	/* fp registers not used by kernel, leave zero */
250	ptr += 32 * 8 / sizeof(long);
251#endif
252
253	PACK64(ptr, regs->nip);
254	PACK64(ptr, regs->msr);
255	PACK32(ptr, regs->ccr);
256	PACK64(ptr, regs->link);
257	PACK64(ptr, regs->ctr);
258	PACK32(ptr, regs->xer);
259
260	BUG_ON((unsigned long)ptr >
261	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
262}
263
264#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
265
266#define UNPACK32(dest, ptr) do {       \
267	u32 *ptr32;                   \
268	ptr32 = (u32 *)ptr;           \
269	dest = *(ptr32++);            \
270	ptr = (unsigned long *)ptr32; \
271	} while (0)
272
273void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
274{
275	unsigned long *ptr = gdb_regs;
276	int reg;
277
278	for (reg = 0; reg < 32; reg++)
279		UNPACK64(regs->gpr[reg], ptr);
280
281#ifdef CONFIG_FSL_BOOKE
282#ifdef CONFIG_SPE
283	for (reg = 0; reg < 32; reg++)
284		UNPACK64(current->thread.evr[reg], ptr);
285#else
286	ptr += 32;
287#endif
288#else
289	/* fp registers not used by kernel, leave zero */
290	ptr += 32 * 8 / sizeof(int);
291#endif
292
293	UNPACK64(regs->nip, ptr);
294	UNPACK64(regs->msr, ptr);
295	UNPACK32(regs->ccr, ptr);
296	UNPACK64(regs->link, ptr);
297	UNPACK64(regs->ctr, ptr);
298	UNPACK32(regs->xer, ptr);
299
300	BUG_ON((unsigned long)ptr >
301	       (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
302}
303
304void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
305{
306	regs->nip = pc;
307}
308
309/*
310 * This function does PowerPC specific procesing for interfacing to gdb.
311 */
312int kgdb_arch_handle_exception(int vector, int signo, int err_code,
313			       char *remcom_in_buffer, char *remcom_out_buffer,
314			       struct pt_regs *linux_regs)
315{
316	char *ptr = &remcom_in_buffer[1];
317	unsigned long addr;
318
319	switch (remcom_in_buffer[0]) {
320		/*
321		 * sAA..AA   Step one instruction from AA..AA
322		 * This will return an error to gdb ..
323		 */
324	case 's':
325	case 'c':
326		/* handle the optional parameter */
327		if (kgdb_hex2long(&ptr, &addr))
328			linux_regs->nip = addr;
329
330		atomic_set(&kgdb_cpu_doing_single_step, -1);
331		/* set the trace bit if we're stepping */
332		if (remcom_in_buffer[0] == 's') {
333#ifdef CONFIG_PPC_ADV_DEBUG_REGS
334			mtspr(SPRN_DBCR0,
335			      mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
336			linux_regs->msr |= MSR_DE;
337#else
338			linux_regs->msr |= MSR_SE;
339#endif
340			kgdb_single_step = 1;
341			atomic_set(&kgdb_cpu_doing_single_step,
342				   raw_smp_processor_id());
343		}
344		return 0;
345	}
346
347	return -1;
348}
349
350/*
351 * Global data
352 */
353struct kgdb_arch arch_kgdb_ops = {
354	.gdb_bpt_instr = {0x7d, 0x82, 0x10, 0x08},
355};
356
357static int kgdb_not_implemented(struct pt_regs *regs)
358{
359	return 0;
360}
361
362static void *old__debugger_ipi;
363static void *old__debugger;
364static void *old__debugger_bpt;
365static void *old__debugger_sstep;
366static void *old__debugger_iabr_match;
367static void *old__debugger_dabr_match;
368static void *old__debugger_fault_handler;
369
370int kgdb_arch_init(void)
371{
372	old__debugger_ipi = __debugger_ipi;
373	old__debugger = __debugger;
374	old__debugger_bpt = __debugger_bpt;
375	old__debugger_sstep = __debugger_sstep;
376	old__debugger_iabr_match = __debugger_iabr_match;
377	old__debugger_dabr_match = __debugger_dabr_match;
378	old__debugger_fault_handler = __debugger_fault_handler;
379
380	__debugger_ipi = kgdb_call_nmi_hook;
381	__debugger = kgdb_debugger;
382	__debugger_bpt = kgdb_handle_breakpoint;
383	__debugger_sstep = kgdb_singlestep;
384	__debugger_iabr_match = kgdb_iabr_match;
385	__debugger_dabr_match = kgdb_dabr_match;
386	__debugger_fault_handler = kgdb_not_implemented;
387
388	return 0;
389}
390
391void kgdb_arch_exit(void)
392{
393	__debugger_ipi = old__debugger_ipi;
394	__debugger = old__debugger;
395	__debugger_bpt = old__debugger_bpt;
396	__debugger_sstep = old__debugger_sstep;
397	__debugger_iabr_match = old__debugger_iabr_match;
398	__debugger_dabr_match = old__debugger_dabr_match;
399	__debugger_fault_handler = old__debugger_fault_handler;
400}
401