aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common')
-rw-r--r--arch/blackfin/mach-common/entry.S189
-rw-r--r--arch/blackfin/mach-common/head.S40
2 files changed, 167 insertions, 62 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 847c172a99e..90c7397036e 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -129,6 +129,18 @@ ENTRY(_ex_icplb_miss)
129#else 129#else
130 call __cplb_hdr; 130 call __cplb_hdr;
131#endif 131#endif
132
133#ifdef CONFIG_DEBUG_DOUBLEFAULT
134 /* While we were processing this, did we double fault? */
135 r7 = SEQSTAT; /* reason code is in bit 5:0 */
136 r6.l = lo(SEQSTAT_EXCAUSE);
137 r6.h = hi(SEQSTAT_EXCAUSE);
138 r7 = r7 & r6;
139 r6 = 0x25;
140 CC = R7 == R6;
141 if CC JUMP _double_fault;
142#endif
143
132 DEBUG_HWTRACE_RESTORE(p5, r7) 144 DEBUG_HWTRACE_RESTORE(p5, r7)
133 RESTORE_ALL_SYS 145 RESTORE_ALL_SYS
134 SP = EX_SCRATCH_REG; 146 SP = EX_SCRATCH_REG;
@@ -136,11 +148,8 @@ ENTRY(_ex_icplb_miss)
136ENDPROC(_ex_icplb_miss) 148ENDPROC(_ex_icplb_miss)
137 149
138ENTRY(_ex_syscall) 150ENTRY(_ex_syscall)
139 (R7:6,P5:4) = [sp++];
140 ASTAT = [sp++];
141 raise 15; /* invoked by TRAP #0, for sys call */ 151 raise 15; /* invoked by TRAP #0, for sys call */
142 sp = EX_SCRATCH_REG; 152 jump.s _bfin_return_from_exception;
143 rtx
144ENDPROC(_ex_syscall) 153ENDPROC(_ex_syscall)
145 154
146ENTRY(_ex_soft_bp) 155ENTRY(_ex_soft_bp)
@@ -250,6 +259,29 @@ ENTRY(_bfin_return_from_exception)
250 R7=LC1; 259 R7=LC1;
251 LC1=R7; 260 LC1=R7;
252#endif 261#endif
262
263#ifdef CONFIG_DEBUG_DOUBLEFAULT
264 /* While we were processing the current exception,
265 * did we cause another, and double fault?
266 */
267 r7 = SEQSTAT; /* reason code is in bit 5:0 */
268 r6.l = lo(SEQSTAT_EXCAUSE);
269 r6.h = hi(SEQSTAT_EXCAUSE);
270 r7 = r7 & r6;
271 r6 = 0x25;
272 CC = R7 == R6;
273 if CC JUMP _double_fault;
274
275 /* Did we cause a HW error? */
276 p5.l = lo(ILAT);
277 p5.h = hi(ILAT);
278 r6 = [p5];
279 r7 = 0x20; /* Did I just cause anther HW error? */
280 r7 = r7 & r1;
281 CC = R7 == R6;
282 if CC JUMP _double_fault;
283#endif
284
253 (R7:6,P5:4) = [sp++]; 285 (R7:6,P5:4) = [sp++];
254 ASTAT = [sp++]; 286 ASTAT = [sp++];
255 sp = EX_SCRATCH_REG; 287 sp = EX_SCRATCH_REG;
@@ -292,6 +324,14 @@ ENTRY(_ex_trap_c)
292 [p4] = p5; 324 [p4] = p5;
293 csync; 325 csync;
294 326
327#ifndef CONFIG_DEBUG_DOUBLEFAULT
328 /*
329 * Save these registers, as they are only valid in exception context
330 * (where we are now - as soon as we defer to IRQ5, they can change)
331 * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3,
332 * but they are not very interesting, so don't save them
333 */
334
295 p4.l = lo(DCPLB_FAULT_ADDR); 335 p4.l = lo(DCPLB_FAULT_ADDR);
296 p4.h = hi(DCPLB_FAULT_ADDR); 336 p4.h = hi(DCPLB_FAULT_ADDR);
297 r7 = [p4]; 337 r7 = [p4];
@@ -304,12 +344,11 @@ ENTRY(_ex_trap_c)
304 p5.l = _saved_icplb_fault_addr; 344 p5.l = _saved_icplb_fault_addr;
305 [p5] = r7; 345 [p5] = r7;
306 346
307 p4.l = _excpt_saved_stuff;
308 p4.h = _excpt_saved_stuff;
309
310 r6 = retx; 347 r6 = retx;
348 p4.l = _saved_retx;
349 p4.h = _saved_retx;
311 [p4] = r6; 350 [p4] = r6;
312 351#endif
313 r6 = SYSCFG; 352 r6 = SYSCFG;
314 [p4 + 4] = r6; 353 [p4 + 4] = r6;
315 BITCLR(r6, 0); 354 BITCLR(r6, 0);
@@ -327,59 +366,56 @@ ENTRY(_ex_trap_c)
327 r6 = 0x3f; 366 r6 = 0x3f;
328 sti r6; 367 sti r6;
329 368
330 (R7:6,P5:4) = [sp++];
331 ASTAT = [sp++];
332 SP = EX_SCRATCH_REG;
333 raise 5; 369 raise 5;
334 rtx; 370 jump.s _bfin_return_from_exception;
335ENDPROC(_ex_trap_c) 371ENDPROC(_ex_trap_c)
336 372
337/* We just realized we got an exception, while we were processing a different 373/* We just realized we got an exception, while we were processing a different
338 * exception. This is a unrecoverable event, so crash 374 * exception. This is a unrecoverable event, so crash
339 */ 375 */
340ENTRY(_double_fault) 376ENTRY(_double_fault)
341 /* Turn caches & protection off, to ensure we don't get any more 377 /* Turn caches & protection off, to ensure we don't get any more
342 * double exceptions 378 * double exceptions
343 */ 379 */
344 380
345 P4.L = LO(IMEM_CONTROL); 381 P4.L = LO(IMEM_CONTROL);
346 P4.H = HI(IMEM_CONTROL); 382 P4.H = HI(IMEM_CONTROL);
347 383
348 R5 = [P4]; /* Control Register*/ 384 R5 = [P4]; /* Control Register*/
349 BITCLR(R5,ENICPLB_P); 385 BITCLR(R5,ENICPLB_P);
350 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ 386 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
351 .align 8; 387 .align 8;
352 [P4] = R5; 388 [P4] = R5;
353 SSYNC; 389 SSYNC;
354 390
355 P4.L = LO(DMEM_CONTROL); 391 P4.L = LO(DMEM_CONTROL);
356 P4.H = HI(DMEM_CONTROL); 392 P4.H = HI(DMEM_CONTROL);
357 R5 = [P4]; 393 R5 = [P4];
358 BITCLR(R5,ENDCPLB_P); 394 BITCLR(R5,ENDCPLB_P);
359 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ 395 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
360 .align 8; 396 .align 8;
361 [P4] = R5; 397 [P4] = R5;
362 SSYNC; 398 SSYNC;
363 399
364 /* Fix up the stack */ 400 /* Fix up the stack */
365 (R7:6,P5:4) = [sp++]; 401 (R7:6,P5:4) = [sp++];
366 ASTAT = [sp++]; 402 ASTAT = [sp++];
367 SP = EX_SCRATCH_REG; 403 SP = EX_SCRATCH_REG;
368 404
369 /* We should be out of the exception stack, and back down into 405 /* We should be out of the exception stack, and back down into
370 * kernel or user space stack 406 * kernel or user space stack
371 */ 407 */
372 SAVE_ALL_SYS 408 SAVE_ALL_SYS
373 409
374 /* The dumping functions expect the return address in the RETI 410 /* The dumping functions expect the return address in the RETI
375 * slot. */ 411 * slot. */
376 r6 = retx; 412 r6 = retx;
377 [sp + PT_PC] = r6; 413 [sp + PT_PC] = r6;
378 414
379 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ 415 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
380 SP += -12; 416 SP += -12;
381 call _double_fault_c; 417 call _double_fault_c;
382 SP += 12; 418 SP += 12;
383.L_double_fault_panic: 419.L_double_fault_panic:
384 JUMP .L_double_fault_panic 420 JUMP .L_double_fault_panic
385 421
@@ -388,8 +424,8 @@ ENDPROC(_double_fault)
388ENTRY(_exception_to_level5) 424ENTRY(_exception_to_level5)
389 SAVE_ALL_SYS 425 SAVE_ALL_SYS
390 426
391 p4.l = _excpt_saved_stuff; 427 p4.l = _saved_retx;
392 p4.h = _excpt_saved_stuff; 428 p4.h = _saved_retx;
393 r6 = [p4]; 429 r6 = [p4];
394 [sp + PT_PC] = r6; 430 [sp + PT_PC] = r6;
395 431
@@ -420,6 +456,17 @@ ENTRY(_exception_to_level5)
420 call _trap_c; 456 call _trap_c;
421 SP += 12; 457 SP += 12;
422 458
459#ifdef CONFIG_DEBUG_DOUBLEFAULT
460 /* Grab ILAT */
461 p2.l = lo(ILAT);
462 p2.h = hi(ILAT);
463 r0 = [p2];
464 r1 = 0x20; /* Did I just cause anther HW error? */
465 r0 = r0 & r1;
466 CC = R0 == R1;
467 if CC JUMP _double_fault;
468#endif
469
423 call _ret_from_exception; 470 call _ret_from_exception;
424 RESTORE_ALL_SYS 471 RESTORE_ALL_SYS
425 rti; 472 rti;
@@ -436,7 +483,39 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
436 /* Try to deal with syscalls quickly. */ 483 /* Try to deal with syscalls quickly. */
437 [--sp] = ASTAT; 484 [--sp] = ASTAT;
438 [--sp] = (R7:6,P5:4); 485 [--sp] = (R7:6,P5:4);
486
487#ifdef CONFIG_DEBUG_DOUBLEFAULT
488 /*
489 * Save these registers, as they are only valid in exception context
490 * (where we are now - as soon as we defer to IRQ5, they can change)
491 * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3,
492 * but they are not very interesting, so don't save them
493 */
494
495 p4.l = lo(DCPLB_FAULT_ADDR);
496 p4.h = hi(DCPLB_FAULT_ADDR);
497 r7 = [p4];
498 p5.h = _saved_dcplb_fault_addr;
499 p5.l = _saved_dcplb_fault_addr;
500 [p5] = r7;
501
502 r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
503 p5.h = _saved_icplb_fault_addr;
504 p5.l = _saved_icplb_fault_addr;
505 [p5] = r7;
506
507 p4.l = _saved_retx;
508 p4.h = _saved_retx;
509 r6 = retx;
510 [p4] = r6;
511
439 r7 = SEQSTAT; /* reason code is in bit 5:0 */ 512 r7 = SEQSTAT; /* reason code is in bit 5:0 */
513 p4.l = _saved_seqstat;
514 p4.h = _saved_seqstat;
515 [p4] = r7;
516#else
517 r7 = SEQSTAT; /* reason code is in bit 5:0 */
518#endif
440 r6.l = lo(SEQSTAT_EXCAUSE); 519 r6.l = lo(SEQSTAT_EXCAUSE);
441 r6.h = hi(SEQSTAT_EXCAUSE); 520 r6.h = hi(SEQSTAT_EXCAUSE);
442 r7 = r7 & r6; 521 r7 = r7 & r6;
@@ -1432,15 +1511,7 @@ ENTRY(_sys_call_table)
1432 .rept NR_syscalls-(.-_sys_call_table)/4 1511 .rept NR_syscalls-(.-_sys_call_table)/4
1433 .long _sys_ni_syscall 1512 .long _sys_ni_syscall
1434 .endr 1513 .endr
1435 1514END(_sys_call_table)
1436 /*
1437 * Used to save the real RETX, IMASK and SYSCFG when temporarily
1438 * storing safe values across the transition from exception to IRQ5.
1439 */
1440_excpt_saved_stuff:
1441 .long 0;
1442 .long 0;
1443 .long 0;
1444 1515
1445_exception_stack: 1516_exception_stack:
1446 .rept 1024 1517 .rept 1024
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 191b4e974c4..7cb21cfcbf2 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -90,12 +90,46 @@ ENTRY(__start)
90 [p0] = R0; 90 [p0] = R0;
91 SSYNC; 91 SSYNC;
92 92
93 /* Save RETX, in case of doublefault */ 93 /* in case of double faults, save a few things */
94 p0.l = ___retx; 94 p0.l = _init_retx;
95 p0.h = ___retx; 95 p0.h = _init_retx;
96 R0 = RETX; 96 R0 = RETX;
97 [P0] = R0; 97 [P0] = R0;
98 98
99#ifdef CONFIG_DEBUG_DOUBLEFAULT
100 /* Only save these if we are storing them,
101 * This happens here, since L1 gets clobbered
102 * below
103 */
104 p0.l = _saved_retx;
105 p0.h = _saved_retx;
106 p1.l = _init_saved_retx;
107 p1.h = _init_saved_retx;
108 r0 = [p0];
109 [p1] = r0;
110
111 p0.l = _saved_dcplb_fault_addr;
112 p0.h = _saved_dcplb_fault_addr;
113 p1.l = _init_saved_dcplb_fault_addr;
114 p1.h = _init_saved_dcplb_fault_addr;
115 r0 = [p0];
116 [p1] = r0;
117
118 p0.l = _saved_icplb_fault_addr;
119 p0.h = _saved_icplb_fault_addr;
120 p1.l = _init_saved_icplb_fault_addr;
121 p1.h = _init_saved_icplb_fault_addr;
122 r0 = [p0];
123 [p1] = r0;
124
125 p0.l = _saved_seqstat;
126 p0.h = _saved_seqstat;
127 p1.l = _init_saved_seqstat;
128 p1.h = _init_saved_seqstat;
129 r0 = [p0];
130 [p1] = r0;
131#endif
132
99 /* Initialize stack pointer */ 133 /* Initialize stack pointer */
100 sp.l = lo(INITIAL_STACK); 134 sp.l = lo(INITIAL_STACK);
101 sp.h = hi(INITIAL_STACK); 135 sp.h = hi(INITIAL_STACK);