summaryrefslogtreecommitdiff
path: root/arch/microblaze/kernel/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel/entry.S')
-rw-r--r--arch/microblaze/kernel/entry.S607
1 files changed, 242 insertions, 365 deletions
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index c0ede25c5b99..304882e56459 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -48,128 +48,107 @@
*/
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
.macro clear_bip
- msrclr r11, MSR_BIP
- nop
+ msrclr r0, MSR_BIP
.endm
.macro set_bip
- msrset r11, MSR_BIP
- nop
+ msrset r0, MSR_BIP
.endm
.macro clear_eip
- msrclr r11, MSR_EIP
- nop
+ msrclr r0, MSR_EIP
.endm
.macro set_ee
- msrset r11, MSR_EE
- nop
+ msrset r0, MSR_EE
.endm
.macro disable_irq
- msrclr r11, MSR_IE
- nop
+ msrclr r0, MSR_IE
.endm
.macro enable_irq
- msrset r11, MSR_IE
- nop
+ msrset r0, MSR_IE
.endm
.macro set_ums
- msrset r11, MSR_UMS
- nop
- msrclr r11, MSR_VMS
- nop
+ msrset r0, MSR_UMS
+ msrclr r0, MSR_VMS
.endm
.macro set_vms
- msrclr r11, MSR_UMS
- nop
- msrset r11, MSR_VMS
- nop
+ msrclr r0, MSR_UMS
+ msrset r0, MSR_VMS
+ .endm
+
+ .macro clear_ums
+ msrclr r0, MSR_UMS
.endm
.macro clear_vms_ums
- msrclr r11, MSR_VMS
- nop
- msrclr r11, MSR_UMS
- nop
+ msrclr r0, MSR_VMS | MSR_UMS
.endm
#else
.macro clear_bip
mfs r11, rmsr
- nop
andi r11, r11, ~MSR_BIP
mts rmsr, r11
- nop
.endm
.macro set_bip
mfs r11, rmsr
- nop
ori r11, r11, MSR_BIP
mts rmsr, r11
- nop
.endm
.macro clear_eip
mfs r11, rmsr
- nop
andi r11, r11, ~MSR_EIP
mts rmsr, r11
- nop
.endm
.macro set_ee
mfs r11, rmsr
- nop
ori r11, r11, MSR_EE
mts rmsr, r11
- nop
.endm
.macro disable_irq
mfs r11, rmsr
- nop
andi r11, r11, ~MSR_IE
mts rmsr, r11
- nop
.endm
.macro enable_irq
mfs r11, rmsr
- nop
ori r11, r11, MSR_IE
mts rmsr, r11
- nop
.endm
.macro set_ums
mfs r11, rmsr
- nop
ori r11, r11, MSR_VMS
andni r11, r11, MSR_UMS
mts rmsr, r11
- nop
.endm
.macro set_vms
mfs r11, rmsr
- nop
ori r11, r11, MSR_VMS
andni r11, r11, MSR_UMS
mts rmsr, r11
- nop
+ .endm
+
+ .macro clear_ums
+ mfs r11, rmsr
+ andni r11, r11, MSR_UMS
+ mts rmsr,r11
.endm
.macro clear_vms_ums
mfs r11, rmsr
- nop
andni r11, r11, (MSR_VMS|MSR_UMS)
mts rmsr,r11
- nop
.endm
#endif
@@ -180,18 +159,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; \
@@ -218,14 +201,14 @@
swi r30, r1, PTO+PT_R30; \
swi r31, r1, PTO+PT_R31; /* Save current task reg */ \
mfs r11, rmsr; /* save MSR */ \
- nop; \
swi r11, r1, PTO+PT_MSR;
#define RESTORE_REGS \
lwi r11, r1, PTO+PT_MSR; \
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 +235,39 @@
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; \
+ 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
/*
@@ -267,45 +283,23 @@
* are masked. This is nice, means we don't have to CLI before state save
*/
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 */
-
- 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 */
- brid 2f;
- nop; /* Fill delay slot */
+ swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
-/* 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 */
-/* calculate kernel stack pointer from task struct 8k */
- addik r1, r1, THREAD_SIZE;
- tophys(r1,r1);
-
- addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
+ /* 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
- 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));
+ clear_ums;
+ lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
/* Save away the syscall number. */
swi r12, r1, PTO+PT_R0;
tovirt(r1,r1)
@@ -316,10 +310,8 @@ C_ENTRY(_user_exception):
* register should point to the location where
* the called function should return. [note that MAKE_SYS_CALL uses label 1] */
- # Step into virtual mode.
- set_vms;
- addik r11, r0, 3f
- rtid r11, 0
+ /* Step into virtual mode */
+ rtbd r0, 3f
nop
3:
lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */
@@ -363,24 +355,17 @@ 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
@@ -413,32 +398,19 @@ 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);
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;
- tophys(r1,r1);
- RESTORE_REGS;
- addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
- tovirt(r1,r1);
-6:
TRAP_return: /* Make global symbol for debugging */
rtbd r14, 0; /* Instructions to return from an IRQ */
nop;
@@ -450,12 +422,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 +437,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 +470,23 @@ 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 +499,27 @@ 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 +540,32 @@ 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 +596,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 +640,23 @@ 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 */
brid 2f;
- nop; /* MS: Fill delay slot */
-
+ swi r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
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,27 +665,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));
-
+ clear_ums;
2:
lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
- swi r0, r1, PTO + PT_R0;
tovirt(r1,r1)
- la r5, r1, PTO;
- set_vms;
- la r11, r0, do_IRQ;
- la r15, r0, irq_call;
-irq_call:rtbd r11, 0;
- nop;
+ addik r15, r0, irq_call;
+irq_call:rtbd r0, do_IRQ;
+ addik r5, r1, PTO;
/* MS: we are in virtual mode */
ret_from_irq:
@@ -815,7 +697,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 +705,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 +736,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);
@@ -868,86 +745,91 @@ IRQ_return: /* MS: Make global symbol for debugging */
nop
/*
- * `Debug' trap
- * We enter dbtrap in "BIP" (breakpoint) mode.
- * So we exit the breakpoint mode with an 'rtbd' and proceed with the
- * original dbtrap.
- * however, wait to save state first
+ * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18
+ * and call handling function with saved pt_regs
*/
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 */
- /* 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
+/* MS: Kernel-mode state save - kgdb */
+ lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
- addik r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
- swi r3, r1, PTO + PT_R3;
- swi r4, r1, PTO + PT_R4;
+ /* BIP bit is set on entry, no interrupts can occur */
+ addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
SAVE_REGS;
+ /* save all regs to pt_reg structure */
+ swi r0, r1, PTO+PT_R0; /* R0 must be saved too */
+ swi r14, r1, PTO+PT_R14 /* rewrite saved R14 value */
+ swi r16, r1, PTO+PT_R16
+ swi r16, r1, PTO+PT_PC; /* PC and r16 are the same */
+ swi r17, r1, PTO+PT_R17
+ /* save special purpose registers to pt_regs */
+ mfs r11, rear;
+ swi r11, r1, PTO+PT_EAR;
+ mfs r11, resr;
+ swi r11, r1, PTO+PT_ESR;
+ mfs r11, rfsr;
+ swi r11, r1, PTO+PT_FSR;
+
+ /* stack pointer is in physical address at it is decrease
+ * by STATE_SAVE_SIZE but we need to get correct R1 value */
+ addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
+ swi r11, r1, PTO+PT_R1
+ /* MS: r31 - current pointer isn't changed */
+ tovirt(r1,r1)
+#ifdef CONFIG_KGDB
+ addi r5, r1, PTO /* pass pt_reg address as the first arg */
+ la r15, r0, dbtrap_call; /* return address */
+ rtbd r0, microblaze_kgdb_break
+ nop;
+#endif
+ /* MS: Place handler for brki from kernel space if KGDB is OFF.
+ * It is very unlikely that another brki instruction is called. */
+ bri 0
- 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 */
+/* MS: User-mode state save - gdb */
+1: 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. */
- 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 r17, r1, PTO+PT_R17;
+ swi r16, r1, PTO+PT_R16;
+ swi r16, r1, PTO+PT_PC; /* Save LP */
+ 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;
+ lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
tovirt(r1,r1)
-
- 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;
+ addik r5, r1, PTO;
+ addik r15, r0, dbtrap_call;
+dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
+ rtbd r0, sw_exception
+ nop
- set_bip; /* Ints masked for state restore*/
- lwi r11, r1, PTO+PT_MODE;
+ /* MS: The first instruction for the second part of the gdb/kgdb */
+ set_bip; /* Ints masked for state restore */
+ lwi r11, r1, PTO + PT_MODE;
bnei r11, 2f;
-
+/* MS: Return to user space - gdb */
/* Get current task ptr into r11 */
lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
andi r11, r11, _TIF_NEED_RESCHED;
beqi r11, 5f;
-/* Call the scheduler before returning from a syscall/trap. */
-
+ /* Call the scheduler before returning from a syscall/trap. */
bralid r15, schedule; /* Call scheduler */
nop; /* delay slot */
- /* XXX Is PT_DTRACE handling needed here? */
- /* XXX m68knommu also checks TASK_STATE & TASK_COUNTER here. */
/* Maybe handle a signal */
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
@@ -955,54 +837,40 @@ dbtrap_call: rtbd r11, 0;
andi r11, r11, _TIF_SIGPENDING;
beqi r11, 1f; /* Signals to handle, handle them */
-/* Handle a signal return; Pending signals should be in r18. */
- /* Not all registers are saved by the normal trap/interrupt entry
- points (for instance, call-saved registers (because the normal
- C-compiler calling sequence in the kernel makes sure they're
- preserved), and call-clobbered registers in the case of
- 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. */
-
- 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. */
- swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
+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;
+ /* MS: Restore all regs */
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;
+ lwi r17, r1, PTO+PT_R17;
+ lwi r16, r1, PTO+PT_R16;
+ addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space */
+ lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
+DBTRAP_return_user: /* MS: Make global symbol for debugging */
+ rtbd r16, 0; /* MS: Instructions to return from a debug trap */
+ nop;
-/* Return to kernel state. */
+/* MS: Return to kernel state - kgdb */
2: VM_OFF;
tophys(r1,r1);
- lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
- lwi r4, r1, PTO+PT_R4;
+ /* MS: Restore all regs */
RESTORE_REGS
- addik r1, r1, STATE_SAVE_SIZE /* Clean up stack space. */
-
+ lwi r14, r1, PTO+PT_R14;
+ lwi r16, r1, PTO+PT_PC;
+ lwi r17, r1, PTO+PT_R17;
+ addik r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
tovirt(r1,r1);
-6:
-DBTRAP_return: /* Make global symbol for debugging */
- rtbd r14, 0; /* Instructions to return from an IRQ */
+DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
+ rtbd r16, 0; /* MS: Instructions to return from a debug trap */
nop;
-
ENTRY(_switch_to)
/* prepare return value */
addk r3, r0, CURRENT_TASK
@@ -1037,16 +905,12 @@ ENTRY(_switch_to)
swi r30, r11, CC_R30
/* special purpose registers */
mfs r12, rmsr
- nop
swi r12, r11, CC_MSR
mfs r12, rear
- nop
swi r12, r11, CC_EAR
mfs r12, resr
- nop
swi r12, r11, CC_ESR
mfs r12, rfsr
- nop
swi r12, r11, CC_FSR
/* update r31, the current-give me pointer to task which will be next */
@@ -1085,10 +949,8 @@ ENTRY(_switch_to)
/* special purpose registers */
lwi r12, r11, CC_FSR
mts rfsr, r12
- nop
lwi r12, r11, CC_MSR
mts rmsr, r12
- nop
rtsd r15, 8
nop
@@ -1096,15 +958,6 @@ ENTRY(_switch_to)
ENTRY(_reset)
brai 0x70; /* Jump back to FS-boot */
-ENTRY(_break)
- mfs r5, rmsr
- nop
- swi r5, r0, 0x250 + TOPHYS(r0_ram)
- mfs r5, resr
- nop
- swi r5, r0, 0x254 + TOPHYS(r0_ram)
- bri 0
-
/* These are compiled and loaded into high memory, then
* copied into place in mach_early_setup */
.section .init.ivt, "ax"
@@ -1116,14 +969,38 @@ ENTRY(_break)
nop
brai TOPHYS(_user_exception); /* syscall handler */
brai TOPHYS(_interrupt); /* Interrupt handler */
- brai TOPHYS(_break); /* nmi trap handler */
+ brai TOPHYS(_debug_exception); /* debug trap handler */
brai TOPHYS(_hw_exception_handler); /* HW exception handler */
- .org 0x60
- brai TOPHYS(_debug_exception); /* debug trap handler*/
-
.section .rodata,"a"
#include "syscall_table.S"
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