Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

C6X: build infrastructure

Original port to early 2.6 kernel using TI COFF toolchain.
Brought up to date by Mark Salter <msalter@redhat.com>

Signed-off-by: Aurelien Jacquiot <a-jacquiot@ti.com>
Signed-off-by: Mark Salter <msalter@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>

authored by

Aurelien Jacquiot and committed by
Mark Salter
e94e6682 8a0c9e03

+1385
+36
arch/c6x/include/asm/traps.h
··· 1 + /* 2 + * Port on Texas Instruments TMS320C6x architecture 3 + * 4 + * Copyright (C) 2004, 2009, 2011 Texas Instruments Incorporated 5 + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + #ifndef _ASM_C6X_TRAPS_H 12 + #define _ASM_C6X_TRAPS_H 13 + 14 + #define EXCEPT_TYPE_NXF 31 /* NMI */ 15 + #define EXCEPT_TYPE_EXC 30 /* external exception */ 16 + #define EXCEPT_TYPE_IXF 1 /* internal exception */ 17 + #define EXCEPT_TYPE_SXF 0 /* software exception */ 18 + 19 + #define EXCEPT_CAUSE_LBX (1 << 7) /* loop buffer exception */ 20 + #define EXCEPT_CAUSE_PRX (1 << 6) /* privilege exception */ 21 + #define EXCEPT_CAUSE_RAX (1 << 5) /* resource access exception */ 22 + #define EXCEPT_CAUSE_RCX (1 << 4) /* resource conflict exception */ 23 + #define EXCEPT_CAUSE_OPX (1 << 3) /* opcode exception */ 24 + #define EXCEPT_CAUSE_EPX (1 << 2) /* execute packet exception */ 25 + #define EXCEPT_CAUSE_FPX (1 << 1) /* fetch packet exception */ 26 + #define EXCEPT_CAUSE_IFX (1 << 0) /* instruction fetch exception */ 27 + 28 + struct exception_info { 29 + char *kernel_str; 30 + int signo; 31 + int code; 32 + }; 33 + 34 + extern int (*c6x_nmi_handler)(struct pt_regs *regs); 35 + 36 + #endif /* _ASM_C6X_TRAPS_H */
+123
arch/c6x/kernel/asm-offsets.c
··· 1 + /* 2 + * Generate definitions needed by assembly language modules. 3 + * This code generates raw asm output which is post-processed 4 + * to extract and format the required data. 5 + */ 6 + 7 + #include <linux/sched.h> 8 + #include <linux/thread_info.h> 9 + #include <asm/procinfo.h> 10 + #include <linux/kbuild.h> 11 + #include <linux/unistd.h> 12 + 13 + void foo(void) 14 + { 15 + OFFSET(REGS_A16, pt_regs, a16); 16 + OFFSET(REGS_A17, pt_regs, a17); 17 + OFFSET(REGS_A18, pt_regs, a18); 18 + OFFSET(REGS_A19, pt_regs, a19); 19 + OFFSET(REGS_A20, pt_regs, a20); 20 + OFFSET(REGS_A21, pt_regs, a21); 21 + OFFSET(REGS_A22, pt_regs, a22); 22 + OFFSET(REGS_A23, pt_regs, a23); 23 + OFFSET(REGS_A24, pt_regs, a24); 24 + OFFSET(REGS_A25, pt_regs, a25); 25 + OFFSET(REGS_A26, pt_regs, a26); 26 + OFFSET(REGS_A27, pt_regs, a27); 27 + OFFSET(REGS_A28, pt_regs, a28); 28 + OFFSET(REGS_A29, pt_regs, a29); 29 + OFFSET(REGS_A30, pt_regs, a30); 30 + OFFSET(REGS_A31, pt_regs, a31); 31 + 32 + OFFSET(REGS_B16, pt_regs, b16); 33 + OFFSET(REGS_B17, pt_regs, b17); 34 + OFFSET(REGS_B18, pt_regs, b18); 35 + OFFSET(REGS_B19, pt_regs, b19); 36 + OFFSET(REGS_B20, pt_regs, b20); 37 + OFFSET(REGS_B21, pt_regs, b21); 38 + OFFSET(REGS_B22, pt_regs, b22); 39 + OFFSET(REGS_B23, pt_regs, b23); 40 + OFFSET(REGS_B24, pt_regs, b24); 41 + OFFSET(REGS_B25, pt_regs, b25); 42 + OFFSET(REGS_B26, pt_regs, b26); 43 + OFFSET(REGS_B27, pt_regs, b27); 44 + OFFSET(REGS_B28, pt_regs, b28); 45 + OFFSET(REGS_B29, pt_regs, b29); 46 + OFFSET(REGS_B30, pt_regs, b30); 47 + OFFSET(REGS_B31, pt_regs, b31); 48 + 49 + OFFSET(REGS_A0, pt_regs, a0); 50 + OFFSET(REGS_A1, pt_regs, a1); 51 + OFFSET(REGS_A2, pt_regs, a2); 52 + OFFSET(REGS_A3, pt_regs, a3); 53 + OFFSET(REGS_A4, pt_regs, a4); 54 + OFFSET(REGS_A5, pt_regs, a5); 55 + OFFSET(REGS_A6, pt_regs, a6); 56 + OFFSET(REGS_A7, pt_regs, a7); 57 + OFFSET(REGS_A8, pt_regs, a8); 58 + OFFSET(REGS_A9, pt_regs, a9); 59 + OFFSET(REGS_A10, pt_regs, a10); 60 + OFFSET(REGS_A11, pt_regs, a11); 61 + OFFSET(REGS_A12, pt_regs, a12); 62 + OFFSET(REGS_A13, pt_regs, a13); 63 + OFFSET(REGS_A14, pt_regs, a14); 64 + OFFSET(REGS_A15, pt_regs, a15); 65 + 66 + OFFSET(REGS_B0, pt_regs, b0); 67 + OFFSET(REGS_B1, pt_regs, b1); 68 + OFFSET(REGS_B2, pt_regs, b2); 69 + OFFSET(REGS_B3, pt_regs, b3); 70 + OFFSET(REGS_B4, pt_regs, b4); 71 + OFFSET(REGS_B5, pt_regs, b5); 72 + OFFSET(REGS_B6, pt_regs, b6); 73 + OFFSET(REGS_B7, pt_regs, b7); 74 + OFFSET(REGS_B8, pt_regs, b8); 75 + OFFSET(REGS_B9, pt_regs, b9); 76 + OFFSET(REGS_B10, pt_regs, b10); 77 + OFFSET(REGS_B11, pt_regs, b11); 78 + OFFSET(REGS_B12, pt_regs, b12); 79 + OFFSET(REGS_B13, pt_regs, b13); 80 + OFFSET(REGS_DP, pt_regs, dp); 81 + OFFSET(REGS_SP, pt_regs, sp); 82 + 83 + OFFSET(REGS_TSR, pt_regs, tsr); 84 + OFFSET(REGS_ORIG_A4, pt_regs, orig_a4); 85 + 86 + DEFINE(REGS__END, sizeof(struct pt_regs)); 87 + BLANK(); 88 + 89 + OFFSET(THREAD_PC, thread_struct, pc); 90 + OFFSET(THREAD_B15_14, thread_struct, b15_14); 91 + OFFSET(THREAD_A15_14, thread_struct, a15_14); 92 + OFFSET(THREAD_B13_12, thread_struct, b13_12); 93 + OFFSET(THREAD_A13_12, thread_struct, a13_12); 94 + OFFSET(THREAD_B11_10, thread_struct, b11_10); 95 + OFFSET(THREAD_A11_10, thread_struct, a11_10); 96 + OFFSET(THREAD_RICL_ICL, thread_struct, ricl_icl); 97 + BLANK(); 98 + 99 + OFFSET(TASK_STATE, task_struct, state); 100 + BLANK(); 101 + 102 + OFFSET(THREAD_INFO_FLAGS, thread_info, flags); 103 + OFFSET(THREAD_INFO_PREEMPT_COUNT, thread_info, preempt_count); 104 + BLANK(); 105 + 106 + /* These would be unneccessary if we ran asm files 107 + * through the preprocessor. 108 + */ 109 + DEFINE(KTHREAD_SIZE, THREAD_SIZE); 110 + DEFINE(KTHREAD_SHIFT, THREAD_SHIFT); 111 + DEFINE(KTHREAD_START_SP, THREAD_START_SP); 112 + DEFINE(ENOSYS_, ENOSYS); 113 + DEFINE(NR_SYSCALLS_, __NR_syscalls); 114 + 115 + DEFINE(_TIF_SYSCALL_TRACE, (1<<TIF_SYSCALL_TRACE)); 116 + DEFINE(_TIF_NOTIFY_RESUME, (1<<TIF_NOTIFY_RESUME)); 117 + DEFINE(_TIF_SIGPENDING, (1<<TIF_SIGPENDING)); 118 + DEFINE(_TIF_NEED_RESCHED, (1<<TIF_NEED_RESCHED)); 119 + DEFINE(_TIF_POLLING_NRFLAG, (1<<TIF_POLLING_NRFLAG)); 120 + 121 + DEFINE(_TIF_ALLWORK_MASK, TIF_ALLWORK_MASK); 122 + DEFINE(_TIF_WORK_MASK, TIF_WORK_MASK); 123 + }
+803
arch/c6x/kernel/entry.S
··· 1 + ; 2 + ; Port on Texas Instruments TMS320C6x architecture 3 + ; 4 + ; Copyright (C) 2004-2011 Texas Instruments Incorporated 5 + ; Author: Aurelien Jacquiot (aurelien.jacquiot@virtuallogix.com) 6 + ; Updated for 2.6.34: Mark Salter <msalter@redhat.com> 7 + ; 8 + ; This program is free software; you can redistribute it and/or modify 9 + ; it under the terms of the GNU General Public License version 2 as 10 + ; published by the Free Software Foundation. 11 + ; 12 + 13 + #include <linux/sys.h> 14 + #include <linux/linkage.h> 15 + #include <asm/thread_info.h> 16 + #include <asm/asm-offsets.h> 17 + #include <asm/unistd.h> 18 + #include <asm/errno.h> 19 + 20 + ; Registers naming 21 + #define DP B14 22 + #define SP B15 23 + 24 + #ifndef CONFIG_PREEMPT 25 + #define resume_kernel restore_all 26 + #endif 27 + 28 + .altmacro 29 + 30 + .macro MASK_INT reg 31 + MVC .S2 CSR,reg 32 + CLR .S2 reg,0,0,reg 33 + MVC .S2 reg,CSR 34 + .endm 35 + 36 + .macro UNMASK_INT reg 37 + MVC .S2 CSR,reg 38 + SET .S2 reg,0,0,reg 39 + MVC .S2 reg,CSR 40 + .endm 41 + 42 + .macro GET_THREAD_INFO reg 43 + SHR .S1X SP,THREAD_SHIFT,reg 44 + SHL .S1 reg,THREAD_SHIFT,reg 45 + .endm 46 + 47 + ;; 48 + ;; This defines the normal kernel pt_regs layout. 49 + ;; 50 + .macro SAVE_ALL __rp __tsr 51 + STW .D2T2 B0,*SP--[2] ; save original B0 52 + MVKL .S2 current_ksp,B0 53 + MVKH .S2 current_ksp,B0 54 + LDW .D2T2 *B0,B1 ; KSP 55 + 56 + NOP 3 57 + STW .D2T2 B1,*+SP[1] ; save original B1 58 + XOR .D2 SP,B1,B0 ; (SP ^ KSP) 59 + LDW .D2T2 *+SP[1],B1 ; restore B0/B1 60 + LDW .D2T2 *++SP[2],B0 61 + SHR .S2 B0,THREAD_SHIFT,B0 ; 0 if already using kstack 62 + [B0] STDW .D2T2 SP:DP,*--B1[1] ; user: save user sp/dp kstack 63 + [B0] MV .S2 B1,SP ; and switch to kstack 64 + ||[!B0] STDW .D2T2 SP:DP,*--SP[1] ; kernel: save on current stack 65 + 66 + SUBAW .D2 SP,2,SP 67 + 68 + ADD .D1X SP,-8,A15 69 + || STDW .D2T1 A15:A14,*SP--[16] ; save A15:A14 70 + 71 + STDW .D2T2 B13:B12,*SP--[1] 72 + || STDW .D1T1 A13:A12,*A15--[1] 73 + || MVC .S2 __rp,B13 74 + 75 + STDW .D2T2 B11:B10,*SP--[1] 76 + || STDW .D1T1 A11:A10,*A15--[1] 77 + || MVC .S2 CSR,B12 78 + 79 + STDW .D2T2 B9:B8,*SP--[1] 80 + || STDW .D1T1 A9:A8,*A15--[1] 81 + || MVC .S2 RILC,B11 82 + STDW .D2T2 B7:B6,*SP--[1] 83 + || STDW .D1T1 A7:A6,*A15--[1] 84 + || MVC .S2 ILC,B10 85 + 86 + STDW .D2T2 B5:B4,*SP--[1] 87 + || STDW .D1T1 A5:A4,*A15--[1] 88 + 89 + STDW .D2T2 B3:B2,*SP--[1] 90 + || STDW .D1T1 A3:A2,*A15--[1] 91 + || MVC .S2 __tsr,B5 92 + 93 + STDW .D2T2 B1:B0,*SP--[1] 94 + || STDW .D1T1 A1:A0,*A15--[1] 95 + || MV .S1X B5,A5 96 + 97 + STDW .D2T2 B31:B30,*SP--[1] 98 + || STDW .D1T1 A31:A30,*A15--[1] 99 + STDW .D2T2 B29:B28,*SP--[1] 100 + || STDW .D1T1 A29:A28,*A15--[1] 101 + STDW .D2T2 B27:B26,*SP--[1] 102 + || STDW .D1T1 A27:A26,*A15--[1] 103 + STDW .D2T2 B25:B24,*SP--[1] 104 + || STDW .D1T1 A25:A24,*A15--[1] 105 + STDW .D2T2 B23:B22,*SP--[1] 106 + || STDW .D1T1 A23:A22,*A15--[1] 107 + STDW .D2T2 B21:B20,*SP--[1] 108 + || STDW .D1T1 A21:A20,*A15--[1] 109 + STDW .D2T2 B19:B18,*SP--[1] 110 + || STDW .D1T1 A19:A18,*A15--[1] 111 + STDW .D2T2 B17:B16,*SP--[1] 112 + || STDW .D1T1 A17:A16,*A15--[1] 113 + 114 + STDW .D2T2 B13:B12,*SP--[1] ; save PC and CSR 115 + 116 + STDW .D2T2 B11:B10,*SP--[1] ; save RILC and ILC 117 + STDW .D2T1 A5:A4,*SP--[1] ; save TSR and orig A4 118 + 119 + ;; We left an unused word on the stack just above pt_regs. 120 + ;; It is used to save whether or not this frame is due to 121 + ;; a syscall. It is cleared here, but the syscall handler 122 + ;; sets it to a non-zero value. 123 + MVK .L2 0,B1 124 + STW .D2T2 B1,*+SP(REGS__END+8) ; clear syscall flag 125 + .endm 126 + 127 + .macro RESTORE_ALL __rp __tsr 128 + LDDW .D2T2 *++SP[1],B9:B8 ; get TSR (B9) 129 + LDDW .D2T2 *++SP[1],B11:B10 ; get RILC (B11) and ILC (B10) 130 + LDDW .D2T2 *++SP[1],B13:B12 ; get PC (B13) and CSR (B12) 131 + 132 + ADDAW .D1X SP,30,A15 133 + 134 + LDDW .D1T1 *++A15[1],A17:A16 135 + || LDDW .D2T2 *++SP[1],B17:B16 136 + LDDW .D1T1 *++A15[1],A19:A18 137 + || LDDW .D2T2 *++SP[1],B19:B18 138 + LDDW .D1T1 *++A15[1],A21:A20 139 + || LDDW .D2T2 *++SP[1],B21:B20 140 + LDDW .D1T1 *++A15[1],A23:A22 141 + || LDDW .D2T2 *++SP[1],B23:B22 142 + LDDW .D1T1 *++A15[1],A25:A24 143 + || LDDW .D2T2 *++SP[1],B25:B24 144 + LDDW .D1T1 *++A15[1],A27:A26 145 + || LDDW .D2T2 *++SP[1],B27:B26 146 + LDDW .D1T1 *++A15[1],A29:A28 147 + || LDDW .D2T2 *++SP[1],B29:B28 148 + LDDW .D1T1 *++A15[1],A31:A30 149 + || LDDW .D2T2 *++SP[1],B31:B30 150 + 151 + LDDW .D1T1 *++A15[1],A1:A0 152 + || LDDW .D2T2 *++SP[1],B1:B0 153 + 154 + LDDW .D1T1 *++A15[1],A3:A2 155 + || LDDW .D2T2 *++SP[1],B3:B2 156 + || MVC .S2 B9,__tsr 157 + LDDW .D1T1 *++A15[1],A5:A4 158 + || LDDW .D2T2 *++SP[1],B5:B4 159 + || MVC .S2 B11,RILC 160 + LDDW .D1T1 *++A15[1],A7:A6 161 + || LDDW .D2T2 *++SP[1],B7:B6 162 + || MVC .S2 B10,ILC 163 + 164 + LDDW .D1T1 *++A15[1],A9:A8 165 + || LDDW .D2T2 *++SP[1],B9:B8 166 + || MVC .S2 B13,__rp 167 + 168 + LDDW .D1T1 *++A15[1],A11:A10 169 + || LDDW .D2T2 *++SP[1],B11:B10 170 + || MVC .S2 B12,CSR 171 + 172 + LDDW .D1T1 *++A15[1],A13:A12 173 + || LDDW .D2T2 *++SP[1],B13:B12 174 + 175 + MV .D2X A15,SP 176 + || MVKL .S1 current_ksp,A15 177 + MVKH .S1 current_ksp,A15 178 + || ADDAW .D1X SP,6,A14 179 + STW .D1T1 A14,*A15 ; save kernel stack pointer 180 + 181 + LDDW .D2T1 *++SP[1],A15:A14 182 + 183 + B .S2 __rp ; return from interruption 184 + LDDW .D2T2 *+SP[1],SP:DP 185 + NOP 4 186 + .endm 187 + 188 + .section .text 189 + 190 + ;; 191 + ;; Jump to schedule() then return to ret_from_exception 192 + ;; 193 + _reschedule: 194 + #ifdef CONFIG_C6X_BIG_KERNEL 195 + MVKL .S1 schedule,A0 196 + MVKH .S1 schedule,A0 197 + B .S2X A0 198 + #else 199 + B .S1 schedule 200 + #endif 201 + ADDKPC .S2 ret_from_exception,B3,4 202 + 203 + ;; 204 + ;; Called before syscall handler when process is being debugged 205 + ;; 206 + tracesys_on: 207 + #ifdef CONFIG_C6X_BIG_KERNEL 208 + MVKL .S1 syscall_trace_entry,A0 209 + MVKH .S1 syscall_trace_entry,A0 210 + B .S2X A0 211 + #else 212 + B .S1 syscall_trace_entry 213 + #endif 214 + ADDKPC .S2 ret_from_syscall_trace,B3,3 215 + ADD .S1X 8,SP,A4 216 + 217 + ret_from_syscall_trace: 218 + ;; tracing returns (possibly new) syscall number 219 + MV .D2X A4,B0 220 + || MVK .S2 __NR_syscalls,B1 221 + CMPLTU .L2 B0,B1,B1 222 + 223 + [!B1] BNOP .S2 ret_from_syscall_function,5 224 + || MVK .S1 -ENOSYS,A4 225 + 226 + ;; reload syscall args from (possibly modified) stack frame 227 + ;; and get syscall handler addr from sys_call_table: 228 + LDW .D2T2 *+SP(REGS_B4+8),B4 229 + || MVKL .S2 sys_call_table,B1 230 + LDW .D2T1 *+SP(REGS_A6+8),A6 231 + || MVKH .S2 sys_call_table,B1 232 + LDW .D2T2 *+B1[B0],B0 233 + || MVKL .S2 ret_from_syscall_function,B3 234 + LDW .D2T2 *+SP(REGS_B6+8),B6 235 + || MVKH .S2 ret_from_syscall_function,B3 236 + LDW .D2T1 *+SP(REGS_A8+8),A8 237 + LDW .D2T2 *+SP(REGS_B8+8),B8 238 + NOP 239 + ; B0 = sys_call_table[__NR_*] 240 + BNOP .S2 B0,5 ; branch to syscall handler 241 + || LDW .D2T1 *+SP(REGS_ORIG_A4+8),A4 242 + 243 + syscall_exit_work: 244 + AND .D1 _TIF_SYSCALL_TRACE,A2,A0 245 + [!A0] BNOP .S1 work_pending,5 246 + [A0] B .S2 syscall_trace_exit 247 + ADDKPC .S2 resume_userspace,B3,1 248 + MVC .S2 CSR,B1 249 + SET .S2 B1,0,0,B1 250 + MVC .S2 B1,CSR ; enable ints 251 + 252 + work_pending: 253 + AND .D1 _TIF_NEED_RESCHED,A2,A0 254 + [!A0] BNOP .S1 work_notifysig,5 255 + 256 + work_resched: 257 + #ifdef CONFIG_C6X_BIG_KERNEL 258 + MVKL .S1 schedule,A1 259 + MVKH .S1 schedule,A1 260 + B .S2X A1 261 + #else 262 + B .S2 schedule 263 + #endif 264 + ADDKPC .S2 work_rescheduled,B3,4 265 + work_rescheduled: 266 + ;; make sure we don't miss an interrupt setting need_resched or 267 + ;; sigpending between sampling and the rti 268 + MASK_INT B2 269 + GET_THREAD_INFO A12 270 + LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 271 + MVK .S1 _TIF_WORK_MASK,A1 272 + MVK .S1 _TIF_NEED_RESCHED,A3 273 + NOP 2 274 + AND .D1 A1,A2,A0 275 + || AND .S1 A3,A2,A1 276 + [!A0] BNOP .S1 restore_all,5 277 + [A1] BNOP .S1 work_resched,5 278 + 279 + work_notifysig: 280 + B .S2 do_notify_resume 281 + LDW .D2T1 *+SP(REGS__END+8),A6 ; syscall flag 282 + ADDKPC .S2 resume_userspace,B3,1 283 + ADD .S1X 8,SP,A4 ; pt_regs pointer is first arg 284 + MV .D2X A2,B4 ; thread_info flags is second arg 285 + 286 + ;; 287 + ;; On C64x+, the return way from exception and interrupt 288 + ;; is a little bit different 289 + ;; 290 + ENTRY(ret_from_exception) 291 + #ifdef CONFIG_PREEMPT 292 + MASK_INT B2 293 + #endif 294 + 295 + ENTRY(ret_from_interrupt) 296 + ;; 297 + ;; Check if we are comming from user mode. 298 + ;; 299 + LDW .D2T2 *+SP(REGS_TSR+8),B0 300 + MVK .S2 0x40,B1 301 + NOP 3 302 + AND .D2 B0,B1,B0 303 + [!B0] BNOP .S2 resume_kernel,5 304 + 305 + resume_userspace: 306 + ;; make sure we don't miss an interrupt setting need_resched or 307 + ;; sigpending between sampling and the rti 308 + MASK_INT B2 309 + GET_THREAD_INFO A12 310 + LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 311 + MVK .S1 _TIF_WORK_MASK,A1 312 + MVK .S1 _TIF_NEED_RESCHED,A3 313 + NOP 2 314 + AND .D1 A1,A2,A0 315 + [A0] BNOP .S1 work_pending,5 316 + BNOP .S1 restore_all,5 317 + 318 + ;; 319 + ;; System call handling 320 + ;; B0 = syscall number (in sys_call_table) 321 + ;; A4,B4,A6,B6,A8,B8 = arguments of the syscall function 322 + ;; A4 is the return value register 323 + ;; 324 + system_call_saved: 325 + MVK .L2 1,B2 326 + STW .D2T2 B2,*+SP(REGS__END+8) ; set syscall flag 327 + MVC .S2 B2,ECR ; ack the software exception 328 + 329 + UNMASK_INT B2 ; re-enable global IT 330 + 331 + system_call_saved_noack: 332 + ;; Check system call number 333 + MVK .S2 __NR_syscalls,B1 334 + #ifdef CONFIG_C6X_BIG_KERNEL 335 + || MVKL .S1 sys_ni_syscall,A0 336 + #endif 337 + CMPLTU .L2 B0,B1,B1 338 + #ifdef CONFIG_C6X_BIG_KERNEL 339 + || MVKH .S1 sys_ni_syscall,A0 340 + #endif 341 + 342 + ;; Check for ptrace 343 + GET_THREAD_INFO A12 344 + 345 + #ifdef CONFIG_C6X_BIG_KERNEL 346 + [!B1] B .S2X A0 347 + #else 348 + [!B1] B .S2 sys_ni_syscall 349 + #endif 350 + [!B1] ADDKPC .S2 ret_from_syscall_function,B3,4 351 + 352 + ;; Get syscall handler addr from sys_call_table 353 + ;; call tracesys_on or call syscall handler 354 + LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 355 + || MVKL .S2 sys_call_table,B1 356 + MVKH .S2 sys_call_table,B1 357 + LDW .D2T2 *+B1[B0],B0 358 + NOP 2 359 + ; A2 = thread_info flags 360 + AND .D1 _TIF_SYSCALL_TRACE,A2,A2 361 + [A2] BNOP .S1 tracesys_on,5 362 + ;; B0 = _sys_call_table[__NR_*] 363 + B .S2 B0 364 + ADDKPC .S2 ret_from_syscall_function,B3,4 365 + 366 + ret_from_syscall_function: 367 + STW .D2T1 A4,*+SP(REGS_A4+8) ; save return value in A4 368 + ; original A4 is in orig_A4 369 + syscall_exit: 370 + ;; make sure we don't miss an interrupt setting need_resched or 371 + ;; sigpending between sampling and the rti 372 + MASK_INT B2 373 + LDW .D1T1 *+A12(THREAD_INFO_FLAGS),A2 374 + MVK .S1 _TIF_ALLWORK_MASK,A1 375 + NOP 3 376 + AND .D1 A1,A2,A2 ; check for work to do 377 + [A2] BNOP .S1 syscall_exit_work,5 378 + 379 + restore_all: 380 + RESTORE_ALL NRP,NTSR 381 + 382 + ;; 383 + ;; After a fork we jump here directly from resume, 384 + ;; so that A4 contains the previous task structure. 385 + ;; 386 + ENTRY(ret_from_fork) 387 + #ifdef CONFIG_C6X_BIG_KERNEL 388 + MVKL .S1 schedule_tail,A0 389 + MVKH .S1 schedule_tail,A0 390 + B .S2X A0 391 + #else 392 + B .S2 schedule_tail 393 + #endif 394 + ADDKPC .S2 ret_from_fork_2,B3,4 395 + ret_from_fork_2: 396 + ;; return 0 in A4 for child process 397 + GET_THREAD_INFO A12 398 + BNOP .S2 syscall_exit,3 399 + MVK .L2 0,B0 400 + STW .D2T2 B0,*+SP(REGS_A4+8) 401 + ENDPROC(ret_from_fork) 402 + 403 + ;; 404 + ;; These are the interrupt handlers, responsible for calling __do_IRQ() 405 + ;; int6 is used for syscalls (see _system_call entry) 406 + ;; 407 + .macro SAVE_ALL_INT 408 + SAVE_ALL IRP,ITSR 409 + .endm 410 + 411 + .macro CALL_INT int 412 + #ifdef CONFIG_C6X_BIG_KERNEL 413 + MVKL .S1 c6x_do_IRQ,A0 414 + MVKH .S1 c6x_do_IRQ,A0 415 + BNOP .S2X A0,1 416 + MVK .S1 int,A4 417 + ADDAW .D2 SP,2,B4 418 + MVKL .S2 ret_from_interrupt,B3 419 + MVKH .S2 ret_from_interrupt,B3 420 + #else 421 + CALLP .S2 c6x_do_IRQ,B3 422 + || MVK .S1 int,A4 423 + || ADDAW .D2 SP,2,B4 424 + B .S1 ret_from_interrupt 425 + NOP 5 426 + #endif 427 + .endm 428 + 429 + ENTRY(_int4_handler) 430 + SAVE_ALL_INT 431 + CALL_INT 4 432 + ENDPROC(_int4_handler) 433 + 434 + ENTRY(_int5_handler) 435 + SAVE_ALL_INT 436 + CALL_INT 5 437 + ENDPROC(_int5_handler) 438 + 439 + ENTRY(_int6_handler) 440 + SAVE_ALL_INT 441 + CALL_INT 6 442 + ENDPROC(_int6_handler) 443 + 444 + ENTRY(_int7_handler) 445 + SAVE_ALL_INT 446 + CALL_INT 7 447 + ENDPROC(_int7_handler) 448 + 449 + ENTRY(_int8_handler) 450 + SAVE_ALL_INT 451 + CALL_INT 8 452 + ENDPROC(_int8_handler) 453 + 454 + ENTRY(_int9_handler) 455 + SAVE_ALL_INT 456 + CALL_INT 9 457 + ENDPROC(_int9_handler) 458 + 459 + ENTRY(_int10_handler) 460 + SAVE_ALL_INT 461 + CALL_INT 10 462 + ENDPROC(_int10_handler) 463 + 464 + ENTRY(_int11_handler) 465 + SAVE_ALL_INT 466 + CALL_INT 11 467 + ENDPROC(_int11_handler) 468 + 469 + ENTRY(_int12_handler) 470 + SAVE_ALL_INT 471 + CALL_INT 12 472 + ENDPROC(_int12_handler) 473 + 474 + ENTRY(_int13_handler) 475 + SAVE_ALL_INT 476 + CALL_INT 13 477 + ENDPROC(_int13_handler) 478 + 479 + ENTRY(_int14_handler) 480 + SAVE_ALL_INT 481 + CALL_INT 14 482 + ENDPROC(_int14_handler) 483 + 484 + ENTRY(_int15_handler) 485 + SAVE_ALL_INT 486 + CALL_INT 15 487 + ENDPROC(_int15_handler) 488 + 489 + ;; 490 + ;; Handler for uninitialized and spurious interrupts 491 + ;; 492 + ENTRY(_bad_interrupt) 493 + B .S2 IRP 494 + NOP 5 495 + ENDPROC(_bad_interrupt) 496 + 497 + ;; 498 + ;; Entry for NMI/exceptions/syscall 499 + ;; 500 + ENTRY(_nmi_handler) 501 + SAVE_ALL NRP,NTSR 502 + 503 + MVC .S2 EFR,B2 504 + CMPEQ .L2 1,B2,B2 505 + || MVC .S2 TSR,B1 506 + CLR .S2 B1,10,10,B1 507 + MVC .S2 B1,TSR 508 + #ifdef CONFIG_C6X_BIG_KERNEL 509 + [!B2] MVKL .S1 process_exception,A0 510 + [!B2] MVKH .S1 process_exception,A0 511 + [!B2] B .S2X A0 512 + #else 513 + [!B2] B .S2 process_exception 514 + #endif 515 + [B2] B .S2 system_call_saved 516 + [!B2] ADDAW .D2 SP,2,B1 517 + [!B2] MV .D1X B1,A4 518 + ADDKPC .S2 ret_from_trap,B3,2 519 + 520 + ret_from_trap: 521 + MV .D2X A4,B0 522 + [!B0] BNOP .S2 ret_from_exception,5 523 + 524 + #ifdef CONFIG_C6X_BIG_KERNEL 525 + MVKL .S2 system_call_saved_noack,B3 526 + MVKH .S2 system_call_saved_noack,B3 527 + #endif 528 + LDW .D2T2 *+SP(REGS_B0+8),B0 529 + LDW .D2T1 *+SP(REGS_A4+8),A4 530 + LDW .D2T2 *+SP(REGS_B4+8),B4 531 + LDW .D2T1 *+SP(REGS_A6+8),A6 532 + LDW .D2T2 *+SP(REGS_B6+8),B6 533 + LDW .D2T1 *+SP(REGS_A8+8),A8 534 + #ifdef CONFIG_C6X_BIG_KERNEL 535 + || B .S2 B3 536 + #else 537 + || B .S2 system_call_saved_noack 538 + #endif 539 + LDW .D2T2 *+SP(REGS_B8+8),B8 540 + NOP 4 541 + ENDPROC(_nmi_handler) 542 + 543 + ;; 544 + ;; Jump to schedule() then return to ret_from_isr 545 + ;; 546 + #ifdef CONFIG_PREEMPT 547 + resume_kernel: 548 + GET_THREAD_INFO A12 549 + LDW .D1T1 *+A12(THREAD_INFO_PREEMPT_COUNT),A1 550 + NOP 4 551 + [A1] BNOP .S2 restore_all,5 552 + 553 + preempt_schedule: 554 + GET_THREAD_INFO A2 555 + LDW .D1T1 *+A2(THREAD_INFO_FLAGS),A1 556 + #ifdef CONFIG_C6X_BIG_KERNEL 557 + MVKL .S2 preempt_schedule_irq,B0 558 + MVKH .S2 preempt_schedule_irq,B0 559 + NOP 2 560 + #else 561 + NOP 4 562 + #endif 563 + AND .D1 _TIF_NEED_RESCHED,A1,A1 564 + [!A1] BNOP .S2 restore_all,5 565 + #ifdef CONFIG_C6X_BIG_KERNEL 566 + B .S2 B0 567 + #else 568 + B .S2 preempt_schedule_irq 569 + #endif 570 + ADDKPC .S2 preempt_schedule,B3,4 571 + #endif /* CONFIG_PREEMPT */ 572 + 573 + ENTRY(enable_exception) 574 + DINT 575 + MVC .S2 TSR,B0 576 + MVC .S2 B3,NRP 577 + MVK .L2 0xc,B1 578 + OR .D2 B0,B1,B0 579 + MVC .S2 B0,TSR ; Set GEE and XEN in TSR 580 + B .S2 NRP 581 + NOP 5 582 + ENDPROC(enable_exception) 583 + 584 + ENTRY(sys_sigaltstack) 585 + #ifdef CONFIG_C6X_BIG_KERNEL 586 + MVKL .S1 do_sigaltstack,A0 ; branch to do_sigaltstack 587 + MVKH .S1 do_sigaltstack,A0 588 + B .S2X A0 589 + #else 590 + B .S2 do_sigaltstack 591 + #endif 592 + LDW .D2T1 *+SP(REGS_SP+8),A6 593 + NOP 4 594 + ENDPROC(sys_sigaltstack) 595 + 596 + ;; kernel_execve 597 + ENTRY(kernel_execve) 598 + MVK .S2 __NR_execve,B0 599 + SWE 600 + BNOP .S2 B3,5 601 + ENDPROC(kernel_execve) 602 + 603 + ;; 604 + ;; Special system calls 605 + ;; return address is in B3 606 + ;; 607 + ENTRY(sys_clone) 608 + ADD .D1X SP,8,A4 609 + #ifdef CONFIG_C6X_BIG_KERNEL 610 + || MVKL .S1 sys_c6x_clone,A0 611 + MVKH .S1 sys_c6x_clone,A0 612 + BNOP .S2X A0,5 613 + #else 614 + || B .S2 sys_c6x_clone 615 + NOP 5 616 + #endif 617 + ENDPROC(sys_clone) 618 + 619 + ENTRY(sys_rt_sigreturn) 620 + ADD .D1X SP,8,A4 621 + #ifdef CONFIG_C6X_BIG_KERNEL 622 + || MVKL .S1 do_rt_sigreturn,A0 623 + MVKH .S1 do_rt_sigreturn,A0 624 + BNOP .S2X A0,5 625 + #else 626 + || B .S2 do_rt_sigreturn 627 + NOP 5 628 + #endif 629 + ENDPROC(sys_rt_sigreturn) 630 + 631 + ENTRY(sys_execve) 632 + ADDAW .D2 SP,2,B6 ; put regs addr in 4th parameter 633 + ; & adjust regs stack addr 634 + LDW .D2T2 *+SP(REGS_B4+8),B4 635 + 636 + ;; c6x_execve(char *name, char **argv, 637 + ;; char **envp, struct pt_regs *regs) 638 + #ifdef CONFIG_C6X_BIG_KERNEL 639 + || MVKL .S1 sys_c6x_execve,A0 640 + MVKH .S1 sys_c6x_execve,A0 641 + B .S2X A0 642 + #else 643 + || B .S2 sys_c6x_execve 644 + #endif 645 + STW .D2T2 B3,*SP--[2] 646 + ADDKPC .S2 ret_from_c6x_execve,B3,3 647 + 648 + ret_from_c6x_execve: 649 + LDW .D2T2 *++SP[2],B3 650 + NOP 4 651 + BNOP .S2 B3,5 652 + ENDPROC(sys_execve) 653 + 654 + ENTRY(sys_pread_c6x) 655 + MV .D2X A8,B7 656 + #ifdef CONFIG_C6X_BIG_KERNEL 657 + || MVKL .S1 sys_pread64,A0 658 + MVKH .S1 sys_pread64,A0 659 + BNOP .S2X A0,5 660 + #else 661 + || B .S2 sys_pread64 662 + NOP 5 663 + #endif 664 + ENDPROC(sys_pread_c6x) 665 + 666 + ENTRY(sys_pwrite_c6x) 667 + MV .D2X A8,B7 668 + #ifdef CONFIG_C6X_BIG_KERNEL 669 + || MVKL .S1 sys_pwrite64,A0 670 + MVKH .S1 sys_pwrite64,A0 671 + BNOP .S2X A0,5 672 + #else 673 + || B .S2 sys_pwrite64 674 + NOP 5 675 + #endif 676 + ENDPROC(sys_pwrite_c6x) 677 + 678 + ;; On Entry 679 + ;; A4 - path 680 + ;; B4 - offset_lo (LE), offset_hi (BE) 681 + ;; A6 - offset_lo (BE), offset_hi (LE) 682 + ENTRY(sys_truncate64_c6x) 683 + #ifdef CONFIG_CPU_BIG_ENDIAN 684 + MV .S2 B4,B5 685 + MV .D2X A6,B4 686 + #else 687 + MV .D2X A6,B5 688 + #endif 689 + #ifdef CONFIG_C6X_BIG_KERNEL 690 + || MVKL .S1 sys_truncate64,A0 691 + MVKH .S1 sys_truncate64,A0 692 + BNOP .S2X A0,5 693 + #else 694 + || B .S2 sys_truncate64 695 + NOP 5 696 + #endif 697 + ENDPROC(sys_truncate64_c6x) 698 + 699 + ;; On Entry 700 + ;; A4 - fd 701 + ;; B4 - offset_lo (LE), offset_hi (BE) 702 + ;; A6 - offset_lo (BE), offset_hi (LE) 703 + ENTRY(sys_ftruncate64_c6x) 704 + #ifdef CONFIG_CPU_BIG_ENDIAN 705 + MV .S2 B4,B5 706 + MV .D2X A6,B4 707 + #else 708 + MV .D2X A6,B5 709 + #endif 710 + #ifdef CONFIG_C6X_BIG_KERNEL 711 + || MVKL .S1 sys_ftruncate64,A0 712 + MVKH .S1 sys_ftruncate64,A0 713 + BNOP .S2X A0,5 714 + #else 715 + || B .S2 sys_ftruncate64 716 + NOP 5 717 + #endif 718 + ENDPROC(sys_ftruncate64_c6x) 719 + 720 + #ifdef __ARCH_WANT_SYSCALL_OFF_T 721 + ;; On Entry 722 + ;; A4 - fd 723 + ;; B4 - offset_lo (LE), offset_hi (BE) 724 + ;; A6 - offset_lo (BE), offset_hi (LE) 725 + ;; B6 - len 726 + ;; A8 - advice 727 + ENTRY(sys_fadvise64_c6x) 728 + #ifdef CONFIG_C6X_BIG_KERNEL 729 + MVKL .S1 sys_fadvise64,A0 730 + MVKH .S1 sys_fadvise64,A0 731 + BNOP .S2X A0,2 732 + #else 733 + B .S2 sys_fadvise64 734 + NOP 2 735 + #endif 736 + #ifdef CONFIG_CPU_BIG_ENDIAN 737 + MV .L2 B4,B5 738 + || MV .D2X A6,B4 739 + #else 740 + MV .D2X A6,B5 741 + #endif 742 + MV .D1X B6,A6 743 + MV .D2X A8,B6 744 + #endif 745 + ENDPROC(sys_fadvise64_c6x) 746 + 747 + ;; On Entry 748 + ;; A4 - fd 749 + ;; B4 - offset_lo (LE), offset_hi (BE) 750 + ;; A6 - offset_lo (BE), offset_hi (LE) 751 + ;; B6 - len_lo (LE), len_hi (BE) 752 + ;; A8 - len_lo (BE), len_hi (LE) 753 + ;; B8 - advice 754 + ENTRY(sys_fadvise64_64_c6x) 755 + #ifdef CONFIG_C6X_BIG_KERNEL 756 + MVKL .S1 sys_fadvise64_64,A0 757 + MVKH .S1 sys_fadvise64_64,A0 758 + BNOP .S2X A0,2 759 + #else 760 + B .S2 sys_fadvise64_64 761 + NOP 2 762 + #endif 763 + #ifdef CONFIG_CPU_BIG_ENDIAN 764 + MV .L2 B4,B5 765 + || MV .D2X A6,B4 766 + MV .L1 A8,A6 767 + || MV .D1X B6,A7 768 + #else 769 + MV .D2X A6,B5 770 + MV .L1 A8,A7 771 + || MV .D1X B6,A6 772 + #endif 773 + MV .L2 B8,B6 774 + ENDPROC(sys_fadvise64_64_c6x) 775 + 776 + ;; On Entry 777 + ;; A4 - fd 778 + ;; B4 - mode 779 + ;; A6 - offset_hi 780 + ;; B6 - offset_lo 781 + ;; A8 - len_hi 782 + ;; B8 - len_lo 783 + ENTRY(sys_fallocate_c6x) 784 + #ifdef CONFIG_C6X_BIG_KERNEL 785 + MVKL .S1 sys_fallocate,A0 786 + MVKH .S1 sys_fallocate,A0 787 + BNOP .S2X A0,1 788 + #else 789 + B .S2 sys_fallocate 790 + NOP 791 + #endif 792 + MV .D1 A6,A7 793 + MV .D1X B6,A6 794 + MV .D2X A8,B7 795 + MV .D2 B8,B6 796 + ENDPROC(sys_fallocate_c6x) 797 + 798 + ;; put this in .neardata for faster access when using DSBT mode 799 + .section .neardata,"aw",@progbits 800 + .global current_ksp 801 + .hidden current_ksp 802 + current_ksp: 803 + .word init_thread_union + THREAD_START_SP
+423
arch/c6x/kernel/traps.c
··· 1 + /* 2 + * Port on Texas Instruments TMS320C6x architecture 3 + * 4 + * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated 5 + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + #include <linux/module.h> 12 + #include <linux/ptrace.h> 13 + #include <linux/kallsyms.h> 14 + #include <linux/bug.h> 15 + 16 + #include <asm/soc.h> 17 + #include <asm/traps.h> 18 + 19 + int (*c6x_nmi_handler)(struct pt_regs *regs); 20 + 21 + void __init trap_init(void) 22 + { 23 + ack_exception(EXCEPT_TYPE_NXF); 24 + ack_exception(EXCEPT_TYPE_EXC); 25 + ack_exception(EXCEPT_TYPE_IXF); 26 + ack_exception(EXCEPT_TYPE_SXF); 27 + enable_exception(); 28 + } 29 + 30 + void show_regs(struct pt_regs *regs) 31 + { 32 + pr_err("\n"); 33 + pr_err("PC: %08lx SP: %08lx\n", regs->pc, regs->sp); 34 + pr_err("Status: %08lx ORIG_A4: %08lx\n", regs->csr, regs->orig_a4); 35 + pr_err("A0: %08lx B0: %08lx\n", regs->a0, regs->b0); 36 + pr_err("A1: %08lx B1: %08lx\n", regs->a1, regs->b1); 37 + pr_err("A2: %08lx B2: %08lx\n", regs->a2, regs->b2); 38 + pr_err("A3: %08lx B3: %08lx\n", regs->a3, regs->b3); 39 + pr_err("A4: %08lx B4: %08lx\n", regs->a4, regs->b4); 40 + pr_err("A5: %08lx B5: %08lx\n", regs->a5, regs->b5); 41 + pr_err("A6: %08lx B6: %08lx\n", regs->a6, regs->b6); 42 + pr_err("A7: %08lx B7: %08lx\n", regs->a7, regs->b7); 43 + pr_err("A8: %08lx B8: %08lx\n", regs->a8, regs->b8); 44 + pr_err("A9: %08lx B9: %08lx\n", regs->a9, regs->b9); 45 + pr_err("A10: %08lx B10: %08lx\n", regs->a10, regs->b10); 46 + pr_err("A11: %08lx B11: %08lx\n", regs->a11, regs->b11); 47 + pr_err("A12: %08lx B12: %08lx\n", regs->a12, regs->b12); 48 + pr_err("A13: %08lx B13: %08lx\n", regs->a13, regs->b13); 49 + pr_err("A14: %08lx B14: %08lx\n", regs->a14, regs->dp); 50 + pr_err("A15: %08lx B15: %08lx\n", regs->a15, regs->sp); 51 + pr_err("A16: %08lx B16: %08lx\n", regs->a16, regs->b16); 52 + pr_err("A17: %08lx B17: %08lx\n", regs->a17, regs->b17); 53 + pr_err("A18: %08lx B18: %08lx\n", regs->a18, regs->b18); 54 + pr_err("A19: %08lx B19: %08lx\n", regs->a19, regs->b19); 55 + pr_err("A20: %08lx B20: %08lx\n", regs->a20, regs->b20); 56 + pr_err("A21: %08lx B21: %08lx\n", regs->a21, regs->b21); 57 + pr_err("A22: %08lx B22: %08lx\n", regs->a22, regs->b22); 58 + pr_err("A23: %08lx B23: %08lx\n", regs->a23, regs->b23); 59 + pr_err("A24: %08lx B24: %08lx\n", regs->a24, regs->b24); 60 + pr_err("A25: %08lx B25: %08lx\n", regs->a25, regs->b25); 61 + pr_err("A26: %08lx B26: %08lx\n", regs->a26, regs->b26); 62 + pr_err("A27: %08lx B27: %08lx\n", regs->a27, regs->b27); 63 + pr_err("A28: %08lx B28: %08lx\n", regs->a28, regs->b28); 64 + pr_err("A29: %08lx B29: %08lx\n", regs->a29, regs->b29); 65 + pr_err("A30: %08lx B30: %08lx\n", regs->a30, regs->b30); 66 + pr_err("A31: %08lx B31: %08lx\n", regs->a31, regs->b31); 67 + } 68 + 69 + void dump_stack(void) 70 + { 71 + unsigned long stack; 72 + 73 + show_stack(current, &stack); 74 + } 75 + EXPORT_SYMBOL(dump_stack); 76 + 77 + 78 + void die(char *str, struct pt_regs *fp, int nr) 79 + { 80 + console_verbose(); 81 + pr_err("%s: %08x\n", str, nr); 82 + show_regs(fp); 83 + 84 + pr_err("Process %s (pid: %d, stackpage=%08lx)\n", 85 + current->comm, current->pid, (PAGE_SIZE + 86 + (unsigned long) current)); 87 + 88 + dump_stack(); 89 + while (1) 90 + ; 91 + } 92 + 93 + static void die_if_kernel(char *str, struct pt_regs *fp, int nr) 94 + { 95 + if (user_mode(fp)) 96 + return; 97 + 98 + die(str, fp, nr); 99 + } 100 + 101 + 102 + /* Internal exceptions */ 103 + static struct exception_info iexcept_table[10] = { 104 + { "Oops - instruction fetch", SIGBUS, BUS_ADRERR }, 105 + { "Oops - fetch packet", SIGBUS, BUS_ADRERR }, 106 + { "Oops - execute packet", SIGILL, ILL_ILLOPC }, 107 + { "Oops - undefined instruction", SIGILL, ILL_ILLOPC }, 108 + { "Oops - resource conflict", SIGILL, ILL_ILLOPC }, 109 + { "Oops - resource access", SIGILL, ILL_PRVREG }, 110 + { "Oops - privilege", SIGILL, ILL_PRVOPC }, 111 + { "Oops - loops buffer", SIGILL, ILL_ILLOPC }, 112 + { "Oops - software exception", SIGILL, ILL_ILLTRP }, 113 + { "Oops - unknown exception", SIGILL, ILL_ILLOPC } 114 + }; 115 + 116 + /* External exceptions */ 117 + static struct exception_info eexcept_table[128] = { 118 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 119 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 120 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 121 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 122 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 123 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 124 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 125 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 126 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 127 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 128 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 129 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 130 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 131 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 132 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 133 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 134 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 135 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 136 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 137 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 138 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 139 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 140 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 141 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 142 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 143 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 144 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 145 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 146 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 147 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 148 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 149 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 150 + 151 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 152 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 153 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 154 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 155 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 156 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 157 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 158 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 159 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 160 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 161 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 162 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 163 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 164 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 165 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 166 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 167 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 168 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 169 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 170 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 171 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 172 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 173 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 174 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 175 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 176 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 177 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 178 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 179 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 180 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 181 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 182 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 183 + 184 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 185 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 186 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 187 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 188 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 189 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 190 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 191 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 192 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 193 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 194 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 195 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 196 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 197 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 198 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 199 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 200 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 201 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 202 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 203 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 204 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 205 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 206 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 207 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 208 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 209 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 210 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 211 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 212 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 213 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 214 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 215 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 216 + 217 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 218 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 219 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 220 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 221 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 222 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 223 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 224 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 225 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 226 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 227 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 228 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 229 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 230 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 231 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 232 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 233 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 234 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 235 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 236 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 237 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 238 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 239 + { "Oops - external exception", SIGBUS, BUS_ADRERR }, 240 + { "Oops - CPU memory protection fault", SIGSEGV, SEGV_ACCERR }, 241 + { "Oops - CPU memory protection fault in L1P", SIGSEGV, SEGV_ACCERR }, 242 + { "Oops - DMA memory protection fault in L1P", SIGSEGV, SEGV_ACCERR }, 243 + { "Oops - CPU memory protection fault in L1D", SIGSEGV, SEGV_ACCERR }, 244 + { "Oops - DMA memory protection fault in L1D", SIGSEGV, SEGV_ACCERR }, 245 + { "Oops - CPU memory protection fault in L2", SIGSEGV, SEGV_ACCERR }, 246 + { "Oops - DMA memory protection fault in L2", SIGSEGV, SEGV_ACCERR }, 247 + { "Oops - EMC CPU memory protection fault", SIGSEGV, SEGV_ACCERR }, 248 + { "Oops - EMC bus error", SIGBUS, BUS_ADRERR } 249 + }; 250 + 251 + static void do_trap(struct exception_info *except_info, struct pt_regs *regs) 252 + { 253 + unsigned long addr = instruction_pointer(regs); 254 + siginfo_t info; 255 + 256 + if (except_info->code != TRAP_BRKPT) 257 + pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n", 258 + except_info->kernel_str, regs->pc, 259 + except_info->signo, except_info->code); 260 + 261 + die_if_kernel(except_info->kernel_str, regs, addr); 262 + 263 + info.si_signo = except_info->signo; 264 + info.si_errno = 0; 265 + info.si_code = except_info->code; 266 + info.si_addr = (void __user *)addr; 267 + 268 + force_sig_info(except_info->signo, &info, current); 269 + } 270 + 271 + /* 272 + * Process an internal exception (non maskable) 273 + */ 274 + static int process_iexcept(struct pt_regs *regs) 275 + { 276 + unsigned int iexcept_report = get_iexcept(); 277 + unsigned int iexcept_num; 278 + 279 + ack_exception(EXCEPT_TYPE_IXF); 280 + 281 + pr_err("IEXCEPT: PC[0x%lx]\n", regs->pc); 282 + 283 + while (iexcept_report) { 284 + iexcept_num = __ffs(iexcept_report); 285 + iexcept_report &= ~(1 << iexcept_num); 286 + set_iexcept(iexcept_report); 287 + if (*(unsigned int *)regs->pc == BKPT_OPCODE) { 288 + /* This is a breakpoint */ 289 + struct exception_info bkpt_exception = { 290 + "Oops - undefined instruction", 291 + SIGTRAP, TRAP_BRKPT 292 + }; 293 + do_trap(&bkpt_exception, regs); 294 + iexcept_report &= ~(0xFF); 295 + set_iexcept(iexcept_report); 296 + continue; 297 + } 298 + 299 + do_trap(&iexcept_table[iexcept_num], regs); 300 + } 301 + return 0; 302 + } 303 + 304 + /* 305 + * Process an external exception (maskable) 306 + */ 307 + static void process_eexcept(struct pt_regs *regs) 308 + { 309 + int evt; 310 + 311 + pr_err("EEXCEPT: PC[0x%lx]\n", regs->pc); 312 + 313 + while ((evt = soc_get_exception()) >= 0) 314 + do_trap(&eexcept_table[evt], regs); 315 + 316 + ack_exception(EXCEPT_TYPE_EXC); 317 + } 318 + 319 + /* 320 + * Main exception processing 321 + */ 322 + asmlinkage int process_exception(struct pt_regs *regs) 323 + { 324 + unsigned int type; 325 + unsigned int type_num; 326 + unsigned int ie_num = 9; /* default is unknown exception */ 327 + 328 + while ((type = get_except_type()) != 0) { 329 + type_num = fls(type) - 1; 330 + 331 + switch (type_num) { 332 + case EXCEPT_TYPE_NXF: 333 + ack_exception(EXCEPT_TYPE_NXF); 334 + if (c6x_nmi_handler) 335 + (c6x_nmi_handler)(regs); 336 + else 337 + pr_alert("NMI interrupt!\n"); 338 + break; 339 + 340 + case EXCEPT_TYPE_IXF: 341 + if (process_iexcept(regs)) 342 + return 1; 343 + break; 344 + 345 + case EXCEPT_TYPE_EXC: 346 + process_eexcept(regs); 347 + break; 348 + 349 + case EXCEPT_TYPE_SXF: 350 + ie_num = 8; 351 + default: 352 + ack_exception(type_num); 353 + do_trap(&iexcept_table[ie_num], regs); 354 + break; 355 + } 356 + } 357 + return 0; 358 + } 359 + 360 + static int kstack_depth_to_print = 48; 361 + 362 + static void show_trace(unsigned long *stack, unsigned long *endstack) 363 + { 364 + unsigned long addr; 365 + int i; 366 + 367 + pr_debug("Call trace:"); 368 + i = 0; 369 + while (stack + 1 <= endstack) { 370 + addr = *stack++; 371 + /* 372 + * If the address is either in the text segment of the 373 + * kernel, or in the region which contains vmalloc'ed 374 + * memory, it *may* be the address of a calling 375 + * routine; if so, print it so that someone tracing 376 + * down the cause of the crash will be able to figure 377 + * out the call path that was taken. 378 + */ 379 + if (__kernel_text_address(addr)) { 380 + #ifndef CONFIG_KALLSYMS 381 + if (i % 5 == 0) 382 + pr_debug("\n "); 383 + #endif 384 + pr_debug(" [<%08lx>]", addr); 385 + print_symbol(" %s\n", addr); 386 + i++; 387 + } 388 + } 389 + pr_debug("\n"); 390 + } 391 + 392 + void show_stack(struct task_struct *task, unsigned long *stack) 393 + { 394 + unsigned long *p, *endstack; 395 + int i; 396 + 397 + if (!stack) { 398 + if (task && task != current) 399 + /* We know this is a kernel stack, 400 + so this is the start/end */ 401 + stack = (unsigned long *)thread_saved_ksp(task); 402 + else 403 + stack = (unsigned long *)&stack; 404 + } 405 + endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) 406 + & -THREAD_SIZE); 407 + 408 + pr_debug("Stack from %08lx:", (unsigned long)stack); 409 + for (i = 0, p = stack; i < kstack_depth_to_print; i++) { 410 + if (p + 1 > endstack) 411 + break; 412 + if (i % 8 == 0) 413 + pr_cont("\n "); 414 + pr_cont(" %08lx", *p++); 415 + } 416 + pr_cont("\n"); 417 + show_trace(stack, endstack); 418 + } 419 + 420 + int is_valid_bugaddr(unsigned long addr) 421 + { 422 + return __kernel_text_address(addr); 423 + }