• 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/blackfin/kernel/
1/*
2 * arch/blackfin/kernel/kgdb.c - Blackfin kgdb pieces
3 *
4 * Copyright 2005-2008 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/ptrace.h>		/* for linux pt_regs struct */
10#include <linux/kgdb.h>
11#include <linux/uaccess.h>
12
13void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
14{
15	gdb_regs[BFIN_R0] = regs->r0;
16	gdb_regs[BFIN_R1] = regs->r1;
17	gdb_regs[BFIN_R2] = regs->r2;
18	gdb_regs[BFIN_R3] = regs->r3;
19	gdb_regs[BFIN_R4] = regs->r4;
20	gdb_regs[BFIN_R5] = regs->r5;
21	gdb_regs[BFIN_R6] = regs->r6;
22	gdb_regs[BFIN_R7] = regs->r7;
23	gdb_regs[BFIN_P0] = regs->p0;
24	gdb_regs[BFIN_P1] = regs->p1;
25	gdb_regs[BFIN_P2] = regs->p2;
26	gdb_regs[BFIN_P3] = regs->p3;
27	gdb_regs[BFIN_P4] = regs->p4;
28	gdb_regs[BFIN_P5] = regs->p5;
29	gdb_regs[BFIN_SP] = regs->reserved;
30	gdb_regs[BFIN_FP] = regs->fp;
31	gdb_regs[BFIN_I0] = regs->i0;
32	gdb_regs[BFIN_I1] = regs->i1;
33	gdb_regs[BFIN_I2] = regs->i2;
34	gdb_regs[BFIN_I3] = regs->i3;
35	gdb_regs[BFIN_M0] = regs->m0;
36	gdb_regs[BFIN_M1] = regs->m1;
37	gdb_regs[BFIN_M2] = regs->m2;
38	gdb_regs[BFIN_M3] = regs->m3;
39	gdb_regs[BFIN_B0] = regs->b0;
40	gdb_regs[BFIN_B1] = regs->b1;
41	gdb_regs[BFIN_B2] = regs->b2;
42	gdb_regs[BFIN_B3] = regs->b3;
43	gdb_regs[BFIN_L0] = regs->l0;
44	gdb_regs[BFIN_L1] = regs->l1;
45	gdb_regs[BFIN_L2] = regs->l2;
46	gdb_regs[BFIN_L3] = regs->l3;
47	gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
48	gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
49	gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
50	gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
51	gdb_regs[BFIN_ASTAT] = regs->astat;
52	gdb_regs[BFIN_RETS] = regs->rets;
53	gdb_regs[BFIN_LC0] = regs->lc0;
54	gdb_regs[BFIN_LT0] = regs->lt0;
55	gdb_regs[BFIN_LB0] = regs->lb0;
56	gdb_regs[BFIN_LC1] = regs->lc1;
57	gdb_regs[BFIN_LT1] = regs->lt1;
58	gdb_regs[BFIN_LB1] = regs->lb1;
59	gdb_regs[BFIN_CYCLES] = 0;
60	gdb_regs[BFIN_CYCLES2] = 0;
61	gdb_regs[BFIN_USP] = regs->usp;
62	gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
63	gdb_regs[BFIN_SYSCFG] = regs->syscfg;
64	gdb_regs[BFIN_RETI] = regs->pc;
65	gdb_regs[BFIN_RETX] = regs->retx;
66	gdb_regs[BFIN_RETN] = regs->retn;
67	gdb_regs[BFIN_RETE] = regs->rete;
68	gdb_regs[BFIN_PC] = regs->pc;
69	gdb_regs[BFIN_CC] = (regs->astat >> 5) & 1;
70	gdb_regs[BFIN_EXTRA1] = 0;
71	gdb_regs[BFIN_EXTRA2] = 0;
72	gdb_regs[BFIN_EXTRA3] = 0;
73	gdb_regs[BFIN_IPEND] = regs->ipend;
74}
75
76/*
77 * Extracts ebp, esp and eip values understandable by gdb from the values
78 * saved by switch_to.
79 * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
80 * prior to entering switch_to is 8 greater than the value that is saved.
81 * If switch_to changes, change following code appropriately.
82 */
83void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
84{
85	gdb_regs[BFIN_SP] = p->thread.ksp;
86	gdb_regs[BFIN_PC] = p->thread.pc;
87	gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat;
88}
89
90void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
91{
92	regs->r0 = gdb_regs[BFIN_R0];
93	regs->r1 = gdb_regs[BFIN_R1];
94	regs->r2 = gdb_regs[BFIN_R2];
95	regs->r3 = gdb_regs[BFIN_R3];
96	regs->r4 = gdb_regs[BFIN_R4];
97	regs->r5 = gdb_regs[BFIN_R5];
98	regs->r6 = gdb_regs[BFIN_R6];
99	regs->r7 = gdb_regs[BFIN_R7];
100	regs->p0 = gdb_regs[BFIN_P0];
101	regs->p1 = gdb_regs[BFIN_P1];
102	regs->p2 = gdb_regs[BFIN_P2];
103	regs->p3 = gdb_regs[BFIN_P3];
104	regs->p4 = gdb_regs[BFIN_P4];
105	regs->p5 = gdb_regs[BFIN_P5];
106	regs->fp = gdb_regs[BFIN_FP];
107	regs->i0 = gdb_regs[BFIN_I0];
108	regs->i1 = gdb_regs[BFIN_I1];
109	regs->i2 = gdb_regs[BFIN_I2];
110	regs->i3 = gdb_regs[BFIN_I3];
111	regs->m0 = gdb_regs[BFIN_M0];
112	regs->m1 = gdb_regs[BFIN_M1];
113	regs->m2 = gdb_regs[BFIN_M2];
114	regs->m3 = gdb_regs[BFIN_M3];
115	regs->b0 = gdb_regs[BFIN_B0];
116	regs->b1 = gdb_regs[BFIN_B1];
117	regs->b2 = gdb_regs[BFIN_B2];
118	regs->b3 = gdb_regs[BFIN_B3];
119	regs->l0 = gdb_regs[BFIN_L0];
120	regs->l1 = gdb_regs[BFIN_L1];
121	regs->l2 = gdb_regs[BFIN_L2];
122	regs->l3 = gdb_regs[BFIN_L3];
123	regs->a0x = gdb_regs[BFIN_A0_DOT_X];
124	regs->a0w = gdb_regs[BFIN_A0_DOT_W];
125	regs->a1x = gdb_regs[BFIN_A1_DOT_X];
126	regs->a1w = gdb_regs[BFIN_A1_DOT_W];
127	regs->rets = gdb_regs[BFIN_RETS];
128	regs->lc0 = gdb_regs[BFIN_LC0];
129	regs->lt0 = gdb_regs[BFIN_LT0];
130	regs->lb0 = gdb_regs[BFIN_LB0];
131	regs->lc1 = gdb_regs[BFIN_LC1];
132	regs->lt1 = gdb_regs[BFIN_LT1];
133	regs->lb1 = gdb_regs[BFIN_LB1];
134	regs->usp = gdb_regs[BFIN_USP];
135	regs->syscfg = gdb_regs[BFIN_SYSCFG];
136	regs->retx = gdb_regs[BFIN_RETX];
137	regs->retn = gdb_regs[BFIN_RETN];
138	regs->rete = gdb_regs[BFIN_RETE];
139	regs->pc = gdb_regs[BFIN_PC];
140
141}
142
143static struct hw_breakpoint {
144	unsigned int occupied:1;
145	unsigned int skip:1;
146	unsigned int enabled:1;
147	unsigned int type:1;
148	unsigned int dataacc:2;
149	unsigned short count;
150	unsigned int addr;
151} breakinfo[HW_WATCHPOINT_NUM];
152
153static int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
154{
155	int breakno;
156	int bfin_type;
157	int dataacc = 0;
158
159	switch (type) {
160	case BP_HARDWARE_BREAKPOINT:
161		bfin_type = TYPE_INST_WATCHPOINT;
162		break;
163	case BP_WRITE_WATCHPOINT:
164		dataacc = 1;
165		bfin_type = TYPE_DATA_WATCHPOINT;
166		break;
167	case BP_READ_WATCHPOINT:
168		dataacc = 2;
169		bfin_type = TYPE_DATA_WATCHPOINT;
170		break;
171	case BP_ACCESS_WATCHPOINT:
172		dataacc = 3;
173		bfin_type = TYPE_DATA_WATCHPOINT;
174		break;
175	default:
176		return -ENOSPC;
177	}
178
179	/* Becasue hardware data watchpoint impelemented in current
180	 * Blackfin can not trigger an exception event as the hardware
181	 * instrction watchpoint does, we ignaore all data watch point here.
182	 * They can be turned on easily after future blackfin design
183	 * supports this feature.
184	 */
185	for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++)
186		if (bfin_type == breakinfo[breakno].type
187			&& !breakinfo[breakno].occupied) {
188			breakinfo[breakno].occupied = 1;
189			breakinfo[breakno].skip = 0;
190			breakinfo[breakno].enabled = 1;
191			breakinfo[breakno].addr = addr;
192			breakinfo[breakno].dataacc = dataacc;
193			breakinfo[breakno].count = 0;
194			return 0;
195		}
196
197	return -ENOSPC;
198}
199
200static int bfin_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
201{
202	int breakno;
203	int bfin_type;
204
205	switch (type) {
206	case BP_HARDWARE_BREAKPOINT:
207		bfin_type = TYPE_INST_WATCHPOINT;
208		break;
209	case BP_WRITE_WATCHPOINT:
210	case BP_READ_WATCHPOINT:
211	case BP_ACCESS_WATCHPOINT:
212		bfin_type = TYPE_DATA_WATCHPOINT;
213		break;
214	default:
215		return 0;
216	}
217	for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
218		if (bfin_type == breakinfo[breakno].type
219			&& breakinfo[breakno].occupied
220			&& breakinfo[breakno].addr == addr) {
221			breakinfo[breakno].occupied = 0;
222			breakinfo[breakno].enabled = 0;
223		}
224
225	return 0;
226}
227
228static void bfin_remove_all_hw_break(void)
229{
230	int breakno;
231
232	memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_WATCHPOINT_NUM);
233
234	for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++)
235		breakinfo[breakno].type = TYPE_INST_WATCHPOINT;
236	for (; breakno < HW_WATCHPOINT_NUM; breakno++)
237		breakinfo[breakno].type = TYPE_DATA_WATCHPOINT;
238}
239
240static void bfin_correct_hw_break(void)
241{
242	int breakno;
243	unsigned int wpiactl = 0;
244	unsigned int wpdactl = 0;
245	int enable_wp = 0;
246
247	for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++)
248		if (breakinfo[breakno].enabled) {
249			enable_wp = 1;
250
251			switch (breakno) {
252			case 0:
253				wpiactl |= WPIAEN0|WPICNTEN0;
254				bfin_write_WPIA0(breakinfo[breakno].addr);
255				bfin_write_WPIACNT0(breakinfo[breakno].count
256					+ breakinfo->skip);
257				break;
258			case 1:
259				wpiactl |= WPIAEN1|WPICNTEN1;
260				bfin_write_WPIA1(breakinfo[breakno].addr);
261				bfin_write_WPIACNT1(breakinfo[breakno].count
262					+ breakinfo->skip);
263				break;
264			case 2:
265				wpiactl |= WPIAEN2|WPICNTEN2;
266				bfin_write_WPIA2(breakinfo[breakno].addr);
267				bfin_write_WPIACNT2(breakinfo[breakno].count
268					+ breakinfo->skip);
269				break;
270			case 3:
271				wpiactl |= WPIAEN3|WPICNTEN3;
272				bfin_write_WPIA3(breakinfo[breakno].addr);
273				bfin_write_WPIACNT3(breakinfo[breakno].count
274					+ breakinfo->skip);
275				break;
276			case 4:
277				wpiactl |= WPIAEN4|WPICNTEN4;
278				bfin_write_WPIA4(breakinfo[breakno].addr);
279				bfin_write_WPIACNT4(breakinfo[breakno].count
280					+ breakinfo->skip);
281				break;
282			case 5:
283				wpiactl |= WPIAEN5|WPICNTEN5;
284				bfin_write_WPIA5(breakinfo[breakno].addr);
285				bfin_write_WPIACNT5(breakinfo[breakno].count
286					+ breakinfo->skip);
287				break;
288			case 6:
289				wpdactl |= WPDAEN0|WPDCNTEN0|WPDSRC0;
290				wpdactl |= breakinfo[breakno].dataacc
291					<< WPDACC0_OFFSET;
292				bfin_write_WPDA0(breakinfo[breakno].addr);
293				bfin_write_WPDACNT0(breakinfo[breakno].count
294					+ breakinfo->skip);
295				break;
296			case 7:
297				wpdactl |= WPDAEN1|WPDCNTEN1|WPDSRC1;
298				wpdactl |= breakinfo[breakno].dataacc
299					<< WPDACC1_OFFSET;
300				bfin_write_WPDA1(breakinfo[breakno].addr);
301				bfin_write_WPDACNT1(breakinfo[breakno].count
302					+ breakinfo->skip);
303				break;
304			}
305		}
306
307	/* Should enable WPPWR bit first before set any other
308	 * WPIACTL and WPDACTL bits */
309	if (enable_wp) {
310		bfin_write_WPIACTL(WPPWR);
311		CSYNC();
312		bfin_write_WPIACTL(wpiactl|WPPWR);
313		bfin_write_WPDACTL(wpdactl);
314		CSYNC();
315	}
316}
317
318void kgdb_disable_hw_debug(struct pt_regs *regs)
319{
320	/* Disable hardware debugging while we are in kgdb */
321	bfin_write_WPIACTL(0);
322	bfin_write_WPDACTL(0);
323	CSYNC();
324}
325
326#ifdef CONFIG_SMP
327void kgdb_passive_cpu_callback(void *info)
328{
329	kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
330}
331
332void kgdb_roundup_cpus(unsigned long flags)
333{
334	smp_call_function(kgdb_passive_cpu_callback, NULL, 0);
335}
336
337void kgdb_roundup_cpu(int cpu, unsigned long flags)
338{
339	smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
340}
341#endif
342
343int kgdb_arch_handle_exception(int vector, int signo,
344			       int err_code, char *remcom_in_buffer,
345			       char *remcom_out_buffer,
346			       struct pt_regs *regs)
347{
348	long addr;
349	char *ptr;
350	int newPC;
351	int i;
352
353	switch (remcom_in_buffer[0]) {
354	case 'c':
355	case 's':
356		if (kgdb_contthread && kgdb_contthread != current) {
357			strcpy(remcom_out_buffer, "E00");
358			break;
359		}
360
361		kgdb_contthread = NULL;
362
363		/* try to read optional parameter, pc unchanged if no parm */
364		ptr = &remcom_in_buffer[1];
365		if (kgdb_hex2long(&ptr, &addr)) {
366			regs->retx = addr;
367		}
368		newPC = regs->retx;
369
370		/* clear the trace bit */
371		regs->syscfg &= 0xfffffffe;
372
373		/* set the trace bit if we're stepping */
374		if (remcom_in_buffer[0] == 's') {
375			regs->syscfg |= 0x1;
376			kgdb_single_step = regs->ipend;
377			kgdb_single_step >>= 6;
378			for (i = 10; i > 0; i--, kgdb_single_step >>= 1)
379				if (kgdb_single_step & 1)
380					break;
381			/* i indicate event priority of current stopped instruction
382			 * user space instruction is 0, IVG15 is 1, IVTMR is 10.
383			 * kgdb_single_step > 0 means in single step mode
384			 */
385			kgdb_single_step = i + 1;
386		}
387
388		bfin_correct_hw_break();
389
390		return 0;
391	}			/* switch */
392	return -1;		/* this means that we do not want to exit from the handler */
393}
394
395struct kgdb_arch arch_kgdb_ops = {
396	.gdb_bpt_instr = {0xa1},
397#ifdef CONFIG_SMP
398	.flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
399#else
400	.flags = KGDB_HW_BREAKPOINT,
401#endif
402	.set_hw_breakpoint = bfin_set_hw_break,
403	.remove_hw_breakpoint = bfin_remove_hw_break,
404	.remove_all_hw_break = bfin_remove_all_hw_break,
405	.correct_hw_break = bfin_correct_hw_break,
406};
407
408#define IN_MEM(addr, size, l1_addr, l1_size) \
409({ \
410	unsigned long __addr = (unsigned long)(addr); \
411	(l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \
412})
413#define ASYNC_BANK_SIZE \
414	(ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
415	 ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE)
416
417int kgdb_validate_break_address(unsigned long addr)
418{
419	int cpu = raw_smp_processor_id();
420
421	if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end)
422		return 0;
423	if (IN_MEM(addr, BREAK_INSTR_SIZE, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
424		return 0;
425	if (cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH))
426		return 0;
427#ifdef CONFIG_SMP
428	else if (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH))
429		return 0;
430#endif
431	if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH))
432		return 0;
433
434	return -EFAULT;
435}
436
437void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
438{
439	regs->retx = ip;
440}
441
442int kgdb_arch_init(void)
443{
444	kgdb_single_step = 0;
445
446	bfin_remove_all_hw_break();
447	return 0;
448}
449
450void kgdb_arch_exit(void)
451{
452}
453