diff options
Diffstat (limited to 'arch/sh/kernel')
| -rw-r--r-- | arch/sh/kernel/cpu/sh2/entry.S | 325 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh2/ex.S | 46 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh3/Makefile | 2 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S (renamed from arch/sh/kernel/entry.S) | 339 | ||||
| -rw-r--r-- | arch/sh/kernel/cpu/sh4/Makefile | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/entry-common.S | 372 | ||||
| -rw-r--r-- | arch/sh/kernel/head.S | 12 |
7 files changed, 767 insertions, 332 deletions
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S new file mode 100644 index 000000000000..298d9191909d --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
| @@ -0,0 +1,325 @@ | |||
| 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 | ||
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S new file mode 100644 index 000000000000..6d285af7846c --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/ex.S | |||
| @@ -0,0 +1,46 @@ | |||
| 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 | ||
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 58d3815695ff..83905e4e4387 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # Makefile for the Linux/SuperH SH-3 backends. | 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 | # CPU subtype setup | 7 | # CPU subtype setup |
| 8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o | 8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o |
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 39aaefb2d83f..8bcd63f9f351 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/sh/entry.S | 2 | * arch/sh/kernel/entry.S |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka |
| 5 | * Copyright (C) 2003 - 2006 Paul Mundt | 5 | * Copyright (C) 2003 - 2006 Paul Mundt |
| @@ -7,7 +7,6 @@ | |||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
| 8 | * License. See the file "COPYING" in the main directory of this archive | 8 | * License. See the file "COPYING" in the main directory of this archive |
| 9 | * for more details. | 9 | * for more details. |
| 10 | * | ||
| 11 | */ | 10 | */ |
| 12 | #include <linux/sys.h> | 11 | #include <linux/sys.h> |
| 13 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| @@ -81,6 +80,8 @@ OFF_TRA = (16*4+6*4) | |||
| 81 | #define k_g_imask r6_bank /* r6_bank1 */ | 80 | #define k_g_imask r6_bank /* r6_bank1 */ |
| 82 | #define current r7 /* r7_bank1 */ | 81 | #define current r7 /* r7_bank1 */ |
| 83 | 82 | ||
| 83 | #include <asm/entry-macros.S> | ||
| 84 | |||
| 84 | /* | 85 | /* |
| 85 | * Kernel mode register usage: | 86 | * Kernel mode register usage: |
| 86 | * k0 scratch | 87 | * k0 scratch |
| @@ -107,26 +108,6 @@ OFF_TRA = (16*4+6*4) | |||
| 107 | ! this first version depends *much* on C implementation. | 108 | ! this first version depends *much* on C implementation. |
| 108 | ! | 109 | ! |
| 109 | 110 | ||
| 110 | #define CLI() \ | ||
| 111 | stc sr, r0; \ | ||
| 112 | or #0xf0, r0; \ | ||
| 113 | ldc r0, sr | ||
| 114 | |||
| 115 | #define STI() \ | ||
| 116 | mov.l __INV_IMASK, r11; \ | ||
| 117 | stc sr, r10; \ | ||
| 118 | and r11, r10; \ | ||
| 119 | stc k_g_imask, r11; \ | ||
| 120 | or r11, r10; \ | ||
| 121 | ldc r10, sr | ||
| 122 | |||
| 123 | #if defined(CONFIG_PREEMPT) | ||
| 124 | # define preempt_stop() CLI() | ||
| 125 | #else | ||
| 126 | # define preempt_stop() | ||
| 127 | # define resume_kernel restore_all | ||
| 128 | #endif | ||
| 129 | |||
| 130 | #if defined(CONFIG_MMU) | 111 | #if defined(CONFIG_MMU) |
| 131 | .align 2 | 112 | .align 2 |
| 132 | ENTRY(tlb_miss_load) | 113 | ENTRY(tlb_miss_load) |
| @@ -168,7 +149,7 @@ call_dpf: | |||
| 168 | lds r10, pr | 149 | lds r10, pr |
| 169 | rts | 150 | rts |
| 170 | nop | 151 | nop |
| 171 | 0: STI() | 152 | 0: sti |
| 172 | mov.l 3f, r0 | 153 | mov.l 3f, r0 |
| 173 | mov r9, r6 | 154 | mov r9, r6 |
| 174 | mov r8, r5 | 155 | mov r8, r5 |
| @@ -203,32 +184,6 @@ call_dae: | |||
| 203 | 2: .long do_address_error | 184 | 2: .long do_address_error |
| 204 | #endif /* CONFIG_MMU */ | 185 | #endif /* CONFIG_MMU */ |
| 205 | 186 | ||
| 206 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
| 207 | ! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present. | ||
| 208 | ! If both are configured, handle the debug traps (breakpoints) in SW, | ||
| 209 | ! but still allow BIOS traps to FW. | ||
| 210 | |||
| 211 | .align 2 | ||
| 212 | debug_kernel: | ||
| 213 | #if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB) | ||
| 214 | /* Force BIOS call to FW (debug_trap put TRA in r8) */ | ||
| 215 | mov r8,r0 | ||
| 216 | shlr2 r0 | ||
| 217 | cmp/eq #0x3f,r0 | ||
| 218 | bt debug_kernel_fw | ||
| 219 | #endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */ | ||
| 220 | |||
| 221 | debug_enter: | ||
| 222 | #if defined(CONFIG_SH_KGDB) | ||
| 223 | /* Jump to kgdb, pass stacked regs as arg */ | ||
| 224 | debug_kernel_sw: | ||
| 225 | mov.l 3f, r0 | ||
| 226 | jmp @r0 | ||
| 227 | mov r15, r4 | ||
| 228 | .align 2 | ||
| 229 | 3: .long kgdb_handle_exception | ||
| 230 | #endif /* CONFIG_SH_KGDB */ | ||
| 231 | |||
| 232 | #if defined(CONFIG_SH_STANDARD_BIOS) | 187 | #if defined(CONFIG_SH_STANDARD_BIOS) |
| 233 | /* Unwind the stack and jmp to the debug entry */ | 188 | /* Unwind the stack and jmp to the debug entry */ |
| 234 | debug_kernel_fw: | 189 | debug_kernel_fw: |
| @@ -269,276 +224,6 @@ debug_kernel_fw: | |||
| 269 | 2: .long gdb_vbr_vector | 224 | 2: .long gdb_vbr_vector |
| 270 | #endif /* CONFIG_SH_STANDARD_BIOS */ | 225 | #endif /* CONFIG_SH_STANDARD_BIOS */ |
| 271 | 226 | ||
| 272 | #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */ | ||
| 273 | |||
| 274 | |||
| 275 | .align 2 | ||
| 276 | debug_trap: | ||
| 277 | #if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB) | ||
| 278 | mov #OFF_SR, r0 | ||
| 279 | mov.l @(r0,r15), r0 ! get status register | ||
| 280 | shll r0 | ||
| 281 | shll r0 ! kernel space? | ||
| 282 | bt/s debug_kernel | ||
| 283 | #endif | ||
| 284 | mov.l @r15, r0 ! Restore R0 value | ||
| 285 | mov.l 1f, r8 | ||
| 286 | jmp @r8 | ||
| 287 | nop | ||
| 288 | |||
| 289 | .align 2 | ||
| 290 | ENTRY(exception_error) | ||
| 291 | ! | ||
| 292 | STI() | ||
| 293 | mov.l 2f, r0 | ||
| 294 | jmp @r0 | ||
| 295 | nop | ||
| 296 | |||
| 297 | ! | ||
| 298 | .align 2 | ||
| 299 | 1: .long break_point_trap_software | ||
| 300 | 2: .long do_exception_error | ||
| 301 | |||
| 302 | .align 2 | ||
| 303 | ret_from_exception: | ||
| 304 | preempt_stop() | ||
| 305 | ENTRY(ret_from_irq) | ||
| 306 | ! | ||
| 307 | mov #OFF_SR, r0 | ||
| 308 | mov.l @(r0,r15), r0 ! get status register | ||
| 309 | shll r0 | ||
| 310 | shll r0 ! kernel space? | ||
| 311 | bt/s resume_kernel ! Yes, it's from kernel, go back soon | ||
| 312 | GET_THREAD_INFO(r8) | ||
| 313 | |||
| 314 | #ifdef CONFIG_PREEMPT | ||
| 315 | bra resume_userspace | ||
| 316 | nop | ||
| 317 | ENTRY(resume_kernel) | ||
| 318 | mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count | ||
| 319 | tst r0, r0 | ||
| 320 | bf noresched | ||
| 321 | need_resched: | ||
| 322 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
| 323 | tst #_TIF_NEED_RESCHED, r0 ! need_resched set? | ||
| 324 | bt noresched | ||
| 325 | |||
| 326 | mov #OFF_SR, r0 | ||
| 327 | mov.l @(r0,r15), r0 ! get status register | ||
| 328 | and #0xf0, r0 ! interrupts off (exception path)? | ||
| 329 | cmp/eq #0xf0, r0 | ||
| 330 | bt noresched | ||
| 331 | |||
| 332 | mov.l 1f, r0 | ||
| 333 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
| 334 | |||
| 335 | STI() | ||
| 336 | mov.l 2f, r0 | ||
| 337 | jsr @r0 | ||
| 338 | nop | ||
| 339 | mov #0, r0 | ||
| 340 | mov.l r0, @(TI_PRE_COUNT,r8) | ||
| 341 | CLI() | ||
| 342 | |||
| 343 | bra need_resched | ||
| 344 | nop | ||
| 345 | noresched: | ||
| 346 | bra restore_all | ||
| 347 | nop | ||
| 348 | |||
| 349 | .align 2 | ||
| 350 | 1: .long PREEMPT_ACTIVE | ||
| 351 | 2: .long schedule | ||
| 352 | #endif | ||
| 353 | |||
| 354 | ENTRY(resume_userspace) | ||
| 355 | ! r8: current_thread_info | ||
| 356 | CLI() | ||
| 357 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
| 358 | tst #_TIF_WORK_MASK, r0 | ||
| 359 | bt/s restore_all | ||
| 360 | tst #_TIF_NEED_RESCHED, r0 | ||
| 361 | |||
| 362 | .align 2 | ||
| 363 | work_pending: | ||
| 364 | ! r0: current_thread_info->flags | ||
| 365 | ! r8: current_thread_info | ||
| 366 | ! t: result of "tst #_TIF_NEED_RESCHED, r0" | ||
| 367 | bf/s work_resched | ||
| 368 | tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0 | ||
| 369 | work_notifysig: | ||
| 370 | bt/s restore_all | ||
| 371 | mov r15, r4 | ||
| 372 | mov r12, r5 ! set arg1(save_r0) | ||
| 373 | mov r0, r6 | ||
| 374 | mov.l 2f, r1 | ||
| 375 | mova restore_all, r0 | ||
| 376 | jmp @r1 | ||
| 377 | lds r0, pr | ||
| 378 | work_resched: | ||
| 379 | #ifndef CONFIG_PREEMPT | ||
| 380 | ! gUSA handling | ||
| 381 | mov.l @(OFF_SP,r15), r0 ! get user space stack pointer | ||
| 382 | mov r0, r1 | ||
| 383 | shll r0 | ||
| 384 | bf/s 1f | ||
| 385 | shll r0 | ||
| 386 | bf/s 1f | ||
| 387 | mov #OFF_PC, r0 | ||
| 388 | ! SP >= 0xc0000000 : gUSA mark | ||
| 389 | mov.l @(r0,r15), r2 ! get user space PC (program counter) | ||
| 390 | mov.l @(OFF_R0,r15), r3 ! end point | ||
| 391 | cmp/hs r3, r2 ! r2 >= r3? | ||
| 392 | bt 1f | ||
| 393 | add r3, r1 ! rewind point #2 | ||
| 394 | mov.l r1, @(r0,r15) ! reset PC to rewind point #2 | ||
| 395 | ! | ||
| 396 | 1: | ||
| 397 | #endif | ||
| 398 | mov.l 1f, r1 | ||
| 399 | jsr @r1 ! schedule | ||
| 400 | nop | ||
| 401 | CLI() | ||
| 402 | ! | ||
| 403 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
| 404 | tst #_TIF_WORK_MASK, r0 | ||
| 405 | bt restore_all | ||
| 406 | bra work_pending | ||
| 407 | tst #_TIF_NEED_RESCHED, r0 | ||
| 408 | |||
| 409 | .align 2 | ||
| 410 | 1: .long schedule | ||
| 411 | 2: .long do_notify_resume | ||
| 412 | |||
| 413 | .align 2 | ||
| 414 | syscall_exit_work: | ||
| 415 | ! r0: current_thread_info->flags | ||
| 416 | ! r8: current_thread_info | ||
| 417 | tst #_TIF_SYSCALL_TRACE, r0 | ||
| 418 | bt/s work_pending | ||
| 419 | tst #_TIF_NEED_RESCHED, r0 | ||
| 420 | STI() | ||
| 421 | ! XXX setup arguments... | ||
| 422 | mov.l 4f, r0 ! do_syscall_trace | ||
| 423 | jsr @r0 | ||
| 424 | nop | ||
| 425 | bra resume_userspace | ||
| 426 | nop | ||
| 427 | |||
| 428 | .align 2 | ||
| 429 | syscall_trace_entry: | ||
| 430 | ! Yes it is traced. | ||
| 431 | ! XXX setup arguments... | ||
| 432 | mov.l 4f, r11 ! Call do_syscall_trace which notifies | ||
| 433 | jsr @r11 ! superior (will chomp R[0-7]) | ||
| 434 | nop | ||
| 435 | ! Reload R0-R4 from kernel stack, where the | ||
| 436 | ! parent may have modified them using | ||
| 437 | ! ptrace(POKEUSR). (Note that R0-R2 are | ||
| 438 | ! used by the system call handler directly | ||
| 439 | ! from the kernel stack anyway, so don't need | ||
| 440 | ! to be reloaded here.) This allows the parent | ||
| 441 | ! to rewrite system calls and args on the fly. | ||
| 442 | mov.l @(OFF_R4,r15), r4 ! arg0 | ||
| 443 | mov.l @(OFF_R5,r15), r5 | ||
| 444 | mov.l @(OFF_R6,r15), r6 | ||
| 445 | mov.l @(OFF_R7,r15), r7 ! arg3 | ||
| 446 | mov.l @(OFF_R3,r15), r3 ! syscall_nr | ||
| 447 | ! Arrange for do_syscall_trace to be called | ||
| 448 | ! again as the system call returns. | ||
| 449 | mov.l 2f, r10 ! Number of syscalls | ||
| 450 | cmp/hs r10, r3 | ||
| 451 | bf syscall_call | ||
| 452 | mov #-ENOSYS, r0 | ||
| 453 | bra syscall_exit | ||
| 454 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
| 455 | |||
| 456 | /* | ||
| 457 | * Syscall interface: | ||
| 458 | * | ||
| 459 | * Syscall #: R3 | ||
| 460 | * Arguments #0 to #3: R4--R7 | ||
| 461 | * Arguments #4 to #6: R0, R1, R2 | ||
| 462 | * TRA: (number of arguments + 0x10) x 4 | ||
| 463 | * | ||
| 464 | * This code also handles delegating other traps to the BIOS/gdb stub | ||
| 465 | * according to: | ||
| 466 | * | ||
| 467 | * Trap number | ||
| 468 | * (TRA>>2) Purpose | ||
| 469 | * -------- ------- | ||
| 470 | * 0x0-0xf old syscall ABI | ||
| 471 | * 0x10-0x1f new syscall ABI | ||
| 472 | * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. | ||
| 473 | * | ||
| 474 | * Note: When we're first called, the TRA value must be shifted | ||
| 475 | * right 2 bits in order to get the value that was used as the "trapa" | ||
| 476 | * argument. | ||
| 477 | */ | ||
| 478 | |||
| 479 | .align 2 | ||
| 480 | .globl ret_from_fork | ||
| 481 | ret_from_fork: | ||
| 482 | mov.l 1f, r8 | ||
| 483 | jsr @r8 | ||
| 484 | mov r0, r4 | ||
| 485 | bra syscall_exit | ||
| 486 | nop | ||
| 487 | .align 2 | ||
| 488 | 1: .long schedule_tail | ||
| 489 | ! | ||
| 490 | ENTRY(system_call) | ||
| 491 | mov.l 1f, r9 | ||
| 492 | mov.l @r9, r8 ! Read from TRA (Trap Address) Register | ||
| 493 | ! | ||
| 494 | ! Is the trap argument >= 0x20? (TRA will be >= 0x80) | ||
| 495 | mov #0x7f, r9 | ||
| 496 | cmp/hi r9, r8 | ||
| 497 | bt/s 0f | ||
| 498 | mov #OFF_TRA, r9 | ||
| 499 | add r15, r9 | ||
| 500 | ! | ||
| 501 | mov.l r8, @r9 ! set TRA value to tra | ||
| 502 | STI() | ||
| 503 | ! Call the system call handler through the table. | ||
| 504 | ! First check for bad syscall number | ||
| 505 | mov r3, r9 | ||
| 506 | mov.l 2f, r8 ! Number of syscalls | ||
| 507 | cmp/hs r8, r9 | ||
| 508 | bf/s good_system_call | ||
| 509 | GET_THREAD_INFO(r8) | ||
| 510 | syscall_badsys: ! Bad syscall number | ||
| 511 | mov #-ENOSYS, r0 | ||
| 512 | bra resume_userspace | ||
| 513 | mov.l r0, @(OFF_R0,r15) ! Return value | ||
| 514 | ! | ||
| 515 | 0: | ||
| 516 | bra debug_trap | ||
| 517 | nop | ||
| 518 | ! | ||
| 519 | good_system_call: ! Good syscall number | ||
| 520 | mov.l @(TI_FLAGS,r8), r8 | ||
| 521 | mov #_TIF_SYSCALL_TRACE, r10 | ||
| 522 | tst r10, r8 | ||
| 523 | bf syscall_trace_entry | ||
| 524 | ! | ||
| 525 | syscall_call: | ||
| 526 | shll2 r9 ! x4 | ||
| 527 | mov.l 3f, r8 ! Load the address of sys_call_table | ||
| 528 | add r8, r9 | ||
| 529 | mov.l @r9, r8 | ||
| 530 | jsr @r8 ! jump to specific syscall handler | ||
| 531 | nop | ||
| 532 | mov.l @(OFF_R0,r15), r12 ! save r0 | ||
| 533 | mov.l r0, @(OFF_R0,r15) ! save the return value | ||
| 534 | ! | ||
| 535 | syscall_exit: | ||
| 536 | CLI() | ||
| 537 | ! | ||
| 538 | GET_THREAD_INFO(r8) | ||
| 539 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | ||
| 540 | tst #_TIF_ALLWORK_MASK, r0 | ||
| 541 | bf syscall_exit_work | ||
| 542 | restore_all: | 227 | restore_all: |
| 543 | mov.l @r15+, r0 | 228 | mov.l @r15+, r0 |
| 544 | mov.l @r15+, r1 | 229 | mov.l @r15+, r1 |
| @@ -606,7 +291,9 @@ skip_restore: | |||
| 606 | ! | 291 | ! |
| 607 | ! Calculate new SR value | 292 | ! Calculate new SR value |
| 608 | mov k3, k2 ! original SR value | 293 | mov k3, k2 ! original SR value |
| 609 | mov.l 9f, k1 | 294 | mov #0xf0, k1 |
| 295 | extu.b k1, k1 | ||
| 296 | not k1, k1 | ||
| 610 | and k1, k2 ! Mask orignal SR value | 297 | and k1, k2 ! Mask orignal SR value |
| 611 | ! | 298 | ! |
| 612 | mov k3, k0 ! Calculate IMASK-bits | 299 | mov k3, k0 ! Calculate IMASK-bits |
| @@ -632,16 +319,12 @@ skip_restore: | |||
| 632 | nop | 319 | nop |
| 633 | 320 | ||
| 634 | .align 2 | 321 | .align 2 |
| 635 | 1: .long TRA | ||
| 636 | 2: .long NR_syscalls | ||
| 637 | 3: .long sys_call_table | ||
| 638 | 4: .long do_syscall_trace | ||
| 639 | 5: .long 0x00001000 ! DSP | 322 | 5: .long 0x00001000 ! DSP |
| 640 | 7: .long 0x30000000 | 323 | 7: .long 0x30000000 |
| 641 | 9: | ||
| 642 | __INV_IMASK: | ||
| 643 | .long 0xffffff0f ! ~(IMASK) | ||
| 644 | 324 | ||
| 325 | ! common exception handler | ||
| 326 | #include "../../entry.S" | ||
| 327 | |||
| 645 | ! Exception Vector Base | 328 | ! Exception Vector Base |
| 646 | ! | 329 | ! |
| 647 | ! Should be aligned page boundary. | 330 | ! Should be aligned page boundary. |
| @@ -761,7 +444,7 @@ skip_save: | |||
| 761 | ! Save the user registers on the stack. | 444 | ! Save the user registers on the stack. |
| 762 | mov.l k2, @-r15 ! EXPEVT | 445 | mov.l k2, @-r15 ! EXPEVT |
| 763 | 446 | ||
| 764 | mov #-1, k4 | 447 | mov #-1, k4 |
| 765 | mov.l k4, @-r15 ! set TRA (default: -1) | 448 | mov.l k4, @-r15 ! set TRA (default: -1) |
| 766 | ! | 449 | ! |
| 767 | sts.l macl, @-r15 | 450 | sts.l macl, @-r15 |
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8dbf3895ece7..6e415baf04b4 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | # Makefile for the Linux/SuperH SH-4 backends. | 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 | obj-$(CONFIG_SH_FPU) += fpu.o | 8 | obj-$(CONFIG_SH_FPU) += fpu.o |
| 8 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 9 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S new file mode 100644 index 000000000000..5bc7fa91d095 --- /dev/null +++ b/arch/sh/kernel/entry-common.S | |||
| @@ -0,0 +1,372 @@ | |||
| 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 | ||
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f5f53d14f245..b5ff23264617 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S | |||
| @@ -53,8 +53,10 @@ ENTRY(_stext) | |||
| 53 | ldc r0, sr | 53 | ldc r0, sr |
| 54 | ! Initialize global interrupt mask | 54 | ! Initialize global interrupt mask |
| 55 | mov #0, r0 | 55 | mov #0, r0 |
| 56 | #ifdef CONFIG_CPU_HAS_SR_RB | ||
| 56 | ldc r0, r6_bank | 57 | ldc r0, r6_bank |
| 57 | 58 | #endif | |
| 59 | |||
| 58 | /* | 60 | /* |
| 59 | * Prefetch if possible to reduce cache miss penalty. | 61 | * Prefetch if possible to reduce cache miss penalty. |
| 60 | * | 62 | * |
| @@ -71,8 +73,10 @@ ENTRY(_stext) | |||
| 71 | mov #(THREAD_SIZE >> 8), r1 | 73 | mov #(THREAD_SIZE >> 8), r1 |
| 72 | shll8 r1 ! r1 = THREAD_SIZE | 74 | shll8 r1 ! r1 = THREAD_SIZE |
| 73 | sub r1, r0 ! | 75 | sub r1, r0 ! |
| 76 | #ifdef CONFIG_CPU_HAS_SR_RB | ||
| 74 | ldc r0, r7_bank ! ... and initial thread_info | 77 | ldc r0, r7_bank ! ... and initial thread_info |
| 75 | 78 | #endif | |
| 79 | |||
| 76 | ! Clear BSS area | 80 | ! Clear BSS area |
| 77 | mov.l 3f, r1 | 81 | mov.l 3f, r1 |
| 78 | add #4, r1 | 82 | add #4, r1 |
| @@ -95,7 +99,11 @@ ENTRY(_stext) | |||
| 95 | nop | 99 | nop |
| 96 | 100 | ||
| 97 | .balign 4 | 101 | .balign 4 |
| 102 | #if defined(CONFIG_CPU_SH2) | ||
| 103 | 1: .long 0x000000F0 ! IMASK=0xF | ||
| 104 | #else | ||
| 98 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF | 105 | 1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF |
| 106 | #endif | ||
| 99 | 2: .long init_thread_union+THREAD_SIZE | 107 | 2: .long init_thread_union+THREAD_SIZE |
| 100 | 3: .long __bss_start | 108 | 3: .long __bss_start |
| 101 | 4: .long _end | 109 | 4: .long _end |
