diff options
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
| -rw-r--r-- | arch/blackfin/mach-common/entry.S | 132 |
1 files changed, 66 insertions, 66 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index bde6dc4e2614..fae774651374 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/linkage.h> | 37 | #include <linux/linkage.h> |
| 38 | #include <linux/unistd.h> | 38 | #include <linux/unistd.h> |
| 39 | #include <linux/threads.h> | ||
| 39 | #include <asm/blackfin.h> | 40 | #include <asm/blackfin.h> |
| 40 | #include <asm/errno.h> | 41 | #include <asm/errno.h> |
| 41 | #include <asm/fixed_code.h> | 42 | #include <asm/fixed_code.h> |
| @@ -75,11 +76,11 @@ ENTRY(_ex_workaround_261) | |||
| 75 | * handle it. | 76 | * handle it. |
| 76 | */ | 77 | */ |
| 77 | P4 = R7; /* Store EXCAUSE */ | 78 | P4 = R7; /* Store EXCAUSE */ |
| 78 | p5.l = _last_cplb_fault_retx; | 79 | |
| 79 | p5.h = _last_cplb_fault_retx; | 80 | GET_PDA(p5, r7); |
| 80 | r7 = [p5]; | 81 | r7 = [p5 + PDA_LFRETX]; |
| 81 | r6 = retx; | 82 | r6 = retx; |
| 82 | [p5] = r6; | 83 | [p5 + PDA_LFRETX] = r6; |
| 83 | cc = r6 == r7; | 84 | cc = r6 == r7; |
| 84 | if !cc jump _bfin_return_from_exception; | 85 | if !cc jump _bfin_return_from_exception; |
| 85 | /* fall through */ | 86 | /* fall through */ |
| @@ -111,24 +112,21 @@ ENTRY(_ex_dcplb_viol) | |||
| 111 | ENTRY(_ex_dcplb_miss) | 112 | ENTRY(_ex_dcplb_miss) |
| 112 | ENTRY(_ex_icplb_miss) | 113 | ENTRY(_ex_icplb_miss) |
| 113 | (R7:6,P5:4) = [sp++]; | 114 | (R7:6,P5:4) = [sp++]; |
| 114 | ASTAT = [sp++]; | 115 | /* We leave the previously pushed ASTAT on the stack. */ |
| 115 | SAVE_ALL_SYS | 116 | SAVE_CONTEXT_CPLB |
| 116 | #ifdef CONFIG_MPU | 117 | |
| 117 | /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that | 118 | /* We must load R1 here, _before_ DEBUG_HWTRACE_SAVE, since that |
| 118 | * will change the stack pointer. */ | 119 | * will change the stack pointer. */ |
| 119 | R0 = SEQSTAT; | 120 | R0 = SEQSTAT; |
| 120 | R1 = SP; | 121 | R1 = SP; |
| 121 | #endif | 122 | |
| 122 | DEBUG_HWTRACE_SAVE(p5, r7) | 123 | DEBUG_HWTRACE_SAVE(p5, r7) |
| 123 | #ifdef CONFIG_MPU | 124 | |
| 124 | sp += -12; | 125 | sp += -12; |
| 125 | call _cplb_hdr; | 126 | call _cplb_hdr; |
| 126 | sp += 12; | 127 | sp += 12; |
| 127 | CC = R0 == 0; | 128 | CC = R0 == 0; |
| 128 | IF !CC JUMP _handle_bad_cplb; | 129 | IF !CC JUMP _handle_bad_cplb; |
| 129 | #else | ||
| 130 | call __cplb_hdr; | ||
| 131 | #endif | ||
| 132 | 130 | ||
| 133 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | 131 | #ifdef CONFIG_DEBUG_DOUBLEFAULT |
| 134 | /* While we were processing this, did we double fault? */ | 132 | /* While we were processing this, did we double fault? */ |
| @@ -142,7 +140,8 @@ ENTRY(_ex_icplb_miss) | |||
| 142 | #endif | 140 | #endif |
| 143 | 141 | ||
| 144 | DEBUG_HWTRACE_RESTORE(p5, r7) | 142 | DEBUG_HWTRACE_RESTORE(p5, r7) |
| 145 | RESTORE_ALL_SYS | 143 | RESTORE_CONTEXT_CPLB |
| 144 | ASTAT = [SP++]; | ||
| 146 | SP = EX_SCRATCH_REG; | 145 | SP = EX_SCRATCH_REG; |
| 147 | rtx; | 146 | rtx; |
| 148 | ENDPROC(_ex_icplb_miss) | 147 | ENDPROC(_ex_icplb_miss) |
| @@ -297,9 +296,8 @@ ENTRY(_handle_bad_cplb) | |||
| 297 | * the stack to get ready so, we can fall through - we | 296 | * the stack to get ready so, we can fall through - we |
| 298 | * need to make a CPLB exception look like a normal exception | 297 | * need to make a CPLB exception look like a normal exception |
| 299 | */ | 298 | */ |
| 300 | 299 | RESTORE_CONTEXT_CPLB | |
| 301 | RESTORE_ALL_SYS | 300 | /* ASTAT is still on the stack, where it is needed. */ |
| 302 | [--sp] = ASTAT; | ||
| 303 | [--sp] = (R7:6,P5:4); | 301 | [--sp] = (R7:6,P5:4); |
| 304 | 302 | ||
| 305 | ENTRY(_ex_replaceable) | 303 | ENTRY(_ex_replaceable) |
| @@ -324,7 +322,9 @@ ENTRY(_ex_trap_c) | |||
| 324 | [p4] = p5; | 322 | [p4] = p5; |
| 325 | csync; | 323 | csync; |
| 326 | 324 | ||
| 325 | GET_PDA(p5, r6); | ||
| 327 | #ifndef CONFIG_DEBUG_DOUBLEFAULT | 326 | #ifndef CONFIG_DEBUG_DOUBLEFAULT |
| 327 | |||
| 328 | /* | 328 | /* |
| 329 | * Save these registers, as they are only valid in exception context | 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) | 330 | * (where we are now - as soon as we defer to IRQ5, they can change) |
| @@ -335,29 +335,25 @@ ENTRY(_ex_trap_c) | |||
| 335 | p4.l = lo(DCPLB_FAULT_ADDR); | 335 | p4.l = lo(DCPLB_FAULT_ADDR); |
| 336 | p4.h = hi(DCPLB_FAULT_ADDR); | 336 | p4.h = hi(DCPLB_FAULT_ADDR); |
| 337 | r7 = [p4]; | 337 | r7 = [p4]; |
| 338 | p5.h = _saved_dcplb_fault_addr; | 338 | [p5 + PDA_DCPLB] = r7; |
| 339 | p5.l = _saved_dcplb_fault_addr; | ||
| 340 | [p5] = r7; | ||
| 341 | 339 | ||
| 342 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | 340 | p4.l = lo(ICPLB_FAULT_ADDR); |
| 343 | p5.h = _saved_icplb_fault_addr; | 341 | p4.h = hi(ICPLB_FAULT_ADDR); |
| 344 | p5.l = _saved_icplb_fault_addr; | 342 | r6 = [p4]; |
| 345 | [p5] = r7; | 343 | [p5 + PDA_ICPLB] = r6; |
| 346 | 344 | ||
| 347 | r6 = retx; | 345 | r6 = retx; |
| 348 | p4.l = _saved_retx; | 346 | [p5 + PDA_RETX] = r6; |
| 349 | p4.h = _saved_retx; | ||
| 350 | [p4] = r6; | ||
| 351 | #endif | 347 | #endif |
| 352 | r6 = SYSCFG; | 348 | r6 = SYSCFG; |
| 353 | [p4 + 4] = r6; | 349 | [p5 + PDA_SYSCFG] = r6; |
| 354 | BITCLR(r6, 0); | 350 | BITCLR(r6, 0); |
| 355 | SYSCFG = r6; | 351 | SYSCFG = r6; |
| 356 | 352 | ||
| 357 | /* Disable all interrupts, but make sure level 5 is enabled so | 353 | /* Disable all interrupts, but make sure level 5 is enabled so |
| 358 | * we can switch to that level. Save the old mask. */ | 354 | * we can switch to that level. Save the old mask. */ |
| 359 | cli r6; | 355 | cli r6; |
| 360 | [p4 + 8] = r6; | 356 | [p5 + PDA_EXIMASK] = r6; |
| 361 | 357 | ||
| 362 | p4.l = lo(SAFE_USER_INSTRUCTION); | 358 | p4.l = lo(SAFE_USER_INSTRUCTION); |
| 363 | p4.h = hi(SAFE_USER_INSTRUCTION); | 359 | p4.h = hi(SAFE_USER_INSTRUCTION); |
| @@ -371,9 +367,10 @@ ENTRY(_ex_trap_c) | |||
| 371 | ENDPROC(_ex_trap_c) | 367 | ENDPROC(_ex_trap_c) |
| 372 | 368 | ||
| 373 | /* We just realized we got an exception, while we were processing a different | 369 | /* We just realized we got an exception, while we were processing a different |
| 374 | * exception. This is a unrecoverable event, so crash | 370 | * exception. This is a unrecoverable event, so crash. |
| 371 | * Note: this cannot be ENTRY() as we jump here with "if cc jump" ... | ||
| 375 | */ | 372 | */ |
| 376 | ENTRY(_double_fault) | 373 | _double_fault: |
| 377 | /* Turn caches & protection off, to ensure we don't get any more | 374 | /* Turn caches & protection off, to ensure we don't get any more |
| 378 | * double exceptions | 375 | * double exceptions |
| 379 | */ | 376 | */ |
| @@ -424,17 +421,16 @@ ENDPROC(_double_fault) | |||
| 424 | ENTRY(_exception_to_level5) | 421 | ENTRY(_exception_to_level5) |
| 425 | SAVE_ALL_SYS | 422 | SAVE_ALL_SYS |
| 426 | 423 | ||
| 427 | p4.l = _saved_retx; | 424 | GET_PDA(p4, r7); /* Fetch current PDA */ |
| 428 | p4.h = _saved_retx; | 425 | r6 = [p4 + PDA_RETX]; |
| 429 | r6 = [p4]; | ||
| 430 | [sp + PT_PC] = r6; | 426 | [sp + PT_PC] = r6; |
| 431 | 427 | ||
| 432 | r6 = [p4 + 4]; | 428 | r6 = [p4 + PDA_SYSCFG]; |
| 433 | [sp + PT_SYSCFG] = r6; | 429 | [sp + PT_SYSCFG] = r6; |
| 434 | 430 | ||
| 435 | /* Restore interrupt mask. We haven't pushed RETI, so this | 431 | /* Restore interrupt mask. We haven't pushed RETI, so this |
| 436 | * doesn't enable interrupts until we return from this handler. */ | 432 | * doesn't enable interrupts until we return from this handler. */ |
| 437 | r6 = [p4 + 8]; | 433 | r6 = [p4 + PDA_EXIMASK]; |
| 438 | sti r6; | 434 | sti r6; |
| 439 | 435 | ||
| 440 | /* Restore the hardware error vector. */ | 436 | /* Restore the hardware error vector. */ |
| @@ -478,8 +474,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
| 478 | * scratch register (for want of a better option). | 474 | * scratch register (for want of a better option). |
| 479 | */ | 475 | */ |
| 480 | EX_SCRATCH_REG = sp; | 476 | EX_SCRATCH_REG = sp; |
| 481 | sp.l = _exception_stack_top; | 477 | GET_PDA_SAFE(sp); |
| 482 | sp.h = _exception_stack_top; | 478 | sp = [sp + PDA_EXSTACK] |
| 483 | /* Try to deal with syscalls quickly. */ | 479 | /* Try to deal with syscalls quickly. */ |
| 484 | [--sp] = ASTAT; | 480 | [--sp] = ASTAT; |
| 485 | [--sp] = (R7:6,P5:4); | 481 | [--sp] = (R7:6,P5:4); |
| @@ -501,27 +497,22 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
| 501 | * but they are not very interesting, so don't save them | 497 | * but they are not very interesting, so don't save them |
| 502 | */ | 498 | */ |
| 503 | 499 | ||
| 500 | GET_PDA(p5, r7); | ||
| 504 | p4.l = lo(DCPLB_FAULT_ADDR); | 501 | p4.l = lo(DCPLB_FAULT_ADDR); |
| 505 | p4.h = hi(DCPLB_FAULT_ADDR); | 502 | p4.h = hi(DCPLB_FAULT_ADDR); |
| 506 | r7 = [p4]; | 503 | r7 = [p4]; |
| 507 | p5.h = _saved_dcplb_fault_addr; | 504 | [p5 + PDA_DCPLB] = r7; |
| 508 | p5.l = _saved_dcplb_fault_addr; | ||
| 509 | [p5] = r7; | ||
| 510 | 505 | ||
| 511 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | 506 | p4.l = lo(ICPLB_FAULT_ADDR); |
| 512 | p5.h = _saved_icplb_fault_addr; | 507 | p4.h = hi(ICPLB_FAULT_ADDR); |
| 513 | p5.l = _saved_icplb_fault_addr; | 508 | r7 = [p4]; |
| 514 | [p5] = r7; | 509 | [p5 + PDA_ICPLB] = r7; |
| 515 | 510 | ||
| 516 | p4.l = _saved_retx; | ||
| 517 | p4.h = _saved_retx; | ||
| 518 | r6 = retx; | 511 | r6 = retx; |
| 519 | [p4] = r6; | 512 | [p5 + PDA_RETX] = r6; |
| 520 | 513 | ||
| 521 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 514 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
| 522 | p4.l = _saved_seqstat; | 515 | [p5 + PDA_SEQSTAT] = r7; |
| 523 | p4.h = _saved_seqstat; | ||
| 524 | [p4] = r7; | ||
| 525 | #else | 516 | #else |
| 526 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 517 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
| 527 | #endif | 518 | #endif |
| @@ -546,11 +537,11 @@ ENTRY(_kernel_execve) | |||
| 546 | p0 = sp; | 537 | p0 = sp; |
| 547 | r3 = SIZEOF_PTREGS / 4; | 538 | r3 = SIZEOF_PTREGS / 4; |
| 548 | r4 = 0(x); | 539 | r4 = 0(x); |
| 549 | 0: | 540 | .Lclear_regs: |
| 550 | [p0++] = r4; | 541 | [p0++] = r4; |
| 551 | r3 += -1; | 542 | r3 += -1; |
| 552 | cc = r3 == 0; | 543 | cc = r3 == 0; |
| 553 | if !cc jump 0b (bp); | 544 | if !cc jump .Lclear_regs (bp); |
| 554 | 545 | ||
| 555 | p0 = sp; | 546 | p0 = sp; |
| 556 | sp += -16; | 547 | sp += -16; |
| @@ -558,7 +549,7 @@ ENTRY(_kernel_execve) | |||
| 558 | call _do_execve; | 549 | call _do_execve; |
| 559 | SP += 16; | 550 | SP += 16; |
| 560 | cc = r0 == 0; | 551 | cc = r0 == 0; |
| 561 | if ! cc jump 1f; | 552 | if ! cc jump .Lexecve_failed; |
| 562 | /* Success. Copy our temporary pt_regs to the top of the kernel | 553 | /* Success. Copy our temporary pt_regs to the top of the kernel |
| 563 | * stack and do a normal exception return. | 554 | * stack and do a normal exception return. |
| 564 | */ | 555 | */ |
| @@ -574,12 +565,12 @@ ENTRY(_kernel_execve) | |||
| 574 | p0 = fp; | 565 | p0 = fp; |
| 575 | r4 = [p0--]; | 566 | r4 = [p0--]; |
| 576 | r3 = SIZEOF_PTREGS / 4; | 567 | r3 = SIZEOF_PTREGS / 4; |
| 577 | 0: | 568 | .Lcopy_regs: |
| 578 | r4 = [p0--]; | 569 | r4 = [p0--]; |
| 579 | [p1--] = r4; | 570 | [p1--] = r4; |
| 580 | r3 += -1; | 571 | r3 += -1; |
| 581 | cc = r3 == 0; | 572 | cc = r3 == 0; |
| 582 | if ! cc jump 0b (bp); | 573 | if ! cc jump .Lcopy_regs (bp); |
| 583 | 574 | ||
| 584 | r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); | 575 | r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); |
| 585 | p1 = r0; | 576 | p1 = r0; |
| @@ -591,7 +582,7 @@ ENTRY(_kernel_execve) | |||
| 591 | 582 | ||
| 592 | RESTORE_CONTEXT; | 583 | RESTORE_CONTEXT; |
| 593 | rti; | 584 | rti; |
| 594 | 1: | 585 | .Lexecve_failed: |
| 595 | unlink; | 586 | unlink; |
| 596 | rts; | 587 | rts; |
| 597 | ENDPROC(_kernel_execve) | 588 | ENDPROC(_kernel_execve) |
| @@ -925,9 +916,14 @@ _schedule_and_signal_from_int: | |||
| 925 | p1 = rets; | 916 | p1 = rets; |
| 926 | [sp + PT_RESERVED] = p1; | 917 | [sp + PT_RESERVED] = p1; |
| 927 | 918 | ||
| 928 | p0.l = _irq_flags; | 919 | #ifdef CONFIG_SMP |
| 929 | p0.h = _irq_flags; | 920 | GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */ |
| 921 | r0 = [p0 + PDA_IRQFLAGS]; | ||
| 922 | #else | ||
| 923 | p0.l = _bfin_irq_flags; | ||
| 924 | p0.h = _bfin_irq_flags; | ||
| 930 | r0 = [p0]; | 925 | r0 = [p0]; |
| 926 | #endif | ||
| 931 | sti r0; | 927 | sti r0; |
| 932 | 928 | ||
| 933 | r0 = sp; | 929 | r0 = sp; |
| @@ -1539,14 +1535,18 @@ ENTRY(_sys_call_table) | |||
| 1539 | .endr | 1535 | .endr |
| 1540 | END(_sys_call_table) | 1536 | END(_sys_call_table) |
| 1541 | 1537 | ||
| 1542 | _exception_stack: | 1538 | #ifdef CONFIG_EXCEPTION_L1_SCRATCH |
| 1543 | .rept 1024 | 1539 | /* .section .l1.bss.scratch */ |
| 1544 | .long 0; | 1540 | .set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH |
| 1541 | #else | ||
| 1542 | #ifdef CONFIG_SYSCALL_TAB_L1 | ||
| 1543 | .section .l1.bss | ||
| 1544 | #else | ||
| 1545 | .bss | ||
| 1546 | #endif | ||
| 1547 | ENTRY(_exception_stack) | ||
| 1548 | .rept 1024 * NR_CPUS | ||
| 1549 | .long 0 | ||
| 1545 | .endr | 1550 | .endr |
| 1546 | _exception_stack_top: | 1551 | _exception_stack_top: |
| 1547 | |||
| 1548 | #if ANOMALY_05000261 | ||
| 1549 | /* Used by the assembly entry point to work around an anomaly. */ | ||
| 1550 | _last_cplb_fault_retx: | ||
| 1551 | .long 0; | ||
| 1552 | #endif | 1552 | #endif |
