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

sh: Exception vector rework and SH-2/SH-2A support.

This splits out common bits from the existing exception handler for
use between SH-2/SH-2A and SH-3/4, and adds support for the SH-2/2A
exceptions.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Yoshinori Sato and committed by
Paul Mundt
de398406 0983b318

+767 -332
+325
arch/sh/kernel/cpu/sh2/entry.S
··· 1 + /* 2 + * arch/sh/kernel/cpu/sh2/entry.S 3 + * 4 + * The SH-2 exception entry 5 + * 6 + * Copyright (C) 2005,2006 Yoshinori Sato 7 + * Copyright (C) 2005 AXE,Inc. 8 + * 9 + * This file is subject to the terms and conditions of the GNU General Public 10 + * License. See the file "COPYING" in the main directory of this archive 11 + * for more details. 12 + */ 13 + 14 + #include <linux/linkage.h> 15 + #include <asm/asm-offsets.h> 16 + #include <asm/thread_info.h> 17 + #include <asm/cpu/mmu_context.h> 18 + #include <asm/unistd.h> 19 + #include <asm/errno.h> 20 + #include <asm/page.h> 21 + 22 + /* Offsets to the stack */ 23 + OFF_R0 = 0 /* Return value. New ABI also arg4 */ 24 + OFF_R1 = 4 /* New ABI: arg5 */ 25 + OFF_R2 = 8 /* New ABI: arg6 */ 26 + OFF_R3 = 12 /* New ABI: syscall_nr */ 27 + OFF_R4 = 16 /* New ABI: arg0 */ 28 + OFF_R5 = 20 /* New ABI: arg1 */ 29 + OFF_R6 = 24 /* New ABI: arg2 */ 30 + OFF_R7 = 28 /* New ABI: arg3 */ 31 + OFF_SP = (15*4) 32 + OFF_PC = (16*4) 33 + OFF_SR = (16*4+2*4) 34 + OFF_TRA = (16*4+6*4) 35 + 36 + #include <asm/entry-macros.S> 37 + 38 + ENTRY(exception_handler) 39 + ! already saved r0/r1 40 + mov.l r2,@-sp 41 + mov.l r3,@-sp 42 + mov r0,r1 43 + cli 44 + mov.l $cpu_mode,r2 45 + mov.l @r2,r0 46 + mov.l @(5*4,r15),r3 ! previous SR 47 + shll2 r3 ! set "S" flag 48 + rotl r0 ! T <- "S" flag 49 + rotl r0 ! "S" flag is LSB 50 + rotcr r3 ! T -> r3:b30 51 + shlr r3 52 + shlr r0 53 + bt/s 1f 54 + mov.l r3,@(5*4,r15) ! copy cpu mode to SR 55 + ! switch to kernel mode 56 + mov #1,r0 57 + rotr r0 58 + rotr r0 59 + mov.l r0,@r2 ! enter kernel mode 60 + mov.l $current_thread_info,r2 61 + mov.l @r2,r2 62 + mov #0x20,r0 63 + shll8 r0 64 + add r2,r0 65 + mov r15,r2 ! r2 = user stack top 66 + mov r0,r15 ! switch kernel stack 67 + add #-4,r15 ! dummy 68 + mov.l r1,@-r15 ! TRA 69 + sts.l macl, @-r15 70 + sts.l mach, @-r15 71 + stc.l gbr, @-r15 72 + mov.l @(4*4,r2),r0 73 + mov.l @(5*4,r2),r1 74 + mov.l r1,@-r15 ! original SR 75 + sts.l pr,@-r15 76 + mov.l r0,@-r15 ! original PC 77 + mov r2,r3 78 + add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame 79 + mov.l r3,@-r15 ! original SP 80 + mov.l r14,@-r15 81 + mov.l r13,@-r15 82 + mov.l r12,@-r15 83 + mov.l r11,@-r15 84 + mov.l r10,@-r15 85 + mov.l r9,@-r15 86 + mov.l r8,@-r15 87 + mov.l r7,@-r15 88 + mov.l r6,@-r15 89 + mov.l r5,@-r15 90 + mov.l r4,@-r15 91 + mov r2,r8 ! copy user -> kernel stack 92 + mov.l @r8+,r3 93 + mov.l r3,@-r15 94 + mov.l @r8+,r2 95 + mov.l r2,@-r15 96 + mov.l @r8+,r1 97 + mov.l r1,@-r15 98 + mov.l @r8+,r0 99 + bra 2f 100 + mov.l r0,@-r15 101 + 1: 102 + ! in kernel exception 103 + mov #(22-4-4-1)*4+4,r0 104 + mov r15,r2 105 + sub r0,r15 106 + mov.l @r2+,r0 ! old R3 107 + mov.l r0,@-r15 108 + mov.l @r2+,r0 ! old R2 109 + mov.l r0,@-r15 110 + mov.l @r2+,r0 ! old R1 111 + mov.l r0,@-r15 112 + mov.l @r2+,r0 ! old R0 113 + mov.l r0,@-r15 114 + mov.l @r2+,r3 ! old PC 115 + mov.l @r2+,r0 ! old SR 116 + add #-4,r2 ! exception frame stub (sr) 117 + mov.l r1,@-r2 ! TRA 118 + sts.l macl, @-r2 119 + sts.l mach, @-r2 120 + stc.l gbr, @-r2 121 + mov.l r0,@-r2 ! save old SR 122 + sts.l pr,@-r2 123 + mov.l r3,@-r2 ! save old PC 124 + mov r2,r0 125 + add #8*4,r0 126 + mov.l r0,@-r2 ! save old SP 127 + mov.l r14,@-r2 128 + mov.l r13,@-r2 129 + mov.l r12,@-r2 130 + mov.l r11,@-r2 131 + mov.l r10,@-r2 132 + mov.l r9,@-r2 133 + mov.l r8,@-r2 134 + mov.l r7,@-r2 135 + mov.l r6,@-r2 136 + mov.l r5,@-r2 137 + mov.l r4,@-r2 138 + mov.l @(OFF_R0,r15),r0 139 + mov.l @(OFF_R1,r15),r1 140 + mov.l @(OFF_R2,r15),r2 141 + mov.l @(OFF_R3,r15),r3 142 + 2: 143 + mov #OFF_TRA,r8 144 + add r15,r8 145 + mov.l @r8,r9 146 + mov #64,r8 147 + cmp/hs r8,r9 148 + bt interrupt_entry ! vec >= 64 is interrupt 149 + mov #32,r8 150 + cmp/hs r8,r9 151 + bt trap_entry ! 64 > vec >= 32 is trap 152 + mov.l 4f,r8 153 + mov r9,r4 154 + shll2 r9 155 + add r9,r8 156 + mov.l @r8,r8 157 + mov #0,r9 158 + cmp/eq r9,r8 159 + bf 3f 160 + mov.l 8f,r8 ! unhandled exception 161 + 3: 162 + mov.l 5f,r10 163 + jmp @r8 164 + lds r10,pr 165 + 166 + interrupt_entry: 167 + mov r9,r4 168 + mov.l 6f,r9 169 + mov.l 7f,r8 170 + jmp @r8 171 + lds r9,pr 172 + 173 + .align 2 174 + 4: .long exception_handling_table 175 + 5: .long ret_from_exception 176 + 6: .long ret_from_irq 177 + 7: .long do_IRQ 178 + 8: .long do_exception_error 179 + 180 + trap_entry: 181 + add #-0x10,r9 182 + shll2 r9 ! TRA 183 + mov #OFF_TRA,r8 184 + add r15,r8 185 + mov.l r9,@r8 186 + mov r9,r8 187 + sti 188 + bra system_call 189 + nop 190 + 191 + .align 2 192 + 1: .long syscall_exit 193 + 2: .long break_point_trap_software 194 + 3: .long NR_syscalls 195 + 4: .long sys_call_table 196 + 197 + #if defined(CONFIG_SH_STANDARD_BIOS) 198 + /* Unwind the stack and jmp to the debug entry */ 199 + debug_kernel_fw: 200 + mov r15,r0 201 + add #(22-4)*4-4,r0 202 + ldc.l @r0+,gbr 203 + lds.l @r0+,mach 204 + lds.l @r0+,macl 205 + mov r15,r0 206 + mov.l @(OFF_SP,r0),r1 207 + mov #OFF_SR,r2 208 + mov.l @(r0,r2),r3 209 + mov.l r3,@-r1 210 + mov #OFF_SP,r2 211 + mov.l @(r0,r2),r3 212 + mov.l r3,@-r1 213 + mov r15,r0 214 + add #(22-4)*4-8,r0 215 + mov.l 1f,r2 216 + mov.l @r2,r2 217 + stc sr,r3 218 + mov.l r2,@r0 219 + mov.l r3,@r0 220 + mov.l r1,@(8,r0) 221 + mov.l @r15+, r0 222 + mov.l @r15+, r1 223 + mov.l @r15+, r2 224 + mov.l @r15+, r3 225 + mov.l @r15+, r4 226 + mov.l @r15+, r5 227 + mov.l @r15+, r6 228 + mov.l @r15+, r7 229 + mov.l @r15+, r8 230 + mov.l @r15+, r9 231 + mov.l @r15+, r10 232 + mov.l @r15+, r11 233 + mov.l @r15+, r12 234 + mov.l @r15+, r13 235 + mov.l @r15+, r14 236 + add #8,r15 237 + lds.l @r15+, pr 238 + rte 239 + mov.l @r15+,r15 240 + .align 2 241 + 1: .long gdb_vbr_vector 242 + #endif /* CONFIG_SH_STANDARD_BIOS */ 243 + 244 + ENTRY(address_error_handler) 245 + mov r15,r4 ! regs 246 + add #4,r4 247 + mov #OFF_PC,r0 248 + mov.l @(r0,r15),r6 ! pc 249 + mov.l 1f,r0 250 + jmp @r0 251 + mov #0,r5 ! writeaccess is unknown 252 + .align 2 253 + 254 + 1: .long do_address_error 255 + 256 + restore_all: 257 + cli 258 + mov r15,r0 259 + mov.l $cpu_mode,r2 260 + mov #OFF_SR,r3 261 + mov.l @(r0,r3),r1 262 + mov.l r1,@r2 263 + shll2 r1 ! clear MD bit 264 + shlr2 r1 265 + mov.l @(OFF_SP,r0),r2 266 + add #-8,r2 267 + mov.l r2,@(OFF_SP,r0) ! point exception frame top 268 + mov.l r1,@(4,r2) ! set sr 269 + mov #OFF_PC,r3 270 + mov.l @(r0,r3),r1 271 + mov.l r1,@r2 ! set pc 272 + add #4*16+4,r0 273 + lds.l @r0+,pr 274 + add #4,r0 ! skip sr 275 + ldc.l @r0+,gbr 276 + lds.l @r0+,mach 277 + lds.l @r0+,macl 278 + get_current_thread_info r0, r1 279 + mov.l $current_thread_info,r1 280 + mov.l r0,@r1 281 + mov.l @r15+,r0 282 + mov.l @r15+,r1 283 + mov.l @r15+,r2 284 + mov.l @r15+,r3 285 + mov.l @r15+,r4 286 + mov.l @r15+,r5 287 + mov.l @r15+,r6 288 + mov.l @r15+,r7 289 + mov.l @r15+,r8 290 + mov.l @r15+,r9 291 + mov.l @r15+,r10 292 + mov.l @r15+,r11 293 + mov.l @r15+,r12 294 + mov.l @r15+,r13 295 + mov.l @r15+,r14 296 + mov.l @r15,r15 297 + rte 298 + nop 299 + 2: 300 + mov.l 1f,r8 301 + mov.l 2f,r9 302 + jmp @r9 303 + lds r8,pr 304 + 305 + .align 2 306 + $current_thread_info: 307 + .long __current_thread_info 308 + $cpu_mode: 309 + .long __cpu_mode 310 + 311 + ! common exception handler 312 + #include "../../entry-common.S" 313 + 314 + .data 315 + ! cpu operation mode 316 + ! bit30 = MD (compatible SH3/4) 317 + __cpu_mode: 318 + .long 0x40000000 319 + 320 + .section .bss 321 + __current_thread_info: 322 + .long 0 323 + 324 + ENTRY(exception_handling_table) 325 + .space 4*32
+46
arch/sh/kernel/cpu/sh2/ex.S
··· 1 + /* 2 + * arch/sh/kernel/cpu/sh2/ex.S 3 + * 4 + * The SH-2 exception vector table 5 + * 6 + * Copyright (C) 2005 Yoshinori Sato 7 + * 8 + * This file is subject to the terms and conditions of the GNU General Public 9 + * License. See the file "COPYING" in the main directory of this archive 10 + * for more details. 11 + */ 12 + 13 + #include <linux/linkage.h> 14 + 15 + ! 16 + ! convert Exception Vector to Exception Number 17 + ! 18 + exception_entry: 19 + no = 0 20 + .rept 256 21 + mov.l r0,@-sp 22 + mov #no,r0 23 + bra exception_trampoline 24 + and #0xff,r0 25 + no = no + 1 26 + .endr 27 + exception_trampoline: 28 + mov.l r1,@-sp 29 + mov.l $exception_handler,r1 30 + jmp @r1 31 + 32 + .align 2 33 + $exception_entry: 34 + .long exception_entry 35 + $exception_handler: 36 + .long exception_handler 37 + ! 38 + ! Exception Vector Base 39 + ! 40 + .align 2 41 + ENTRY(vbr_base) 42 + vector = 0 43 + .rept 256 44 + .long exception_entry + vector * 8 45 + vector = vector + 1 46 + .endr
+1 -1
arch/sh/kernel/cpu/sh3/Makefile
··· 2 2 # Makefile for the Linux/SuperH SH-3 backends. 3 3 # 4 4 5 - obj-y := ex.o probe.o 5 + obj-y := ex.o probe.o entry.o 6 6 7 7 # CPU subtype setup 8 8 obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o
+2 -1
arch/sh/kernel/cpu/sh4/Makefile
··· 2 2 # Makefile for the Linux/SuperH SH-4 backends. 3 3 # 4 4 5 - obj-y := ex.o probe.o 5 + obj-y := ex.o probe.o common.o 6 + common-y += $(addprefix ../sh3/, entry.o) 6 7 7 8 obj-$(CONFIG_SH_FPU) += fpu.o 8 9 obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
+372
arch/sh/kernel/entry-common.S
··· 1 + /* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $ 2 + * 3 + * linux/arch/sh/entry.S 4 + * 5 + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 6 + * Copyright (C) 2003 Paul Mundt 7 + * 8 + * This file is subject to the terms and conditions of the GNU General Public 9 + * License. See the file "COPYING" in the main directory of this archive 10 + * for more details. 11 + * 12 + */ 13 + 14 + ! NOTE: 15 + ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address 16 + ! to be jumped is too far, but it causes illegal slot exception. 17 + 18 + /* 19 + * entry.S contains the system-call and fault low-level handling routines. 20 + * This also contains the timer-interrupt handler, as well as all interrupts 21 + * and faults that can result in a task-switch. 22 + * 23 + * NOTE: This code handles signal-recognition, which happens every time 24 + * after a timer-interrupt and after each system call. 25 + * 26 + * NOTE: This code uses a convention that instructions in the delay slot 27 + * of a transfer-control instruction are indented by an extra space, thus: 28 + * 29 + * jmp @k0 ! control-transfer instruction 30 + * ldc k1, ssr ! delay slot 31 + * 32 + * Stack layout in 'ret_from_syscall': 33 + * ptrace needs to have all regs on the stack. 34 + * if the order here is changed, it needs to be 35 + * updated in ptrace.c and ptrace.h 36 + * 37 + * r0 38 + * ... 39 + * r15 = stack pointer 40 + * spc 41 + * pr 42 + * ssr 43 + * gbr 44 + * mach 45 + * macl 46 + * syscall # 47 + * 48 + */ 49 + 50 + #if defined(CONFIG_PREEMPT) 51 + # define preempt_stop() cli 52 + #else 53 + # define preempt_stop() 54 + # define resume_kernel __restore_all 55 + #endif 56 + 57 + #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) 58 + ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. 59 + ! If both are configured, handle the debug traps (breakpoints) in SW, 60 + ! but still allow BIOS traps to FW. 61 + 62 + .align 2 63 + debug_kernel: 64 + #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) 65 + /* Force BIOS call to FW (debug_trap put TRA in r8) */ 66 + mov r8,r0 67 + shlr2 r0 68 + cmp/eq #0x3f,r0 69 + bt debug_kernel_fw 70 + #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ 71 + 72 + debug_enter: 73 + #if defined(CONFIG_SH_KGDB) 74 + /* Jump to kgdb, pass stacked regs as arg */ 75 + debug_kernel_sw: 76 + mov.l 3f, r0 77 + jmp @r0 78 + mov r15, r4 79 + .align 2 80 + 3: .long kgdb_handle_exception 81 + #endif /* CONFIG_SH_KGDB */ 82 + 83 + #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ 84 + 85 + 86 + .align 2 87 + debug_trap: 88 + #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) 89 + mov #OFF_SR, r0 90 + mov.l @(r0,r15), r0 ! get status register 91 + shll r0 92 + shll r0 ! kernel space? 93 + bt/s debug_kernel 94 + #endif 95 + mov.l @r15, r0 ! Restore R0 value 96 + mov.l 1f, r8 97 + jmp @r8 98 + nop 99 + 100 + .align 2 101 + ENTRY(exception_error) 102 + ! 103 + sti 104 + mov.l 2f, r0 105 + jmp @r0 106 + nop 107 + 108 + ! 109 + .align 2 110 + 1: .long break_point_trap_software 111 + 2: .long do_exception_error 112 + 113 + .align 2 114 + ret_from_exception: 115 + preempt_stop() 116 + ENTRY(ret_from_irq) 117 + ! 118 + mov #OFF_SR, r0 119 + mov.l @(r0,r15), r0 ! get status register 120 + shll r0 121 + shll r0 ! kernel space? 122 + get_current_thread_info r8, r0 123 + bt resume_kernel ! Yes, it's from kernel, go back soon 124 + 125 + #ifdef CONFIG_PREEMPT 126 + bra resume_userspace 127 + nop 128 + ENTRY(resume_kernel) 129 + mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count 130 + tst r0, r0 131 + bf noresched 132 + need_resched: 133 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 134 + tst #_TIF_NEED_RESCHED, r0 ! need_resched set? 135 + bt noresched 136 + 137 + mov #OFF_SR, r0 138 + mov.l @(r0,r15), r0 ! get status register 139 + and #0xf0, r0 ! interrupts off (exception path)? 140 + cmp/eq #0xf0, r0 141 + bt noresched 142 + 143 + mov.l 1f, r0 144 + mov.l r0, @(TI_PRE_COUNT,r8) 145 + 146 + sti 147 + mov.l 2f, r0 148 + jsr @r0 149 + nop 150 + mov #0, r0 151 + mov.l r0, @(TI_PRE_COUNT,r8) 152 + cli 153 + 154 + bra need_resched 155 + nop 156 + noresched: 157 + bra __restore_all 158 + nop 159 + 160 + .align 2 161 + 1: .long PREEMPT_ACTIVE 162 + 2: .long schedule 163 + #endif 164 + 165 + ENTRY(resume_userspace) 166 + ! r8: current_thread_info 167 + cli 168 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 169 + tst #_TIF_WORK_MASK, r0 170 + bt/s __restore_all 171 + tst #_TIF_NEED_RESCHED, r0 172 + 173 + .align 2 174 + work_pending: 175 + ! r0: current_thread_info->flags 176 + ! r8: current_thread_info 177 + ! t: result of "tst #_TIF_NEED_RESCHED, r0" 178 + bf/s work_resched 179 + tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 180 + work_notifysig: 181 + bt/s __restore_all 182 + mov r15, r4 183 + mov r12, r5 ! set arg1(save_r0) 184 + mov r0, r6 185 + mov.l 2f, r1 186 + mov.l 3f, r0 187 + jmp @r1 188 + lds r0, pr 189 + work_resched: 190 + #ifndef CONFIG_PREEMPT 191 + ! gUSA handling 192 + mov.l @(OFF_SP,r15), r0 ! get user space stack pointer 193 + mov r0, r1 194 + shll r0 195 + bf/s 1f 196 + shll r0 197 + bf/s 1f 198 + mov #OFF_PC, r0 199 + ! SP >= 0xc0000000 : gUSA mark 200 + mov.l @(r0,r15), r2 ! get user space PC (program counter) 201 + mov.l @(OFF_R0,r15), r3 ! end point 202 + cmp/hs r3, r2 ! r2 >= r3? 203 + bt 1f 204 + add r3, r1 ! rewind point #2 205 + mov.l r1, @(r0,r15) ! reset PC to rewind point #2 206 + ! 207 + 1: 208 + #endif 209 + mov.l 1f, r1 210 + jsr @r1 ! schedule 211 + nop 212 + cli 213 + ! 214 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 215 + tst #_TIF_WORK_MASK, r0 216 + bt __restore_all 217 + bra work_pending 218 + tst #_TIF_NEED_RESCHED, r0 219 + 220 + .align 2 221 + 1: .long schedule 222 + 2: .long do_notify_resume 223 + 3: .long restore_all 224 + 225 + .align 2 226 + syscall_exit_work: 227 + ! r0: current_thread_info->flags 228 + ! r8: current_thread_info 229 + tst #_TIF_SYSCALL_TRACE, r0 230 + bt/s work_pending 231 + tst #_TIF_NEED_RESCHED, r0 232 + sti 233 + ! XXX setup arguments... 234 + mov.l 4f, r0 ! do_syscall_trace 235 + jsr @r0 236 + nop 237 + bra resume_userspace 238 + nop 239 + 240 + .align 2 241 + syscall_trace_entry: 242 + ! Yes it is traced. 243 + ! XXX setup arguments... 244 + mov.l 4f, r11 ! Call do_syscall_trace which notifies 245 + jsr @r11 ! superior (will chomp R[0-7]) 246 + nop 247 + ! Reload R0-R4 from kernel stack, where the 248 + ! parent may have modified them using 249 + ! ptrace(POKEUSR). (Note that R0-R2 are 250 + ! used by the system call handler directly 251 + ! from the kernel stack anyway, so don't need 252 + ! to be reloaded here.) This allows the parent 253 + ! to rewrite system calls and args on the fly. 254 + mov.l @(OFF_R4,r15), r4 ! arg0 255 + mov.l @(OFF_R5,r15), r5 256 + mov.l @(OFF_R6,r15), r6 257 + mov.l @(OFF_R7,r15), r7 ! arg3 258 + mov.l @(OFF_R3,r15), r3 ! syscall_nr 259 + ! Arrange for do_syscall_trace to be called 260 + ! again as the system call returns. 261 + mov.l 2f, r10 ! Number of syscalls 262 + cmp/hs r10, r3 263 + bf syscall_call 264 + mov #-ENOSYS, r0 265 + bra syscall_exit 266 + mov.l r0, @(OFF_R0,r15) ! Return value 267 + 268 + __restore_all: 269 + mov.l 1f,r0 270 + jmp @r0 271 + nop 272 + 273 + .align 2 274 + 1: .long restore_all 275 + 276 + /* 277 + * Syscall interface: 278 + * 279 + * Syscall #: R3 280 + * Arguments #0 to #3: R4--R7 281 + * Arguments #4 to #6: R0, R1, R2 282 + * TRA: (number of arguments + 0x10) x 4 283 + * 284 + * This code also handles delegating other traps to the BIOS/gdb stub 285 + * according to: 286 + * 287 + * Trap number 288 + * (TRA>>2) Purpose 289 + * -------- ------- 290 + * 0x0-0xf old syscall ABI 291 + * 0x10-0x1f new syscall ABI 292 + * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. 293 + * 294 + * Note: When we're first called, the TRA value must be shifted 295 + * right 2 bits in order to get the value that was used as the "trapa" 296 + * argument. 297 + */ 298 + 299 + .align 2 300 + .globl ret_from_fork 301 + ret_from_fork: 302 + mov.l 1f, r8 303 + jsr @r8 304 + mov r0, r4 305 + bra syscall_exit 306 + nop 307 + .align 2 308 + 1: .long schedule_tail 309 + ! 310 + ENTRY(system_call) 311 + #if !defined(CONFIG_CPU_SH2) 312 + mov.l 1f, r9 313 + mov.l @r9, r8 ! Read from TRA (Trap Address) Register 314 + #endif 315 + ! 316 + ! Is the trap argument >= 0x20? (TRA will be >= 0x80) 317 + mov #0x7f, r9 318 + cmp/hi r9, r8 319 + bt/s 0f 320 + mov #OFF_TRA, r9 321 + add r15, r9 322 + ! 323 + mov.l r8, @r9 ! set TRA value to tra 324 + sti 325 + ! Call the system call handler through the table. 326 + ! First check for bad syscall number 327 + mov r3, r9 328 + mov.l 2f, r8 ! Number of syscalls 329 + cmp/hs r8, r9 330 + get_current_thread_info r8, r10 331 + bf good_system_call 332 + syscall_badsys: ! Bad syscall number 333 + mov #-ENOSYS, r0 334 + bra resume_userspace 335 + mov.l r0, @(OFF_R0,r15) ! Return value 336 + ! 337 + 0: 338 + bra debug_trap 339 + nop 340 + ! 341 + good_system_call: ! Good syscall number 342 + mov.l @(TI_FLAGS,r8), r8 343 + mov #_TIF_SYSCALL_TRACE, r10 344 + tst r10, r8 345 + bf syscall_trace_entry 346 + ! 347 + syscall_call: 348 + shll2 r9 ! x4 349 + mov.l 3f, r8 ! Load the address of sys_call_table 350 + add r8, r9 351 + mov.l @r9, r8 352 + jsr @r8 ! jump to specific syscall handler 353 + nop 354 + mov.l @(OFF_R0,r15), r12 ! save r0 355 + mov.l r0, @(OFF_R0,r15) ! save the return value 356 + ! 357 + syscall_exit: 358 + cli 359 + ! 360 + get_current_thread_info r8, r0 361 + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 362 + tst #_TIF_ALLWORK_MASK, r0 363 + bf syscall_exit_work 364 + bra __restore_all 365 + nop 366 + .align 2 367 + #if !defined(CONFIG_CPU_SH2) 368 + 1: .long TRA 369 + #endif 370 + 2: .long NR_syscalls 371 + 3: .long sys_call_table 372 + 4: .long do_syscall_trace
+11 -328
arch/sh/kernel/entry.S arch/sh/kernel/cpu/sh3/entry.S
··· 1 1 /* 2 - * linux/arch/sh/entry.S 2 + * arch/sh/kernel/entry.S 3 3 * 4 4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 5 5 * Copyright (C) 2003 - 2006 Paul Mundt ··· 7 7 * This file is subject to the terms and conditions of the GNU General Public 8 8 * License. See the file "COPYING" in the main directory of this archive 9 9 * for more details. 10 - * 11 10 */ 12 11 #include <linux/sys.h> 13 12 #include <linux/errno.h> ··· 80 81 #define k_g_imask r6_bank /* r6_bank1 */ 81 82 #define current r7 /* r7_bank1 */ 82 83 84 + #include <asm/entry-macros.S> 85 + 83 86 /* 84 87 * Kernel mode register usage: 85 88 * k0 scratch ··· 107 106 ! Although this could be written in assembly language (and it'd be faster), 108 107 ! this first version depends *much* on C implementation. 109 108 ! 110 - 111 - #define CLI() \ 112 - stc sr, r0; \ 113 - or #0xf0, r0; \ 114 - ldc r0, sr 115 - 116 - #define STI() \ 117 - mov.l __INV_IMASK, r11; \ 118 - stc sr, r10; \ 119 - and r11, r10; \ 120 - stc k_g_imask, r11; \ 121 - or r11, r10; \ 122 - ldc r10, sr 123 - 124 - #if defined(CONFIG_PREEMPT) 125 - # define preempt_stop() CLI() 126 - #else 127 - # define preempt_stop() 128 - # define resume_kernel restore_all 129 - #endif 130 109 131 110 #if defined(CONFIG_MMU) 132 111 .align 2 ··· 149 168 lds r10, pr 150 169 rts 151 170 nop 152 - 0: STI() 171 + 0: sti 153 172 mov.l 3f, r0 154 173 mov r9, r6 155 174 mov r8, r5 ··· 183 202 1: .long MMU_TEA 184 203 2: .long do_address_error 185 204 #endif /* CONFIG_MMU */ 186 - 187 - #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) 188 - ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. 189 - ! If both are configured, handle the debug traps (breakpoints) in SW, 190 - ! but still allow BIOS traps to FW. 191 - 192 - .align 2 193 - debug_kernel: 194 - #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) 195 - /* Force BIOS call to FW (debug_trap put TRA in r8) */ 196 - mov r8,r0 197 - shlr2 r0 198 - cmp/eq #0x3f,r0 199 - bt debug_kernel_fw 200 - #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ 201 - 202 - debug_enter: 203 - #if defined(CONFIG_SH_KGDB) 204 - /* Jump to kgdb, pass stacked regs as arg */ 205 - debug_kernel_sw: 206 - mov.l 3f, r0 207 - jmp @r0 208 - mov r15, r4 209 - .align 2 210 - 3: .long kgdb_handle_exception 211 - #endif /* CONFIG_SH_KGDB */ 212 205 213 206 #if defined(CONFIG_SH_STANDARD_BIOS) 214 207 /* Unwind the stack and jmp to the debug entry */ ··· 224 269 2: .long gdb_vbr_vector 225 270 #endif /* CONFIG_SH_STANDARD_BIOS */ 226 271 227 - #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ 228 - 229 - 230 - .align 2 231 - debug_trap: 232 - #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) 233 - mov #OFF_SR, r0 234 - mov.l @(r0,r15), r0 ! get status register 235 - shll r0 236 - shll r0 ! kernel space? 237 - bt/s debug_kernel 238 - #endif 239 - mov.l @r15, r0 ! Restore R0 value 240 - mov.l 1f, r8 241 - jmp @r8 242 - nop 243 - 244 - .align 2 245 - ENTRY(exception_error) 246 - ! 247 - STI() 248 - mov.l 2f, r0 249 - jmp @r0 250 - nop 251 - 252 - ! 253 - .align 2 254 - 1: .long break_point_trap_software 255 - 2: .long do_exception_error 256 - 257 - .align 2 258 - ret_from_exception: 259 - preempt_stop() 260 - ENTRY(ret_from_irq) 261 - ! 262 - mov #OFF_SR, r0 263 - mov.l @(r0,r15), r0 ! get status register 264 - shll r0 265 - shll r0 ! kernel space? 266 - bt/s resume_kernel ! Yes, it's from kernel, go back soon 267 - GET_THREAD_INFO(r8) 268 - 269 - #ifdef CONFIG_PREEMPT 270 - bra resume_userspace 271 - nop 272 - ENTRY(resume_kernel) 273 - mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count 274 - tst r0, r0 275 - bf noresched 276 - need_resched: 277 - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 278 - tst #_TIF_NEED_RESCHED, r0 ! need_resched set? 279 - bt noresched 280 - 281 - mov #OFF_SR, r0 282 - mov.l @(r0,r15), r0 ! get status register 283 - and #0xf0, r0 ! interrupts off (exception path)? 284 - cmp/eq #0xf0, r0 285 - bt noresched 286 - 287 - mov.l 1f, r0 288 - mov.l r0, @(TI_PRE_COUNT,r8) 289 - 290 - STI() 291 - mov.l 2f, r0 292 - jsr @r0 293 - nop 294 - mov #0, r0 295 - mov.l r0, @(TI_PRE_COUNT,r8) 296 - CLI() 297 - 298 - bra need_resched 299 - nop 300 - noresched: 301 - bra restore_all 302 - nop 303 - 304 - .align 2 305 - 1: .long PREEMPT_ACTIVE 306 - 2: .long schedule 307 - #endif 308 - 309 - ENTRY(resume_userspace) 310 - ! r8: current_thread_info 311 - CLI() 312 - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 313 - tst #_TIF_WORK_MASK, r0 314 - bt/s restore_all 315 - tst #_TIF_NEED_RESCHED, r0 316 - 317 - .align 2 318 - work_pending: 319 - ! r0: current_thread_info->flags 320 - ! r8: current_thread_info 321 - ! t: result of "tst #_TIF_NEED_RESCHED, r0" 322 - bf/s work_resched 323 - tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 324 - work_notifysig: 325 - bt/s restore_all 326 - mov r15, r4 327 - mov r12, r5 ! set arg1(save_r0) 328 - mov r0, r6 329 - mov.l 2f, r1 330 - mova restore_all, r0 331 - jmp @r1 332 - lds r0, pr 333 - work_resched: 334 - #ifndef CONFIG_PREEMPT 335 - ! gUSA handling 336 - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer 337 - mov r0, r1 338 - shll r0 339 - bf/s 1f 340 - shll r0 341 - bf/s 1f 342 - mov #OFF_PC, r0 343 - ! SP >= 0xc0000000 : gUSA mark 344 - mov.l @(r0,r15), r2 ! get user space PC (program counter) 345 - mov.l @(OFF_R0,r15), r3 ! end point 346 - cmp/hs r3, r2 ! r2 >= r3? 347 - bt 1f 348 - add r3, r1 ! rewind point #2 349 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 350 - ! 351 - 1: 352 - #endif 353 - mov.l 1f, r1 354 - jsr @r1 ! schedule 355 - nop 356 - CLI() 357 - ! 358 - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 359 - tst #_TIF_WORK_MASK, r0 360 - bt restore_all 361 - bra work_pending 362 - tst #_TIF_NEED_RESCHED, r0 363 - 364 - .align 2 365 - 1: .long schedule 366 - 2: .long do_notify_resume 367 - 368 - .align 2 369 - syscall_exit_work: 370 - ! r0: current_thread_info->flags 371 - ! r8: current_thread_info 372 - tst #_TIF_SYSCALL_TRACE, r0 373 - bt/s work_pending 374 - tst #_TIF_NEED_RESCHED, r0 375 - STI() 376 - ! XXX setup arguments... 377 - mov.l 4f, r0 ! do_syscall_trace 378 - jsr @r0 379 - nop 380 - bra resume_userspace 381 - nop 382 - 383 - .align 2 384 - syscall_trace_entry: 385 - ! Yes it is traced. 386 - ! XXX setup arguments... 387 - mov.l 4f, r11 ! Call do_syscall_trace which notifies 388 - jsr @r11 ! superior (will chomp R[0-7]) 389 - nop 390 - ! Reload R0-R4 from kernel stack, where the 391 - ! parent may have modified them using 392 - ! ptrace(POKEUSR). (Note that R0-R2 are 393 - ! used by the system call handler directly 394 - ! from the kernel stack anyway, so don't need 395 - ! to be reloaded here.) This allows the parent 396 - ! to rewrite system calls and args on the fly. 397 - mov.l @(OFF_R4,r15), r4 ! arg0 398 - mov.l @(OFF_R5,r15), r5 399 - mov.l @(OFF_R6,r15), r6 400 - mov.l @(OFF_R7,r15), r7 ! arg3 401 - mov.l @(OFF_R3,r15), r3 ! syscall_nr 402 - ! Arrange for do_syscall_trace to be called 403 - ! again as the system call returns. 404 - mov.l 2f, r10 ! Number of syscalls 405 - cmp/hs r10, r3 406 - bf syscall_call 407 - mov #-ENOSYS, r0 408 - bra syscall_exit 409 - mov.l r0, @(OFF_R0,r15) ! Return value 410 - 411 - /* 412 - * Syscall interface: 413 - * 414 - * Syscall #: R3 415 - * Arguments #0 to #3: R4--R7 416 - * Arguments #4 to #6: R0, R1, R2 417 - * TRA: (number of arguments + 0x10) x 4 418 - * 419 - * This code also handles delegating other traps to the BIOS/gdb stub 420 - * according to: 421 - * 422 - * Trap number 423 - * (TRA>>2) Purpose 424 - * -------- ------- 425 - * 0x0-0xf old syscall ABI 426 - * 0x10-0x1f new syscall ABI 427 - * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. 428 - * 429 - * Note: When we're first called, the TRA value must be shifted 430 - * right 2 bits in order to get the value that was used as the "trapa" 431 - * argument. 432 - */ 433 - 434 - .align 2 435 - .globl ret_from_fork 436 - ret_from_fork: 437 - mov.l 1f, r8 438 - jsr @r8 439 - mov r0, r4 440 - bra syscall_exit 441 - nop 442 - .align 2 443 - 1: .long schedule_tail 444 - ! 445 - ENTRY(system_call) 446 - mov.l 1f, r9 447 - mov.l @r9, r8 ! Read from TRA (Trap Address) Register 448 - ! 449 - ! Is the trap argument >= 0x20? (TRA will be >= 0x80) 450 - mov #0x7f, r9 451 - cmp/hi r9, r8 452 - bt/s 0f 453 - mov #OFF_TRA, r9 454 - add r15, r9 455 - ! 456 - mov.l r8, @r9 ! set TRA value to tra 457 - STI() 458 - ! Call the system call handler through the table. 459 - ! First check for bad syscall number 460 - mov r3, r9 461 - mov.l 2f, r8 ! Number of syscalls 462 - cmp/hs r8, r9 463 - bf/s good_system_call 464 - GET_THREAD_INFO(r8) 465 - syscall_badsys: ! Bad syscall number 466 - mov #-ENOSYS, r0 467 - bra resume_userspace 468 - mov.l r0, @(OFF_R0,r15) ! Return value 469 - ! 470 - 0: 471 - bra debug_trap 472 - nop 473 - ! 474 - good_system_call: ! Good syscall number 475 - mov.l @(TI_FLAGS,r8), r8 476 - mov #_TIF_SYSCALL_TRACE, r10 477 - tst r10, r8 478 - bf syscall_trace_entry 479 - ! 480 - syscall_call: 481 - shll2 r9 ! x4 482 - mov.l 3f, r8 ! Load the address of sys_call_table 483 - add r8, r9 484 - mov.l @r9, r8 485 - jsr @r8 ! jump to specific syscall handler 486 - nop 487 - mov.l @(OFF_R0,r15), r12 ! save r0 488 - mov.l r0, @(OFF_R0,r15) ! save the return value 489 - ! 490 - syscall_exit: 491 - CLI() 492 - ! 493 - GET_THREAD_INFO(r8) 494 - mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags 495 - tst #_TIF_ALLWORK_MASK, r0 496 - bf syscall_exit_work 497 272 restore_all: 498 273 mov.l @r15+, r0 499 274 mov.l @r15+, r1 ··· 291 606 ! 292 607 ! Calculate new SR value 293 608 mov k3, k2 ! original SR value 294 - mov.l 9f, k1 609 + mov #0xf0, k1 610 + extu.b k1, k1 611 + not k1, k1 295 612 and k1, k2 ! Mask orignal SR value 296 613 ! 297 614 mov k3, k0 ! Calculate IMASK-bits ··· 319 632 nop 320 633 321 634 .align 2 322 - 1: .long TRA 323 - 2: .long NR_syscalls 324 - 3: .long sys_call_table 325 - 4: .long do_syscall_trace 326 635 5: .long 0x00001000 ! DSP 327 636 7: .long 0x30000000 328 - 9: 329 - __INV_IMASK: 330 - .long 0xffffff0f ! ~(IMASK) 331 637 638 + ! common exception handler 639 + #include "../../entry.S" 640 + 332 641 ! Exception Vector Base 333 642 ! 334 643 ! Should be aligned page boundary. ··· 444 761 ! Save the user registers on the stack. 445 762 mov.l k2, @-r15 ! EXPEVT 446 763 447 - mov #-1, k4 764 + mov #-1, k4 448 765 mov.l k4, @-r15 ! set TRA (default: -1) 449 766 ! 450 767 sts.l macl, @-r15
+10 -2
arch/sh/kernel/head.S
··· 53 53 ldc r0, sr 54 54 ! Initialize global interrupt mask 55 55 mov #0, r0 56 + #ifdef CONFIG_CPU_HAS_SR_RB 56 57 ldc r0, r6_bank 57 - 58 + #endif 59 + 58 60 /* 59 61 * Prefetch if possible to reduce cache miss penalty. 60 62 * ··· 73 71 mov #(THREAD_SIZE >> 8), r1 74 72 shll8 r1 ! r1 = THREAD_SIZE 75 73 sub r1, r0 ! 74 + #ifdef CONFIG_CPU_HAS_SR_RB 76 75 ldc r0, r7_bank ! ... and initial thread_info 77 - 76 + #endif 77 + 78 78 ! Clear BSS area 79 79 mov.l 3f, r1 80 80 add #4, r1 ··· 99 95 nop 100 96 101 97 .balign 4 98 + #if defined(CONFIG_CPU_SH2) 99 + 1: .long 0x000000F0 ! IMASK=0xF 100 + #else 102 101 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 102 + #endif 103 103 2: .long init_thread_union+THREAD_SIZE 104 104 3: .long __bss_start 105 105 4: .long _end