1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
|
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1994 - 2000, 2001 by Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
* Copyright (C) 2001 MIPS Technologies, Inc.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/sys.h>
#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/cacheops.h>
#include <asm/current.h>
#include <asm/errno.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/pgtable-bits.h>
#include <asm/stackframe.h>
#include <asm/processor.h>
#include <asm/regdef.h>
#include <asm/fpregdef.h>
#include <asm/unistd.h>
#include <asm/isadep.h>
.text
.align 5
.set push
.set reorder
FEXPORT(ret_from_irq)
FEXPORT(ret_from_exception)
lw t0, PT_STATUS(sp) # returning to kernel mode?
andi t0, t0, KU_USER
beqz t0, restore_all
FEXPORT(ret_from_sys_call) # here to prevent code duplication
ret_from_schedule:
mfc0 t0, CP0_STATUS # need_resched and signals atomic test
ori t0, t0, 1
xori t0, t0, 1
mtc0 t0, CP0_STATUS
SSNOP; SSNOP; SSNOP
lw v0, TASK_NEED_RESCHED($28)
lw v1, TASK_SIGPENDING($28)
bnez v0, reschedule
bnez v1, signal_return
restore_all: .set noat
RESTORE_ALL_AND_RET
.set at
/* Put this behind restore_all for the sake of the branch prediction. */
signal_return:
.type signal_return, @function
mfc0 t0, CP0_STATUS
ori t0, t0, 1
mtc0 t0, CP0_STATUS
move a0, zero
move a1, sp
jal do_signal
b restore_all
reschedule:
jal schedule
b ret_from_schedule
/*
* Common spurious interrupt handler.
*/
.text
.align 5
LEAF(spurious_interrupt)
/*
* Someone tried to fool us by sending an interrupt but we
* couldn't find a cause for it.
*/
lui t1,%hi(irq_err_count)
lw t0,%lo(irq_err_count)(t1)
addiu t0,1
sw t0,%lo(irq_err_count)(t1)
j ret_from_irq
END(spurious_interrupt)
__INIT
.set reorder
NESTED(except_vec1_generic, 0, sp)
PANIC("Exception vector 1 called")
END(except_vec1_generic)
/*
* General exception vector. Used for all CPUs except R4000
* and R4400 SC and MC versions.
*/
NESTED(except_vec3_generic, 0, sp)
#ifdef CONFIG_BCM4710
nop
nop
#endif
mfc0 k1, CP0_CAUSE
la k0, exception_handlers
andi k1, k1, 0x7c
addu k0, k0, k1
lw k0, (k0)
jr k0
END(except_vec3_generic)
.set at
/* General exception vector R4000 version. */
NESTED(except_vec3_r4000, 0, sp)
.set push
.set mips3
.set noat
#if defined(R5432_CP0_INTERRUPT_WAR)
mfc0 k0, CP0_INDEX
#endif
mfc0 k1, CP0_CAUSE
li k0, 31<<2
andi k1, k1, 0x7c
.set noreorder
beq k1, k0, handle_vced
li k0, 14<<2
beq k1, k0, handle_vcei
la k0, exception_handlers
.set reorder
addu k0, k0, k1
lw k0, (k0)
jr k0
/*
* Big shit, we now may have two dirty primary cache lines for
* the same physical address. We can savely invalidate the
* line pointed to by c0_badvaddr because after return from
* this exception handler the load / store will be re-executed.
*/
handle_vced:
mfc0 k0, CP0_BADVADDR
li k1, -4
and k0, k1
mtc0 zero, CP0_TAGLO
cache Index_Store_Tag_D,(k0)
cache Hit_Writeback_Inv_SD,(k0)
#ifdef CONFIG_PROC_FS
lui k0, %hi(vced_count)
lw k1, %lo(vced_count)(k0)
addiu k1, 1
sw k1, %lo(vced_count)(k0)
#endif
eret
handle_vcei:
mfc0 k0, CP0_BADVADDR
cache Hit_Writeback_Inv_SD, (k0) # also cleans pi
#ifdef CONFIG_PROC_FS
lui k0, %hi(vcei_count)
lw k1, %lo(vcei_count)(k0)
addiu k1, 1
sw k1, %lo(vcei_count)(k0)
#endif
eret
.set pop
END(except_vec3_r4000)
__FINIT
/*
* Build a default exception handler for the exceptions that don't need
* special handlers. If you didn't know yet - I *like* playing games with
* the C preprocessor ...
*/
#define __BUILD_clear_none(exception)
#define __BUILD_clear_sti(exception) \
STI
#define __BUILD_clear_cli(exception) \
CLI
#define __BUILD_clear_fpe(exception) \
cfc1 a1,fcr31; \
li a2,~(0x3f<<12); \
and a2,a1; \
ctc1 a2,fcr31; \
STI
#define __BUILD_clear_ade(exception) \
.set reorder; \
MFC0 t0,CP0_BADVADDR; \
.set noreorder; \
REG_S t0,PT_BVADDR(sp); \
KMODE
#define __BUILD_silent(exception)
#define fmt "Got %s at %08lx.\n"
#define __BUILD_verbose(exception) \
la a1,8f; \
TEXT (#exception); \
REG_L a2,PT_EPC(sp); \
PRINT(fmt)
#define __BUILD_count(exception) \
.set reorder; \
lw t0,exception_count_##exception; \
.set noreorder; \
addiu t0, 1; \
sw t0,exception_count_##exception; \
.data; \
EXPORT(exception_count_##exception); \
.word 0; \
.previous;
#define BUILD_HANDLER(exception,handler,clear,verbose) \
.align 5; \
NESTED(handle_##exception, PT_SIZE, sp); \
.set noat; \
SAVE_ALL; \
FEXPORT(handle_##exception##_int); \
__BUILD_clear_##clear(exception); \
.set at; \
__BUILD_##verbose(exception); \
jal do_##handler; \
move a0, sp; \
j ret_from_exception; \
nop; \
END(handle_##exception)
BUILD_HANDLER(adel,ade,ade,silent) /* #4 */
BUILD_HANDLER(ades,ade,ade,silent) /* #5 */
BUILD_HANDLER(ibe,be,cli,silent) /* #6 */
BUILD_HANDLER(dbe,be,cli,silent) /* #7 */
BUILD_HANDLER(bp,bp,sti,silent) /* #9 */
BUILD_HANDLER(ri,ri,sti,silent) /* #10 */
BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */
BUILD_HANDLER(ov,ov,sti,silent) /* #12 */
BUILD_HANDLER(tr,tr,sti,silent) /* #13 */
BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */
BUILD_HANDLER(mdmx,mdmx,sti,silent) /* #22 */
BUILD_HANDLER(watch,watch,sti,silent) /* #23 */
BUILD_HANDLER(mcheck,mcheck,cli,silent) /* #24 */
BUILD_HANDLER(reserved,reserved,sti,silent) /* others */
.set pop
/*
* Table of syscalls
*/
.data
.align PTRLOG
EXPORT(sys_call_table)
#define SYS(call, narg) PTR call
/* Reserved space for all SVR4 syscalls. */
.space (1000)*PTRSIZE
#ifdef CONFIG_BINFMT_IRIX
/* 32bit IRIX5 system calls. */
#include "irix5sys.h"
#else
.space (1000)*PTRSIZE /* No IRIX syscalls */
#endif
/* Reserved space for all the BSD43 and POSIX syscalls. */
.space (2000)*PTRSIZE
/* Linux flavoured syscalls. */
#include "syscalls.h"
/*
* Number of arguments of each syscall
*/
EXPORT(sys_narg_table)
#undef SYS
#define SYS(call, narg) .byte narg
/* Reserved space for all SVR4 flavoured syscalls. */
.space (1000)
#ifdef CONFIG_BINFMT_IRIX
/* 32bit IRIX5 system calls. */
#include "irix5sys.h"
#else
.space (1000) /* No IRIX syscalls */
#endif
/* Reserved space for all the BSD43 and POSIX syscalls. */
.space (2000)
/* Linux flavoured syscalls. */
#include "syscalls.h"
|