X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=arch%2Fmicroblaze%2Fkernel%2Fentry.S;h=e7abf7426c8cbe122e497db9e78b11468cb089b8;hb=287503fabd9910cc77266142c7c8acbdb8efbf6b;hp=c0ede25c5b99ec305abd4d97fa774d249b36fda0;hpb=18e41da89d55014d25b9a24502ee92b7f50599f9;p=mv-sheeva.git diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index c0ede25c5b9..e7abf7426c8 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S @@ -48,53 +48,56 @@ */ #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR .macro clear_bip - msrclr r11, MSR_BIP + msrclr r0, MSR_BIP nop .endm .macro set_bip - msrset r11, MSR_BIP + msrset r0, MSR_BIP nop .endm .macro clear_eip - msrclr r11, MSR_EIP + msrclr r0, MSR_EIP nop .endm .macro set_ee - msrset r11, MSR_EE + msrset r0, MSR_EE nop .endm .macro disable_irq - msrclr r11, MSR_IE + msrclr r0, MSR_IE nop .endm .macro enable_irq - msrset r11, MSR_IE + msrset r0, MSR_IE nop .endm .macro set_ums - msrset r11, MSR_UMS + msrset r0, MSR_UMS nop - msrclr r11, MSR_VMS + msrclr r0, MSR_VMS nop .endm .macro set_vms - msrclr r11, MSR_UMS + msrclr r0, MSR_UMS nop - msrset r11, MSR_VMS + msrset r0, MSR_VMS nop .endm - .macro clear_vms_ums - msrclr r11, MSR_VMS + .macro clear_ums + msrclr r0, MSR_UMS nop - msrclr r11, MSR_UMS + .endm + + .macro clear_vms_ums + msrclr r0, MSR_VMS | MSR_UMS nop .endm #else @@ -164,6 +167,14 @@ nop .endm + .macro clear_ums + mfs r11, rmsr + nop + andni r11, r11, MSR_UMS + mts rmsr,r11 + nop + .endm + .macro clear_vms_ums mfs r11, rmsr nop @@ -180,18 +191,22 @@ /* turn on virtual protected mode save */ #define VM_ON \ - set_ums; \ + set_ums; \ rted r0, 2f; \ -2: nop; + nop; \ +2: /* turn off virtual protected mode save and user mode save*/ #define VM_OFF \ - clear_vms_ums; \ + clear_vms_ums; \ rted r0, TOPHYS(1f); \ -1: nop; + nop; \ +1: #define SAVE_REGS \ swi r2, r1, PTO+PT_R2; /* Save SDA */ \ + swi r3, r1, PTO+PT_R3; \ + swi r4, r1, PTO+PT_R4; \ swi r5, r1, PTO+PT_R5; \ swi r6, r1, PTO+PT_R6; \ swi r7, r1, PTO+PT_R7; \ @@ -226,6 +241,8 @@ mts rmsr , r11; \ nop; \ lwi r2, r1, PTO+PT_R2; /* restore SDA */ \ + lwi r3, r1, PTO+PT_R3; \ + lwi r4, r1, PTO+PT_R4; \ lwi r5, r1, PTO+PT_R5; \ lwi r6, r1, PTO+PT_R6; \ lwi r7, r1, PTO+PT_R7; \ @@ -252,6 +269,40 @@ lwi r30, r1, PTO+PT_R30; \ lwi r31, r1, PTO+PT_R31; /* Restore cur task reg */ +#define SAVE_STATE \ + swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */ \ + /* See if already in kernel mode.*/ \ + mfs r1, rmsr; \ + nop; \ + andi r1, r1, MSR_UMS; \ + bnei r1, 1f; \ + /* Kernel-mode state save. */ \ + /* Reload kernel stack-ptr. */ \ + lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ + /* FIXME: I can add these two lines to one */ \ + /* tophys(r1,r1); */ \ + /* addik r1, r1, -STATE_SAVE_SIZE; */ \ + addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \ + SAVE_REGS \ + brid 2f; \ + swi r1, r1, PTO+PT_MODE; \ +1: /* User-mode state save. */ \ + lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ + tophys(r1,r1); \ + lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \ + /* MS these three instructions can be added to one */ \ + /* addik r1, r1, THREAD_SIZE; */ \ + /* tophys(r1,r1); */ \ + /* addik r1, r1, -STATE_SAVE_SIZE; */ \ + addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \ + SAVE_REGS \ + lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ + swi r11, r1, PTO+PT_R1; /* Store user SP. */ \ + swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ \ + /* MS: I am clearing UMS even in case when I come from kernel space */ \ + clear_ums; \ +2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); + .text /* @@ -269,27 +320,25 @@ C_ENTRY(_user_exception): swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ addi r14, r14, 4 /* return address is 4 byte after call */ - swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ - lwi r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/ - beqi r11, 1f; /* Jump ahead if coming from user */ -/* Kernel-mode state save. */ - lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ - tophys(r1,r11); - swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */ - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */ + mfs r1, rmsr + nop + andi r1, r1, MSR_UMS + bnei r1, 1f + +/* Kernel-mode state save - kernel execve */ + lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ + tophys(r1,r1); addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS - addi r11, r0, 1; /* Was in kernel-mode. */ - swi r11, r1, PTO+PT_MODE; /* pt_regs -> kernel mode */ + swi r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */ brid 2f; nop; /* Fill delay slot */ /* User-mode state save. */ 1: - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */ lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ tophys(r1,r1); lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ @@ -300,11 +349,9 @@ C_ENTRY(_user_exception): addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ SAVE_REGS - swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ + swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); swi r11, r1, PTO+PT_R1; /* Store user SP. */ - addi r11, r0, 1; - swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */ 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* Save away the syscall number. */ swi r12, r1, PTO+PT_R0; @@ -363,27 +410,23 @@ C_ENTRY(_user_exception): # Find and jump into the syscall handler. lwi r12, r12, sys_call_table /* where the trap should return need -8 to adjust for rtsd r15, 8 */ - la r15, r0, ret_from_trap-8 + addi r15, r0, ret_from_trap-8 bra r12 /* The syscall number is invalid, return an error. */ 5: + rtsd r15, 8; /* looks like a normal subroutine return */ addi r3, r0, -ENOSYS; - rtsd r15,8; /* looks like a normal subroutine return */ - or r0, r0, r0 - /* Entry point used to return from a syscall/trap */ /* We re-enable BIP bit before state restore */ C_ENTRY(ret_from_trap): - set_bip; /* Ints masked for state restore*/ - lwi r11, r1, PTO+PT_MODE; -/* See if returning to kernel mode, if so, skip resched &c. */ - bnei r11, 2f; - swi r3, r1, PTO + PT_R3 swi r4, r1, PTO + PT_R4 + lwi r11, r1, PTO + PT_MODE; +/* See if returning to kernel mode, if so, skip resched &c. */ + bnei r11, 2f; /* We're returning to user mode, so check for various conditions that * trigger rescheduling. */ /* FIXME: Restructure all these flag checks. */ @@ -413,17 +456,13 @@ C_ENTRY(ret_from_trap): andi r11, r11, _TIF_SIGPENDING; beqi r11, 1f; /* Signals to handle, handle them */ - la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ addi r7, r0, 1; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ -1: - lwi r3, r1, PTO + PT_R3; /* restore syscall result */ - lwi r4, r1, PTO + PT_R4; - - swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ +1: set_bip; /* Ints masked for state restore */ swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); @@ -433,7 +472,8 @@ C_ENTRY(ret_from_trap): bri 6f; /* Return to kernel state. */ -2: VM_OFF; +2: set_bip; /* Ints masked for state restore */ + VM_OFF; tophys(r1,r1); RESTORE_REGS; addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ @@ -450,12 +490,11 @@ TRAP_return: /* Make global symbol for debugging */ C_ENTRY(sys_fork_wrapper): addi r5, r0, SIGCHLD /* Arg 0: flags */ lwi r6, r1, PTO+PT_R1 /* Arg 1: child SP (use parent's) */ - la r7, r1, PTO /* Arg 2: parent context */ + addik r7, r1, PTO /* Arg 2: parent context */ add r8. r0, r0 /* Arg 3: (unused) */ add r9, r0, r0; /* Arg 4: (unused) */ - add r10, r0, r0; /* Arg 5: (unused) */ brid do_fork /* Do real work (tail-call) */ - nop; + add r10, r0, r0; /* Arg 5: (unused) */ /* This the initial entry point for a new child thread, with an appropriate stack in place that makes it look the the child is in the middle of an @@ -466,35 +505,31 @@ C_ENTRY(ret_from_fork): bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ add r3, r5, r0; /* switch_thread returns the prev task */ /* ( in the delay slot ) */ - add r3, r0, r0; /* Child's fork call should return 0. */ brid ret_from_trap; /* Do normal trap return */ - nop; + add r3, r0, r0; /* Child's fork call should return 0. */ C_ENTRY(sys_vfork): brid microblaze_vfork /* Do real work (tail-call) */ - la r5, r1, PTO + addik r5, r1, PTO C_ENTRY(sys_clone): bnei r6, 1f; /* See if child SP arg (arg 1) is 0. */ - lwi r6, r1, PTO+PT_R1; /* If so, use paret's stack ptr */ -1: la r7, r1, PTO; /* Arg 2: parent context */ + lwi r6, r1, PTO + PT_R1; /* If so, use paret's stack ptr */ +1: addik r7, r1, PTO; /* Arg 2: parent context */ add r8, r0, r0; /* Arg 3: (unused) */ add r9, r0, r0; /* Arg 4: (unused) */ - add r10, r0, r0; /* Arg 5: (unused) */ brid do_fork /* Do real work (tail-call) */ - nop; + add r10, r0, r0; /* Arg 5: (unused) */ C_ENTRY(sys_execve): - la r8, r1, PTO; /* add user context as 4th arg */ brid microblaze_execve; /* Do real work (tail-call).*/ - nop; + addik r8, r1, PTO; /* add user context as 4th arg */ C_ENTRY(sys_rt_sigreturn_wrapper): swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ swi r4, r1, PTO+PT_R4; - la r5, r1, PTO; /* add user context as 1st arg */ brlid r15, sys_rt_sigreturn /* Do real work */ - nop; + addik r5, r1, PTO; /* add user context as 1st arg */ lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ lwi r4, r1, PTO+PT_R4; bri ret_from_trap /* fall through will not work here due to align */ @@ -503,83 +538,26 @@ C_ENTRY(sys_rt_sigreturn_wrapper): /* * HW EXCEPTION rutine start */ - -#define SAVE_STATE \ - swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ \ - set_bip; /*equalize initial state for all possible entries*/\ - clear_eip; \ - enable_irq; \ - set_ee; \ - /* See if already in kernel mode.*/ \ - lwi r11, r0, TOPHYS(PER_CPU(KM)); \ - beqi r11, 1f; /* Jump ahead if coming from user */\ - /* Kernel-mode state save. */ \ - /* Reload kernel stack-ptr. */ \ - lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ - tophys(r1,r11); \ - swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */ \ - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\ - addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */\ - /* store return registers separately because \ - * this macros is use for others exceptions */ \ - swi r3, r1, PTO + PT_R3; \ - swi r4, r1, PTO + PT_R4; \ - SAVE_REGS \ - /* PC, before IRQ/trap - this is one instruction above */ \ - swi r17, r1, PTO+PT_PC; \ - \ - addi r11, r0, 1; /* Was in kernel-mode. */ \ - swi r11, r1, PTO+PT_MODE; \ - brid 2f; \ - nop; /* Fill delay slot */ \ -1: /* User-mode state save. */ \ - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */\ - lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ - tophys(r1,r1); \ - lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \ - addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */\ - tophys(r1,r1); \ - \ - addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */\ - /* store return registers separately because this macros \ - * is use for others exceptions */ \ - swi r3, r1, PTO + PT_R3; \ - swi r4, r1, PTO + PT_R4; \ - SAVE_REGS \ - /* PC, before IRQ/trap - this is one instruction above FIXME*/ \ - swi r17, r1, PTO+PT_PC; \ - \ - swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ \ - lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ - swi r11, r1, PTO+PT_R1; /* Store user SP. */ \ - addi r11, r0, 1; \ - swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode.*/\ -2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); \ - /* Save away the syscall number. */ \ - swi r0, r1, PTO+PT_R0; \ - tovirt(r1,r1) - C_ENTRY(full_exception_trap): - swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ /* adjust exception address for privileged instruction * for finding where is it */ addik r17, r17, -4 SAVE_STATE /* Save registers */ + /* PC, before IRQ/trap - this is one instruction above */ + swi r17, r1, PTO+PT_PC; + tovirt(r1,r1) /* FIXME this can be store directly in PT_ESR reg. * I tested it but there is a fault */ /* where the trap should return need -8 to adjust for rtsd r15, 8 */ - la r15, r0, ret_from_exc - 8 - la r5, r1, PTO /* parameter struct pt_regs * regs */ + addik r15, r0, ret_from_exc - 8 mfs r6, resr nop mfs r7, rfsr; /* save FSR */ nop mts rfsr, r0; /* Clear sticky fsr */ nop - la r12, r0, full_exception - set_vms; - rtbd r12, 0; - nop; + rted r0, full_exception + addik r5, r1, PTO /* parameter struct pt_regs * regs */ /* * Unaligned data trap. @@ -592,19 +570,29 @@ C_ENTRY(full_exception_trap): * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S" */ C_ENTRY(unaligned_data_trap): - swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ + /* MS: I have to save r11 value and then restore it because + * set_bit, clear_eip, set_ee use r11 as temp register if MSR + * instructions are not used. We don't need to do if MSR instructions + * are used and they use r0 instead of r11. + * I am using ENTRY_SP which should be primary used only for stack + * pointer saving. */ + swi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); + set_bip; /* equalize initial state for all possible entries */ + clear_eip; + set_ee; + lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); SAVE_STATE /* Save registers.*/ + /* PC, before IRQ/trap - this is one instruction above */ + swi r17, r1, PTO+PT_PC; + tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ - la r15, r0, ret_from_exc-8 + addik r15, r0, ret_from_exc-8 mfs r3, resr /* ESR */ nop mfs r4, rear /* EAR */ nop - la r7, r1, PTO /* parameter struct pt_regs * regs */ - la r12, r0, _unaligned_data_exception - set_vms; - rtbd r12, 0; /* interrupts enabled */ - nop; + rtbd r0, _unaligned_data_exception + addik r7, r1, PTO /* parameter struct pt_regs * regs */ /* * Page fault traps. @@ -625,38 +613,35 @@ C_ENTRY(unaligned_data_trap): */ /* data and intruction trap - which is choose is resolved int fault.c */ C_ENTRY(page_fault_data_trap): - swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ SAVE_STATE /* Save registers.*/ + /* PC, before IRQ/trap - this is one instruction above */ + swi r17, r1, PTO+PT_PC; + tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ - la r15, r0, ret_from_exc-8 - la r5, r1, PTO /* parameter struct pt_regs * regs */ + addik r15, r0, ret_from_exc-8 mfs r6, rear /* parameter unsigned long address */ nop mfs r7, resr /* parameter unsigned long error_code */ nop - la r12, r0, do_page_fault - set_vms; - rtbd r12, 0; /* interrupts enabled */ - nop; + rted r0, do_page_fault + addik r5, r1, PTO /* parameter struct pt_regs * regs */ C_ENTRY(page_fault_instr_trap): - swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ SAVE_STATE /* Save registers.*/ + /* PC, before IRQ/trap - this is one instruction above */ + swi r17, r1, PTO+PT_PC; + tovirt(r1,r1) /* where the trap should return need -8 to adjust for rtsd r15, 8 */ - la r15, r0, ret_from_exc-8 - la r5, r1, PTO /* parameter struct pt_regs * regs */ + addik r15, r0, ret_from_exc-8 mfs r6, rear /* parameter unsigned long address */ nop ori r7, r0, 0 /* parameter unsigned long error_code */ - la r12, r0, do_page_fault - set_vms; - rtbd r12, 0; /* interrupts enabled */ - nop; + rted r0, do_page_fault + addik r5, r1, PTO /* parameter struct pt_regs * regs */ /* Entry point used to return from an exception. */ C_ENTRY(ret_from_exc): - set_bip; /* Ints masked for state restore*/ - lwi r11, r1, PTO+PT_MODE; + lwi r11, r1, PTO + PT_MODE; bnei r11, 2f; /* See if returning to kernel mode, */ /* ... if so, skip resched &c. */ @@ -687,32 +672,27 @@ C_ENTRY(ret_from_exc): * traps), but signal handlers may want to examine or change the * complete register state. Here we save anything not saved by * the normal entry sequence, so that it may be safely restored - * (in a possibly modified form) after do_signal returns. - * store return registers separately because this macros is use - * for others exceptions */ - la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ + * (in a possibly modified form) after do_signal returns. */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ -1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ +1: set_bip; /* Ints masked for state restore */ swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; RESTORE_REGS; addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */ bri 6f; /* Return to kernel state. */ -2: VM_OFF; +2: set_bip; /* Ints masked for state restore */ + VM_OFF; tophys(r1,r1); - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; RESTORE_REGS; addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ @@ -736,36 +716,25 @@ C_ENTRY(_interrupt): /* MS: we are in physical address */ /* Save registers, switch to proper stack, convert SP to virtual.*/ swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) - swi r11, r0, TOPHYS(PER_CPU(R11_SAVE)); /* MS: See if already in kernel mode. */ - lwi r11, r0, TOPHYS(PER_CPU(KM)); - beqi r11, 1f; /* MS: Jump ahead if coming from user */ + mfs r1, rmsr + nop + andi r1, r1, MSR_UMS + bnei r1, 1f /* Kernel-mode state save. */ - or r11, r1, r0 - tophys(r1,r11); /* MS: I have in r1 physical address where stack is */ -/* MS: Save original SP - position PT_R1 to next stack frame 4 *1 - 152*/ - swi r11, r1, (PT_R1 - PT_SIZE); -/* MS: restore r11 because of saving in SAVE_REGS */ - lwi r11, r0, TOPHYS(PER_CPU(R11_SAVE)); + lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) + tophys(r1,r1); /* MS: I have in r1 physical address where stack is */ /* save registers */ /* MS: Make room on the stack -> activation record */ addik r1, r1, -STATE_SAVE_SIZE; -/* MS: store return registers separately because - * this macros is use for others exceptions */ - swi r3, r1, PTO + PT_R3; - swi r4, r1, PTO + PT_R4; SAVE_REGS - /* MS: store mode */ - addi r11, r0, 1; /* MS: Was in kernel-mode. */ - swi r11, r1, PTO + PT_MODE; /* MS: and save it */ + swi r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */ brid 2f; nop; /* MS: Fill delay slot */ 1: /* User-mode state save. */ -/* MS: restore r11 -> FIXME move before SAVE_REG */ - lwi r11, r0, TOPHYS(PER_CPU(R11_SAVE)); /* MS: get the saved current */ lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); tophys(r1,r1); @@ -774,25 +743,18 @@ C_ENTRY(_interrupt): tophys(r1,r1); /* save registers */ addik r1, r1, -STATE_SAVE_SIZE; - swi r3, r1, PTO+PT_R3; - swi r4, r1, PTO+PT_R4; SAVE_REGS /* calculate mode */ swi r0, r1, PTO + PT_MODE; lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); swi r11, r1, PTO+PT_R1; - /* setup kernel mode to KM */ - addi r11, r0, 1; - swi r11, r0, TOPHYS(PER_CPU(KM)); - 2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); - swi r0, r1, PTO + PT_R0; tovirt(r1,r1) - la r5, r1, PTO; + addik r5, r1, PTO; set_vms; - la r11, r0, do_IRQ; - la r15, r0, irq_call; + addik r11, r0, do_IRQ; + addik r15, r0, irq_call; irq_call:rtbd r11, 0; nop; @@ -815,7 +777,7 @@ ret_from_irq: beqid r11, no_intr_resched /* Handle a signal return; Pending signals should be in r18. */ addi r7, r0, 0; /* Arg 3: int in_syscall */ - la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ bralid r15, do_signal; /* Handle any signals */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ @@ -823,12 +785,9 @@ ret_from_irq: no_intr_resched: /* Disable interrupts, we are now committed to the state restore */ disable_irq - swi r0, r0, PER_CPU(KM); /* MS: Now officially in user state. */ swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); VM_OFF; tophys(r1,r1); - lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */ - lwi r4, r1, PTO + PT_R4; RESTORE_REGS addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ lwi r1, r1, PT_R1 - PT_SIZE; @@ -857,8 +816,6 @@ restore: #endif VM_OFF /* MS: turn off MMU */ tophys(r1,r1) - lwi r3, r1, PTO + PT_R3; /* MS: restore saved r3, r4 registers */ - lwi r4, r1, PTO + PT_R4; RESTORE_REGS addik r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */ tovirt(r1,r1); @@ -878,29 +835,21 @@ C_ENTRY(_debug_exception): /* BIP bit is set on entry, no interrupts can occur */ swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) - swi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* Save r11 */ - set_bip; /*equalize initial state for all possible entries*/ - clear_eip; - enable_irq; - lwi r11, r0, TOPHYS(PER_CPU(KM));/* See if already in kernel mode.*/ - beqi r11, 1f; /* Jump ahead if coming from user */ + mfs r1, rmsr + nop + andi r1, r1, MSR_UMS + bnei r1, 1f /* Kernel-mode state save. */ - lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ - tophys(r1,r11); - swi r11, r1, (PT_R1-PT_SIZE); /* Save original SP. */ - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */ + lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ + tophys(r1,r1); addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ - swi r3, r1, PTO + PT_R3; - swi r4, r1, PTO + PT_R4; SAVE_REGS; - addi r11, r0, 1; /* Was in kernel-mode. */ - swi r11, r1, PTO + PT_MODE; + swi r1, r1, PTO + PT_MODE; brid 2f; nop; /* Fill delay slot */ 1: /* User-mode state save. */ - lwi r11, r0, TOPHYS(r0_ram + PTO + PT_R11); /* restore r11 */ lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ tophys(r1,r1); lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ @@ -908,32 +857,23 @@ C_ENTRY(_debug_exception): tophys(r1,r1); addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */ - swi r3, r1, PTO + PT_R3; - swi r4, r1, PTO + PT_R4; SAVE_REGS; - swi r0, r1, PTO+PT_MODE; /* Was in user-mode. */ + swi r0, r1, PTO + PT_MODE; /* Was in user-mode. */ lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); swi r11, r1, PTO+PT_R1; /* Store user SP. */ - addi r11, r0, 1; - swi r11, r0, TOPHYS(PER_CPU(KM)); /* Now we're in kernel-mode. */ -2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); - /* Save away the syscall number. */ - swi r0, r1, PTO+PT_R0; +2: tovirt(r1,r1) + set_vms; addi r5, r0, SIGTRAP /* send the trap signal */ add r6, r0, CURRENT_TASK; /* Get current task ptr into r11 */ addk r7, r0, r0 /* 3rd param zero */ - - set_vms; - la r11, r0, send_sig; - la r15, r0, dbtrap_call; -dbtrap_call: rtbd r11, 0; - nop; +dbtrap_call: rtbd r0, send_sig; + addik r15, r0, dbtrap_call; set_bip; /* Ints masked for state restore*/ - lwi r11, r1, PTO+PT_MODE; + lwi r11, r1, PTO + PT_MODE; bnei r11, 2f; /* Get current task ptr into r11 */ @@ -965,20 +905,18 @@ dbtrap_call: rtbd r11, 0; the normal entry sequence, so that it may be safely restored (in a possibly modified form) after do_signal returns. */ - la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ + addik r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ addi r7, r0, 0; /* Arg 3: int in_syscall */ bralid r15, do_signal; /* Handle any signals */ add r6, r0, r0; /* Arg 2: sigset_t *oldset */ /* Finally, return to user state. */ -1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ +1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ VM_OFF; tophys(r1,r1); - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; RESTORE_REGS addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ @@ -990,8 +928,6 @@ dbtrap_call: rtbd r11, 0; /* Return to kernel state. */ 2: VM_OFF; tophys(r1,r1); - lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ - lwi r4, r1, PTO+PT_R4; RESTORE_REGS addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */ @@ -1127,3 +1063,30 @@ ENTRY(_break) syscall_table_size=(.-sys_call_table) +type_SYSCALL: + .ascii "SYSCALL\0" +type_IRQ: + .ascii "IRQ\0" +type_IRQ_PREEMPT: + .ascii "IRQ (PREEMPTED)\0" +type_SYSCALL_PREEMPT: + .ascii " SYSCALL (PREEMPTED)\0" + + /* + * Trap decoding for stack unwinder + * Tuples are (start addr, end addr, string) + * If return address lies on [start addr, end addr], + * unwinder displays 'string' + */ + + .align 4 +.global microblaze_trap_handlers +microblaze_trap_handlers: + /* Exact matches come first */ + .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL + .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ + /* Fuzzy matches go here */ + .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT + .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT + /* End of table */ + .word 0 ; .word 0 ; .word 0