diff options
author | Graf Yang <graf.yang@analog.com> | 2009-01-07 10:14:39 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2009-01-07 10:14:39 -0500 |
commit | 6b3087c64a92a36ae20d33479b4df6d7afc910d4 (patch) | |
tree | 95984fc623658ebf150d0d912a7f6c5a0301a5a9 /arch/blackfin/mach-common/entry.S | |
parent | c51b4488cd5bff08ed5690a8f303ff7f0894da2a (diff) |
Blackfin arch: SMP supporting patchset: Blackfin header files and machine common code
Blackfin dual core BF561 processor can support SMP like features.
https://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:smp-like
In this patch, we provide SMP extend to Blackfin header files
and machine common code
Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 92 |
1 files changed, 42 insertions, 50 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index c6ae8442fc4e..5531f49c84e6 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 */ |
@@ -324,7 +325,9 @@ ENTRY(_ex_trap_c) | |||
324 | [p4] = p5; | 325 | [p4] = p5; |
325 | csync; | 326 | csync; |
326 | 327 | ||
328 | GET_PDA(p5, r6); | ||
327 | #ifndef CONFIG_DEBUG_DOUBLEFAULT | 329 | #ifndef CONFIG_DEBUG_DOUBLEFAULT |
330 | |||
328 | /* | 331 | /* |
329 | * Save these registers, as they are only valid in exception context | 332 | * 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) | 333 | * (where we are now - as soon as we defer to IRQ5, they can change) |
@@ -335,29 +338,25 @@ ENTRY(_ex_trap_c) | |||
335 | p4.l = lo(DCPLB_FAULT_ADDR); | 338 | p4.l = lo(DCPLB_FAULT_ADDR); |
336 | p4.h = hi(DCPLB_FAULT_ADDR); | 339 | p4.h = hi(DCPLB_FAULT_ADDR); |
337 | r7 = [p4]; | 340 | r7 = [p4]; |
338 | p5.h = _saved_dcplb_fault_addr; | 341 | [p5 + PDA_DCPLB] = r7; |
339 | p5.l = _saved_dcplb_fault_addr; | ||
340 | [p5] = r7; | ||
341 | 342 | ||
342 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | 343 | p4.l = lo(ICPLB_FAULT_ADDR); |
343 | p5.h = _saved_icplb_fault_addr; | 344 | p4.h = hi(ICPLB_FAULT_ADDR); |
344 | p5.l = _saved_icplb_fault_addr; | 345 | r6 = [p4]; |
345 | [p5] = r7; | 346 | [p5 + PDA_ICPLB] = r6; |
346 | 347 | ||
347 | r6 = retx; | 348 | r6 = retx; |
348 | p4.l = _saved_retx; | 349 | [p5 + PDA_RETX] = r6; |
349 | p4.h = _saved_retx; | ||
350 | [p4] = r6; | ||
351 | #endif | 350 | #endif |
352 | r6 = SYSCFG; | 351 | r6 = SYSCFG; |
353 | [p4 + 4] = r6; | 352 | [p5 + PDA_SYSCFG] = r6; |
354 | BITCLR(r6, 0); | 353 | BITCLR(r6, 0); |
355 | SYSCFG = r6; | 354 | SYSCFG = r6; |
356 | 355 | ||
357 | /* Disable all interrupts, but make sure level 5 is enabled so | 356 | /* Disable all interrupts, but make sure level 5 is enabled so |
358 | * we can switch to that level. Save the old mask. */ | 357 | * we can switch to that level. Save the old mask. */ |
359 | cli r6; | 358 | cli r6; |
360 | [p4 + 8] = r6; | 359 | [p5 + PDA_EXIMASK] = r6; |
361 | 360 | ||
362 | p4.l = lo(SAFE_USER_INSTRUCTION); | 361 | p4.l = lo(SAFE_USER_INSTRUCTION); |
363 | p4.h = hi(SAFE_USER_INSTRUCTION); | 362 | p4.h = hi(SAFE_USER_INSTRUCTION); |
@@ -424,17 +423,16 @@ ENDPROC(_double_fault) | |||
424 | ENTRY(_exception_to_level5) | 423 | ENTRY(_exception_to_level5) |
425 | SAVE_ALL_SYS | 424 | SAVE_ALL_SYS |
426 | 425 | ||
427 | p4.l = _saved_retx; | 426 | GET_PDA(p4, r7); /* Fetch current PDA */ |
428 | p4.h = _saved_retx; | 427 | r6 = [p4 + PDA_RETX]; |
429 | r6 = [p4]; | ||
430 | [sp + PT_PC] = r6; | 428 | [sp + PT_PC] = r6; |
431 | 429 | ||
432 | r6 = [p4 + 4]; | 430 | r6 = [p4 + PDA_SYSCFG]; |
433 | [sp + PT_SYSCFG] = r6; | 431 | [sp + PT_SYSCFG] = r6; |
434 | 432 | ||
435 | /* Restore interrupt mask. We haven't pushed RETI, so this | 433 | /* Restore interrupt mask. We haven't pushed RETI, so this |
436 | * doesn't enable interrupts until we return from this handler. */ | 434 | * doesn't enable interrupts until we return from this handler. */ |
437 | r6 = [p4 + 8]; | 435 | r6 = [p4 + PDA_EXIMASK]; |
438 | sti r6; | 436 | sti r6; |
439 | 437 | ||
440 | /* Restore the hardware error vector. */ | 438 | /* Restore the hardware error vector. */ |
@@ -478,8 +476,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
478 | * scratch register (for want of a better option). | 476 | * scratch register (for want of a better option). |
479 | */ | 477 | */ |
480 | EX_SCRATCH_REG = sp; | 478 | EX_SCRATCH_REG = sp; |
481 | sp.l = _exception_stack_top; | 479 | GET_PDA_SAFE(sp); |
482 | sp.h = _exception_stack_top; | 480 | sp = [sp + PDA_EXSTACK] |
483 | /* Try to deal with syscalls quickly. */ | 481 | /* Try to deal with syscalls quickly. */ |
484 | [--sp] = ASTAT; | 482 | [--sp] = ASTAT; |
485 | [--sp] = (R7:6,P5:4); | 483 | [--sp] = (R7:6,P5:4); |
@@ -501,27 +499,22 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
501 | * but they are not very interesting, so don't save them | 499 | * but they are not very interesting, so don't save them |
502 | */ | 500 | */ |
503 | 501 | ||
502 | GET_PDA(p5, r7); | ||
504 | p4.l = lo(DCPLB_FAULT_ADDR); | 503 | p4.l = lo(DCPLB_FAULT_ADDR); |
505 | p4.h = hi(DCPLB_FAULT_ADDR); | 504 | p4.h = hi(DCPLB_FAULT_ADDR); |
506 | r7 = [p4]; | 505 | r7 = [p4]; |
507 | p5.h = _saved_dcplb_fault_addr; | 506 | [p5 + PDA_DCPLB] = r7; |
508 | p5.l = _saved_dcplb_fault_addr; | ||
509 | [p5] = r7; | ||
510 | 507 | ||
511 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | 508 | p4.l = lo(ICPLB_FAULT_ADDR); |
512 | p5.h = _saved_icplb_fault_addr; | 509 | p4.h = hi(ICPLB_FAULT_ADDR); |
513 | p5.l = _saved_icplb_fault_addr; | 510 | r7 = [p4]; |
514 | [p5] = r7; | 511 | [p5 + PDA_ICPLB] = r7; |
515 | 512 | ||
516 | p4.l = _saved_retx; | ||
517 | p4.h = _saved_retx; | ||
518 | r6 = retx; | 513 | r6 = retx; |
519 | [p4] = r6; | 514 | [p5 + PDA_RETX] = r6; |
520 | 515 | ||
521 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 516 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
522 | p4.l = _saved_seqstat; | 517 | [p5 + PDA_SEQSTAT] = r7; |
523 | p4.h = _saved_seqstat; | ||
524 | [p4] = r7; | ||
525 | #else | 518 | #else |
526 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 519 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
527 | #endif | 520 | #endif |
@@ -546,11 +539,11 @@ ENTRY(_kernel_execve) | |||
546 | p0 = sp; | 539 | p0 = sp; |
547 | r3 = SIZEOF_PTREGS / 4; | 540 | r3 = SIZEOF_PTREGS / 4; |
548 | r4 = 0(x); | 541 | r4 = 0(x); |
549 | 0: | 542 | .Lclear_regs: |
550 | [p0++] = r4; | 543 | [p0++] = r4; |
551 | r3 += -1; | 544 | r3 += -1; |
552 | cc = r3 == 0; | 545 | cc = r3 == 0; |
553 | if !cc jump 0b (bp); | 546 | if !cc jump .Lclear_regs (bp); |
554 | 547 | ||
555 | p0 = sp; | 548 | p0 = sp; |
556 | sp += -16; | 549 | sp += -16; |
@@ -558,7 +551,7 @@ ENTRY(_kernel_execve) | |||
558 | call _do_execve; | 551 | call _do_execve; |
559 | SP += 16; | 552 | SP += 16; |
560 | cc = r0 == 0; | 553 | cc = r0 == 0; |
561 | if ! cc jump 1f; | 554 | if ! cc jump .Lexecve_failed; |
562 | /* Success. Copy our temporary pt_regs to the top of the kernel | 555 | /* Success. Copy our temporary pt_regs to the top of the kernel |
563 | * stack and do a normal exception return. | 556 | * stack and do a normal exception return. |
564 | */ | 557 | */ |
@@ -574,12 +567,12 @@ ENTRY(_kernel_execve) | |||
574 | p0 = fp; | 567 | p0 = fp; |
575 | r4 = [p0--]; | 568 | r4 = [p0--]; |
576 | r3 = SIZEOF_PTREGS / 4; | 569 | r3 = SIZEOF_PTREGS / 4; |
577 | 0: | 570 | .Lcopy_regs: |
578 | r4 = [p0--]; | 571 | r4 = [p0--]; |
579 | [p1--] = r4; | 572 | [p1--] = r4; |
580 | r3 += -1; | 573 | r3 += -1; |
581 | cc = r3 == 0; | 574 | cc = r3 == 0; |
582 | if ! cc jump 0b (bp); | 575 | if ! cc jump .Lcopy_regs (bp); |
583 | 576 | ||
584 | r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); | 577 | r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z); |
585 | p1 = r0; | 578 | p1 = r0; |
@@ -591,7 +584,7 @@ ENTRY(_kernel_execve) | |||
591 | 584 | ||
592 | RESTORE_CONTEXT; | 585 | RESTORE_CONTEXT; |
593 | rti; | 586 | rti; |
594 | 1: | 587 | .Lexecve_failed: |
595 | unlink; | 588 | unlink; |
596 | rts; | 589 | rts; |
597 | ENDPROC(_kernel_execve) | 590 | ENDPROC(_kernel_execve) |
@@ -925,9 +918,14 @@ _schedule_and_signal_from_int: | |||
925 | p1 = rets; | 918 | p1 = rets; |
926 | [sp + PT_RESERVED] = p1; | 919 | [sp + PT_RESERVED] = p1; |
927 | 920 | ||
921 | #ifdef CONFIG_SMP | ||
922 | GET_PDA(p0, r0); /* Fetch current PDA (can't migrate to other CPU here) */ | ||
923 | r0 = [p0 + PDA_IRQFLAGS]; | ||
924 | #else | ||
928 | p0.l = _irq_flags; | 925 | p0.l = _irq_flags; |
929 | p0.h = _irq_flags; | 926 | p0.h = _irq_flags; |
930 | r0 = [p0]; | 927 | r0 = [p0]; |
928 | #endif | ||
931 | sti r0; | 929 | sti r0; |
932 | 930 | ||
933 | r0 = sp; | 931 | r0 = sp; |
@@ -1539,12 +1537,6 @@ ENTRY(_sys_call_table) | |||
1539 | .endr | 1537 | .endr |
1540 | END(_sys_call_table) | 1538 | END(_sys_call_table) |
1541 | 1539 | ||
1542 | #if ANOMALY_05000261 | ||
1543 | /* Used by the assembly entry point to work around an anomaly. */ | ||
1544 | _last_cplb_fault_retx: | ||
1545 | .long 0; | ||
1546 | #endif | ||
1547 | |||
1548 | #ifdef CONFIG_EXCEPTION_L1_SCRATCH | 1540 | #ifdef CONFIG_EXCEPTION_L1_SCRATCH |
1549 | /* .section .l1.bss.scratch */ | 1541 | /* .section .l1.bss.scratch */ |
1550 | .set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH | 1542 | .set _exception_stack_top, L1_SCRATCH_START + L1_SCRATCH_LENGTH |
@@ -1554,8 +1546,8 @@ _last_cplb_fault_retx: | |||
1554 | #else | 1546 | #else |
1555 | .bss | 1547 | .bss |
1556 | #endif | 1548 | #endif |
1557 | _exception_stack: | 1549 | ENTRY(_exception_stack) |
1558 | .rept 1024 | 1550 | .rept 1024 * NR_CPUS |
1559 | .long 0 | 1551 | .long 0 |
1560 | .endr | 1552 | .endr |
1561 | _exception_stack_top: | 1553 | _exception_stack_top: |