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