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 | */ | |
1da177e4 LT |
10 | |
11 | #include <asm/asm.h> | |
12 | #include <asm/asmmacro.h> | |
aebac993 | 13 | #include <asm/compiler.h> |
1da177e4 LT |
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> | |
20 | ||
f431baa5 | 21 | #ifndef CONFIG_PREEMPT |
1da177e4 | 22 | #define resume_kernel restore_all |
7da8a581 FBH |
23 | #else |
24 | #define __ret_from_irq ret_from_exception | |
1da177e4 LT |
25 | #endif |
26 | ||
27 | .text | |
28 | .align 5 | |
7da8a581 | 29 | #ifndef CONFIG_PREEMPT |
1da177e4 | 30 | FEXPORT(ret_from_exception) |
7da8a581 FBH |
31 | local_irq_disable # preempt stop |
32 | b __ret_from_irq | |
f431baa5 | 33 | #endif |
7da8a581 FBH |
34 | FEXPORT(ret_from_irq) |
35 | LONG_S s0, TI_REGS($28) | |
36 | FEXPORT(__ret_from_irq) | |
c90e6fbb DA |
37 | /* |
38 | * We can be coming here from a syscall done in the kernel space, | |
39 | * e.g. a failed kernel_execve(). | |
40 | */ | |
41 | resume_userspace_check: | |
1da177e4 LT |
42 | LONG_L t0, PT_STATUS(sp) # returning to kernel mode? |
43 | andi t0, t0, KU_USER | |
44 | beqz t0, resume_kernel | |
45 | ||
c2648527 TS |
46 | resume_userspace: |
47 | local_irq_disable # make sure we dont miss an | |
1da177e4 LT |
48 | # interrupt setting need_resched |
49 | # between sampling and return | |
7c151d3d MC |
50 | #ifdef CONFIG_MIPSR2_TO_R6_EMULATOR |
51 | lw k0, TI_R2_EMUL_RET($28) | |
52 | bnez k0, restore_all_from_r2_emul | |
53 | #endif | |
54 | ||
1da177e4 | 55 | LONG_L a2, TI_FLAGS($28) # current->work |
c2648527 TS |
56 | andi t0, a2, _TIF_WORK_MASK # (ignoring syscall_trace) |
57 | bnez t0, work_pending | |
1da177e4 LT |
58 | j restore_all |
59 | ||
60 | #ifdef CONFIG_PREEMPT | |
c2648527 | 61 | resume_kernel: |
a18815ab | 62 | local_irq_disable |
1da177e4 LT |
63 | lw t0, TI_PRE_COUNT($28) |
64 | bnez t0, restore_all | |
65 | need_resched: | |
66 | LONG_L t0, TI_FLAGS($28) | |
67 | andi t1, t0, _TIF_NEED_RESCHED | |
68 | beqz t1, restore_all | |
69 | LONG_L t0, PT_STATUS(sp) # Interrupts off? | |
70 | andi t0, 1 | |
71 | beqz t0, restore_all | |
a18815ab | 72 | jal preempt_schedule_irq |
cdaed73a | 73 | b need_resched |
1da177e4 LT |
74 | #endif |
75 | ||
8f54bcac AV |
76 | FEXPORT(ret_from_kernel_thread) |
77 | jal schedule_tail # a0 = struct task_struct *prev | |
78 | move a0, s1 | |
79 | jal s0 | |
9b0e5d42 | 80 | j syscall_exit |
8f54bcac | 81 | |
1da177e4 | 82 | FEXPORT(ret_from_fork) |
36c8b586 | 83 | jal schedule_tail # a0 = struct task_struct *prev |
1da177e4 LT |
84 | |
85 | FEXPORT(syscall_exit) | |
86 | local_irq_disable # make sure need_resched and | |
87 | # signals dont change between | |
88 | # sampling and return | |
89 | LONG_L a2, TI_FLAGS($28) # current->work | |
90 | li t0, _TIF_ALLWORK_MASK | |
91 | and t0, a2, t0 | |
92 | bnez t0, syscall_exit_work | |
93 | ||
02f884ed | 94 | restore_all: # restore full frame |
1da177e4 LT |
95 | .set noat |
96 | RESTORE_TEMP | |
97 | RESTORE_AT | |
98 | RESTORE_STATIC | |
02f884ed | 99 | restore_partial: # restore partial frame |
192ef366 RB |
100 | #ifdef CONFIG_TRACE_IRQFLAGS |
101 | SAVE_STATIC | |
102 | SAVE_AT | |
103 | SAVE_TEMP | |
104 | LONG_L v0, PT_STATUS(sp) | |
cbde5ebc CD |
105 | #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
106 | and v0, ST0_IEP | |
107 | #else | |
108 | and v0, ST0_IE | |
109 | #endif | |
192ef366 RB |
110 | beqz v0, 1f |
111 | jal trace_hardirqs_on | |
112 | b 2f | |
113 | 1: jal trace_hardirqs_off | |
114 | 2: | |
115 | RESTORE_TEMP | |
116 | RESTORE_AT | |
117 | RESTORE_STATIC | |
118 | #endif | |
1da177e4 LT |
119 | RESTORE_SOME |
120 | RESTORE_SP_AND_RET | |
121 | .set at | |
122 | ||
7c151d3d MC |
123 | #ifdef CONFIG_MIPSR2_TO_R6_EMULATOR |
124 | restore_all_from_r2_emul: # restore full frame | |
125 | .set noat | |
126 | sw zero, TI_R2_EMUL_RET($28) # reset it | |
127 | RESTORE_TEMP | |
128 | RESTORE_AT | |
129 | RESTORE_STATIC | |
130 | RESTORE_SOME | |
131 | LONG_L sp, PT_R29(sp) | |
132 | eretnc | |
133 | .set at | |
134 | #endif | |
135 | ||
c2648527 TS |
136 | work_pending: |
137 | andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS | |
1da177e4 LT |
138 | beqz t0, work_notifysig |
139 | work_resched: | |
140 | jal schedule | |
141 | ||
c2648527 | 142 | local_irq_disable # make sure need_resched and |
1da177e4 LT |
143 | # signals dont change between |
144 | # sampling and return | |
145 | LONG_L a2, TI_FLAGS($28) | |
146 | andi t0, a2, _TIF_WORK_MASK # is there any work to be done | |
147 | # other than syscall tracing? | |
148 | beqz t0, restore_all | |
149 | andi t0, a2, _TIF_NEED_RESCHED | |
150 | bnez t0, work_resched | |
151 | ||
152 | work_notifysig: # deal with pending signals and | |
153 | # notify-resume requests | |
154 | move a0, sp | |
155 | li a1, 0 | |
156 | jal do_notify_resume # a2 already loaded | |
c90e6fbb | 157 | j resume_userspace_check |
1da177e4 | 158 | |
02f884ed AV |
159 | FEXPORT(syscall_exit_partial) |
160 | local_irq_disable # make sure need_resched doesn't | |
161 | # change between and return | |
162 | LONG_L a2, TI_FLAGS($28) # current->work | |
163 | li t0, _TIF_ALLWORK_MASK | |
164 | and t0, a2 | |
165 | beqz t0, restore_partial | |
1da177e4 | 166 | SAVE_STATIC |
c2648527 | 167 | syscall_exit_work: |
f76f3308 AV |
168 | LONG_L t0, PT_STATUS(sp) # returning to kernel mode? |
169 | andi t0, t0, KU_USER | |
170 | beqz t0, resume_kernel | |
c19c20ac | 171 | li t0, _TIF_WORK_SYSCALL_EXIT |
c2648527 TS |
172 | and t0, a2 # a2 is preloaded with TI_FLAGS |
173 | beqz t0, work_pending # trace bit set? | |
8b659a39 | 174 | local_irq_enable # could let syscall_trace_leave() |
1da177e4 LT |
175 | # call schedule() instead |
176 | move a0, sp | |
8b659a39 | 177 | jal syscall_trace_leave |
1da177e4 | 178 | b resume_userspace |
bce1a286 | 179 | |
6ebb496f MC |
180 | #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) || \ |
181 | defined(CONFIG_MIPS_MT) | |
bce1a286 RB |
182 | |
183 | /* | |
184 | * MIPS32R2 Instruction Hazard Barrier - must be called | |
185 | * | |
186 | * For C code use the inline version named instruction_hazard(). | |
187 | */ | |
188 | LEAF(mips_ihb) | |
aebac993 | 189 | .set MIPS_ISA_LEVEL_RAW |
bce1a286 RB |
190 | jr.hb ra |
191 | nop | |
192 | END(mips_ihb) | |
193 | ||
6ebb496f | 194 | #endif /* CONFIG_CPU_MIPSR2 or CONFIG_CPU_MIPSR6 or CONFIG_MIPS_MT */ |