aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r--arch/blackfin/mach-common/entry.S219
1 files changed, 158 insertions, 61 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 847c172a99eb..c13fa8da28c7 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)
@@ -181,8 +190,8 @@ ENTRY(_ex_single_step)
181 if cc jump .Lfind_priority_done; 190 if cc jump .Lfind_priority_done;
182 jump.s .Lfind_priority_start; 191 jump.s .Lfind_priority_start;
183.Lfind_priority_done: 192.Lfind_priority_done:
184 p4.l = _debugger_step; 193 p4.l = _kgdb_single_step;
185 p4.h = _debugger_step; 194 p4.h = _kgdb_single_step;
186 r6 = [p4]; 195 r6 = [p4];
187 cc = r6 == 0; 196 cc = r6 == 0;
188 if cc jump .Ldo_single_step; 197 if cc jump .Ldo_single_step;
@@ -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,48 @@ 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#if ANOMALY_05000283 || ANOMALY_05000315
488 cc = r7 == r7;
489 p5.h = HI(CHIPID);
490 p5.l = LO(CHIPID);
491 if cc jump 1f;
492 r7.l = W[p5];
4931:
494#endif
495
496#ifdef CONFIG_DEBUG_DOUBLEFAULT
497 /*
498 * Save these registers, as they are only valid in exception context
499 * (where we are now - as soon as we defer to IRQ5, they can change)
500 * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3,
501 * but they are not very interesting, so don't save them
502 */
503
504 p4.l = lo(DCPLB_FAULT_ADDR);
505 p4.h = hi(DCPLB_FAULT_ADDR);
506 r7 = [p4];
507 p5.h = _saved_dcplb_fault_addr;
508 p5.l = _saved_dcplb_fault_addr;
509 [p5] = r7;
510
511 r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
512 p5.h = _saved_icplb_fault_addr;
513 p5.l = _saved_icplb_fault_addr;
514 [p5] = r7;
515
516 p4.l = _saved_retx;
517 p4.h = _saved_retx;
518 r6 = retx;
519 [p4] = r6;
520
439 r7 = SEQSTAT; /* reason code is in bit 5:0 */ 521 r7 = SEQSTAT; /* reason code is in bit 5:0 */
522 p4.l = _saved_seqstat;
523 p4.h = _saved_seqstat;
524 [p4] = r7;
525#else
526 r7 = SEQSTAT; /* reason code is in bit 5:0 */
527#endif
440 r6.l = lo(SEQSTAT_EXCAUSE); 528 r6.l = lo(SEQSTAT_EXCAUSE);
441 r6.h = hi(SEQSTAT_EXCAUSE); 529 r6.h = hi(SEQSTAT_EXCAUSE);
442 r7 = r7 & r6; 530 r7 = r7 & r6;
@@ -616,6 +704,9 @@ ENTRY(_system_call)
616 rts; 704 rts;
617ENDPROC(_system_call) 705ENDPROC(_system_call)
618 706
707/* Do not mark as ENTRY() to avoid error in assembler ...
708 * this symbol need not be global anyways, so ...
709 */
619_sys_trace: 710_sys_trace:
620 call _syscall_trace; 711 call _syscall_trace;
621 712
@@ -941,6 +1032,15 @@ ENTRY(_early_trap)
941 SAVE_ALL_SYS 1032 SAVE_ALL_SYS
942 trace_buffer_stop(p0,r0); 1033 trace_buffer_stop(p0,r0);
943 1034
1035#if ANOMALY_05000283 || ANOMALY_05000315
1036 cc = r5 == r5;
1037 p4.h = HI(CHIPID);
1038 p4.l = LO(CHIPID);
1039 if cc jump 1f;
1040 r5.l = W[p4];
10411:
1042#endif
1043
944 /* Turn caches off, to ensure we don't get double exceptions */ 1044 /* Turn caches off, to ensure we don't get double exceptions */
945 1045
946 P4.L = LO(IMEM_CONTROL); 1046 P4.L = LO(IMEM_CONTROL);
@@ -992,7 +1092,12 @@ ENTRY(_ex_table)
992 */ 1092 */
993 .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ 1093 .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */
994 .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ 1094 .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
1095#ifdef CONFIG_KGDB
1096 .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection
1097 and break signal trap */
1098#else
995 .long _ex_replaceable /* 0x02 - User Defined */ 1099 .long _ex_replaceable /* 0x02 - User Defined */
1100#endif
996 .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ 1101 .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */
997 .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ 1102 .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */
998 .long _ex_replaceable /* 0x05 - User Defined */ 1103 .long _ex_replaceable /* 0x05 - User Defined */
@@ -1432,15 +1537,7 @@ ENTRY(_sys_call_table)
1432 .rept NR_syscalls-(.-_sys_call_table)/4 1537 .rept NR_syscalls-(.-_sys_call_table)/4
1433 .long _sys_ni_syscall 1538 .long _sys_ni_syscall
1434 .endr 1539 .endr
1435 1540END(_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 1541
1445_exception_stack: 1542_exception_stack:
1446 .rept 1024 1543 .rept 1024