diff options
Diffstat (limited to 'arch/microblaze/kernel/entry.S')
-rw-r--r-- | arch/microblaze/kernel/entry.S | 106 |
1 files changed, 57 insertions, 49 deletions
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 5a5cb5842938..304882e56459 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
@@ -745,11 +745,8 @@ IRQ_return: /* MS: Make global symbol for debugging */ | |||
745 | nop | 745 | nop |
746 | 746 | ||
747 | /* | 747 | /* |
748 | * `Debug' trap | 748 | * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18 |
749 | * We enter dbtrap in "BIP" (breakpoint) mode. | 749 | * and call handling function with saved pt_regs |
750 | * So we exit the breakpoint mode with an 'rtbd' and proceed with the | ||
751 | * original dbtrap. | ||
752 | * however, wait to save state first | ||
753 | */ | 750 | */ |
754 | C_ENTRY(_debug_exception): | 751 | C_ENTRY(_debug_exception): |
755 | /* BIP bit is set on entry, no interrupts can occur */ | 752 | /* BIP bit is set on entry, no interrupts can occur */ |
@@ -759,18 +756,44 @@ C_ENTRY(_debug_exception): | |||
759 | nop | 756 | nop |
760 | andi r1, r1, MSR_UMS | 757 | andi r1, r1, MSR_UMS |
761 | bnei r1, 1f | 758 | bnei r1, 1f |
762 | /* Kernel-mode state save. */ | 759 | /* MS: Kernel-mode state save - kgdb */ |
763 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ | 760 | lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ |
764 | tophys(r1,r1); | ||
765 | 761 | ||
766 | addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ | 762 | /* BIP bit is set on entry, no interrupts can occur */ |
763 | addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; | ||
767 | SAVE_REGS; | 764 | SAVE_REGS; |
765 | /* save all regs to pt_reg structure */ | ||
766 | swi r0, r1, PTO+PT_R0; /* R0 must be saved too */ | ||
767 | swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */ | ||
768 | swi r16, r1, PTO+PT_R16 | ||
769 | swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */ | ||
770 | swi r17, r1, PTO+PT_R17 | ||
771 | /* save special purpose registers to pt_regs */ | ||
772 | mfs r11, rear; | ||
773 | swi r11, r1, PTO+PT_EAR; | ||
774 | mfs r11, resr; | ||
775 | swi r11, r1, PTO+PT_ESR; | ||
776 | mfs r11, rfsr; | ||
777 | swi r11, r1, PTO+PT_FSR; | ||
778 | |||
779 | /* stack pointer is in physical address at it is decrease | ||
780 | * by STATE_SAVE_SIZE but we need to get correct R1 value */ | ||
781 | addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE; | ||
782 | swi r11, r1, PTO+PT_R1 | ||
783 | /* MS: r31 - current pointer isn't changed */ | ||
784 | tovirt(r1,r1) | ||
785 | #ifdef CONFIG_KGDB | ||
786 | addi r5, r1, PTO /* pass pt_reg address as the first arg */ | ||
787 | la r15, r0, dbtrap_call; /* return address */ | ||
788 | rtbd r0, microblaze_kgdb_break | ||
789 | nop; | ||
790 | #endif | ||
791 | /* MS: Place handler for brki from kernel space if KGDB is OFF. | ||
792 | * It is very unlikely that another brki instruction is called. */ | ||
793 | bri 0 | ||
768 | 794 | ||
769 | swi r1, r1, PTO + PT_MODE; | 795 | /* MS: User-mode state save - gdb */ |
770 | brid 2f; | 796 | 1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ |
771 | nop; /* Fill delay slot */ | ||
772 | 1: /* User-mode state save. */ | ||
773 | lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ | ||
774 | tophys(r1,r1); | 797 | tophys(r1,r1); |
775 | lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ | 798 | lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ |
776 | addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ | 799 | addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ |
@@ -781,36 +804,32 @@ C_ENTRY(_debug_exception): | |||
781 | swi r17, r1, PTO+PT_R17; | 804 | swi r17, r1, PTO+PT_R17; |
782 | swi r16, r1, PTO+PT_R16; | 805 | swi r16, r1, PTO+PT_R16; |
783 | swi r16, r1, PTO+PT_PC; /* Save LP */ | 806 | swi r16, r1, PTO+PT_PC; /* Save LP */ |
784 | |||
785 | swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ | 807 | swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ |
786 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); | 808 | lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); |
787 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ | 809 | swi r11, r1, PTO+PT_R1; /* Store user SP. */ |
788 | 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); | 810 | lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); |
789 | tovirt(r1,r1) | 811 | tovirt(r1,r1) |
790 | |||
791 | set_vms; | 812 | set_vms; |
792 | addik r5, r1, PTO; | 813 | addik r5, r1, PTO; |
793 | addik r15, r0, dbtrap_call; | 814 | addik r15, r0, dbtrap_call; |
794 | dbtrap_call: /* return point for kernel/user entry */ | 815 | dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ |
795 | rtbd r0, sw_exception | 816 | rtbd r0, sw_exception |
796 | nop | 817 | nop |
797 | 818 | ||
798 | set_bip; /* Ints masked for state restore*/ | 819 | /* MS: The first instruction for the second part of the gdb/kgdb */ |
820 | set_bip; /* Ints masked for state restore */ | ||
799 | lwi r11, r1, PTO + PT_MODE; | 821 | lwi r11, r1, PTO + PT_MODE; |
800 | bnei r11, 2f; | 822 | bnei r11, 2f; |
801 | 823 | /* MS: Return to user space - gdb */ | |
802 | /* Get current task ptr into r11 */ | 824 | /* Get current task ptr into r11 */ |
803 | lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ | 825 | lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ |
804 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ | 826 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ |
805 | andi r11, r11, _TIF_NEED_RESCHED; | 827 | andi r11, r11, _TIF_NEED_RESCHED; |
806 | beqi r11, 5f; | 828 | beqi r11, 5f; |
807 | 829 | ||
808 | /* Call the scheduler before returning from a syscall/trap. */ | 830 | /* Call the scheduler before returning from a syscall/trap. */ |
809 | |||
810 | bralid r15, schedule; /* Call scheduler */ | 831 | bralid r15, schedule; /* Call scheduler */ |
811 | nop; /* delay slot */ | 832 | nop; /* delay slot */ |
812 | /* XXX Is PT_DTRACE handling needed here? */ | ||
813 | /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here. */ | ||
814 | 833 | ||
815 | /* Maybe handle a signal */ | 834 | /* Maybe handle a signal */ |
816 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ | 835 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ |
@@ -818,48 +837,37 @@ dbtrap_call: /* return point for kernel/user entry */ | |||
818 | andi r11, r11, _TIF_SIGPENDING; | 837 | andi r11, r11, _TIF_SIGPENDING; |
819 | beqi r11, 1f; /* Signals to handle, handle them */ | 838 | beqi r11, 1f; /* Signals to handle, handle them */ |
820 | 839 | ||
821 | /* Handle a signal return; Pending signals should be in r18. */ | ||
822 | /* Not all registers are saved by the normal trap/interrupt entry | ||
823 | points (for instance, call-saved registers (because the normal | ||
824 | C-compiler calling sequence in the kernel makes sure they're | ||
825 | preserved), and call-clobbered registers in the case of | ||
826 | traps), but signal handlers may want to examine or change the | ||
827 | complete register state. Here we save anything not saved by | ||
828 | the normal entry sequence, so that it may be safely restored | ||
829 | (in a possibly modified form) after do_signal returns. */ | ||
830 | |||
831 | addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ | 840 | addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ |
832 | addi r7, r0, 0; /* Arg 3: int in_syscall */ | 841 | addi r7, r0, 0; /* Arg 3: int in_syscall */ |
833 | bralid r15, do_signal; /* Handle any signals */ | 842 | bralid r15, do_signal; /* Handle any signals */ |
834 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | 843 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ |
835 | 844 | ||
836 | |||
837 | /* Finally, return to user state. */ | 845 | /* Finally, return to user state. */ |
838 | 1: | 846 | 1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ |
839 | swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ | ||
840 | VM_OFF; | 847 | VM_OFF; |
841 | tophys(r1,r1); | 848 | tophys(r1,r1); |
842 | 849 | /* MS: Restore all regs */ | |
843 | RESTORE_REGS | 850 | RESTORE_REGS |
844 | lwi r17, r1, PTO+PT_R17; | 851 | lwi r17, r1, PTO+PT_R17; |
845 | lwi r16, r1, PTO+PT_R16; | 852 | lwi r16, r1, PTO+PT_R16; |
846 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ | 853 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space */ |
847 | 854 | lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */ | |
848 | 855 | DBTRAP_return_user: /* MS: Make global symbol for debugging */ | |
849 | lwi r1, r1, PT_R1 - PT_SIZE; | 856 | rtbd r16, 0; /* MS: Instructions to return from a debug trap */ |
850 | /* Restore user stack pointer. */ | 857 | nop; |
851 | bri 6f; | ||
852 | 858 | ||
853 | /* Return to kernel state. */ | 859 | /* MS: Return to kernel state - kgdb */ |
854 | 2: VM_OFF; | 860 | 2: VM_OFF; |
855 | tophys(r1,r1); | 861 | tophys(r1,r1); |
862 | /* MS: Restore all regs */ | ||
856 | RESTORE_REGS | 863 | RESTORE_REGS |
857 | addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ | 864 | lwi r14, r1, PTO+PT_R14; |
858 | 865 | lwi r16, r1, PTO+PT_PC; | |
866 | lwi r17, r1, PTO+PT_R17; | ||
867 | addik r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */ | ||
859 | tovirt(r1,r1); | 868 | tovirt(r1,r1); |
860 | 6: | 869 | DBTRAP_return_kernel: /* MS: Make global symbol for debugging */ |
861 | DBTRAP_return: /* Make global symbol for debugging */ | 870 | rtbd r16, 0; /* MS: Instructions to return from a debug trap */ |
862 | rtbd r16, 0; /* Instructions to return from an IRQ */ | ||
863 | nop; | 871 | nop; |
864 | 872 | ||
865 | 873 | ||