Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle | |
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | |
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | |
9 | */ | |
10 | #include <linux/config.h> | |
11 | ||
12 | #include <asm/asm.h> | |
13 | #include <asm/asmmacro.h> | |
14 | #include <asm/regdef.h> | |
15 | #include <asm/mipsregs.h> | |
16 | #include <asm/stackframe.h> | |
17 | #include <asm/isadep.h> | |
18 | #include <asm/thread_info.h> | |
19 | #include <asm/war.h> | |
41c594ab RB |
20 | #ifdef CONFIG_MIPS_MT_SMTC |
21 | #include <asm/mipsmtregs.h> | |
22 | #endif | |
1da177e4 LT |
23 | |
24 | #ifdef CONFIG_PREEMPT | |
c2648527 | 25 | .macro preempt_stop |
1da177e4 LT |
26 | .endm |
27 | #else | |
c2648527 TS |
28 | .macro preempt_stop |
29 | local_irq_disable | |
1da177e4 LT |
30 | .endm |
31 | #define resume_kernel restore_all | |
32 | #endif | |
33 | ||
34 | .text | |
35 | .align 5 | |
36 | FEXPORT(ret_from_exception) | |
37 | preempt_stop | |
38 | FEXPORT(ret_from_irq) | |
39 | LONG_L t0, PT_STATUS(sp) # returning to kernel mode? | |
40 | andi t0, t0, KU_USER | |
41 | beqz t0, resume_kernel | |
42 | ||
c2648527 TS |
43 | resume_userspace: |
44 | local_irq_disable # make sure we dont miss an | |
1da177e4 LT |
45 | # interrupt setting need_resched |
46 | # between sampling and return | |
47 | LONG_L a2, TI_FLAGS($28) # current->work | |
c2648527 TS |
48 | andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) |
49 | bnez t0, work_pending | |
1da177e4 LT |
50 | j restore_all |
51 | ||
52 | #ifdef CONFIG_PREEMPT | |
c2648527 | 53 | resume_kernel: |
a18815ab | 54 | local_irq_disable |
1da177e4 LT |
55 | lw t0, TI_PRE_COUNT($28) |
56 | bnez t0, restore_all | |
57 | need_resched: | |
58 | LONG_L t0, TI_FLAGS($28) | |
59 | andi t1, t0, _TIF_NEED_RESCHED | |
60 | beqz t1, restore_all | |
61 | LONG_L t0, PT_STATUS(sp) # Interrupts off? | |
62 | andi t0, 1 | |
63 | beqz t0, restore_all | |
a18815ab | 64 | jal preempt_schedule_irq |
cdaed73a | 65 | b need_resched |
1da177e4 LT |
66 | #endif |
67 | ||
68 | FEXPORT(ret_from_fork) | |
69 | jal schedule_tail # a0 = task_t *prev | |
70 | ||
71 | FEXPORT(syscall_exit) | |
72 | local_irq_disable # make sure need_resched and | |
73 | # signals dont change between | |
74 | # sampling and return | |
75 | LONG_L a2, TI_FLAGS($28) # current->work | |
76 | li t0, _TIF_ALLWORK_MASK | |
77 | and t0, a2, t0 | |
78 | bnez t0, syscall_exit_work | |
79 | ||
80 | FEXPORT(restore_all) # restore full frame | |
41c594ab RB |
81 | #ifdef CONFIG_MIPS_MT_SMTC |
82 | /* Detect and execute deferred IPI "interrupts" */ | |
83 | move a0,sp | |
84 | jal deferred_smtc_ipi | |
85 | /* Re-arm any temporarily masked interrupts not explicitly "acked" */ | |
86 | mfc0 v0, CP0_TCSTATUS | |
87 | ori v1, v0, TCSTATUS_IXMT | |
88 | mtc0 v1, CP0_TCSTATUS | |
89 | andi v0, TCSTATUS_IXMT | |
90 | ehb | |
91 | mfc0 t0, CP0_TCCONTEXT | |
92 | DMT 9 # dmt t1 | |
93 | jal mips_ihb | |
94 | mfc0 t2, CP0_STATUS | |
95 | andi t3, t0, 0xff00 | |
96 | or t2, t2, t3 | |
97 | mtc0 t2, CP0_STATUS | |
98 | ehb | |
99 | andi t1, t1, VPECONTROL_TE | |
100 | beqz t1, 1f | |
101 | EMT | |
102 | 1: | |
103 | mfc0 v1, CP0_TCSTATUS | |
477654fc | 104 | /* We set IXMT above, XOR should clear it here */ |
41c594ab RB |
105 | xori v1, v1, TCSTATUS_IXMT |
106 | or v1, v0, v1 | |
107 | mtc0 v1, CP0_TCSTATUS | |
108 | ehb | |
109 | xor t0, t0, t3 | |
110 | mtc0 t0, CP0_TCCONTEXT | |
111 | #endif /* CONFIG_MIPS_MT_SMTC */ | |
1da177e4 LT |
112 | .set noat |
113 | RESTORE_TEMP | |
114 | RESTORE_AT | |
115 | RESTORE_STATIC | |
116 | FEXPORT(restore_partial) # restore partial frame | |
117 | RESTORE_SOME | |
118 | RESTORE_SP_AND_RET | |
119 | .set at | |
120 | ||
c2648527 TS |
121 | work_pending: |
122 | andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS | |
1da177e4 LT |
123 | beqz t0, work_notifysig |
124 | work_resched: | |
125 | jal schedule | |
126 | ||
c2648527 | 127 | local_irq_disable # make sure need_resched and |
1da177e4 LT |
128 | # signals dont change between |
129 | # sampling and return | |
130 | LONG_L a2, TI_FLAGS($28) | |
131 | andi t0, a2, _TIF_WORK_MASK # is there any work to be done | |
132 | # other than syscall tracing? | |
133 | beqz t0, restore_all | |
134 | andi t0, a2, _TIF_NEED_RESCHED | |
135 | bnez t0, work_resched | |
136 | ||
137 | work_notifysig: # deal with pending signals and | |
138 | # notify-resume requests | |
139 | move a0, sp | |
140 | li a1, 0 | |
141 | jal do_notify_resume # a2 already loaded | |
0bf0e3e2 | 142 | j resume_userspace |
1da177e4 LT |
143 | |
144 | FEXPORT(syscall_exit_work_partial) | |
145 | SAVE_STATIC | |
c2648527 TS |
146 | syscall_exit_work: |
147 | li t0, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | |
148 | and t0, a2 # a2 is preloaded with TI_FLAGS | |
149 | beqz t0, work_pending # trace bit set? | |
1da177e4 LT |
150 | local_irq_enable # could let do_syscall_trace() |
151 | # call schedule() instead | |
152 | move a0, sp | |
153 | li a1, 1 | |
154 | jal do_syscall_trace | |
155 | b resume_userspace | |
bce1a286 RB |
156 | |
157 | #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT) | |
158 | ||
159 | /* | |
160 | * MIPS32R2 Instruction Hazard Barrier - must be called | |
161 | * | |
162 | * For C code use the inline version named instruction_hazard(). | |
163 | */ | |
164 | LEAF(mips_ihb) | |
165 | .set mips32r2 | |
166 | jr.hb ra | |
167 | nop | |
168 | END(mips_ihb) | |
169 | ||
170 | #endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */ |