>> 1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* 2 /* 2 * Low-level system-call handling, trap handle !! 3 * arch/alpha/kernel/entry.S 3 * 4 * 4 * Copyright (C) 2008-2009 Michal Simek <monstr !! 5 * Kernel entry-points. 5 * Copyright (C) 2008-2009 PetaLogix << 6 * Copyright (C) 2003 John Williams < << 7 * Copyright (C) 2001,2002 NEC Corporatio << 8 * Copyright (C) 2001,2002 Miles Bader <mi << 9 * << 10 * This file is subject to the terms and condi << 11 * Public License. See the file COPYING in the << 12 * archive for more details. << 13 * << 14 * Written by Miles Bader <miles@gnu.org> << 15 * Heavily modified by John Williams for Micro << 16 */ 6 */ 17 7 18 #include <linux/sys.h> << 19 #include <linux/linkage.h> << 20 << 21 #include <asm/entry.h> << 22 #include <asm/current.h> << 23 #include <asm/processor.h> << 24 #include <asm/exceptions.h> << 25 #include <asm/asm-offsets.h> 8 #include <asm/asm-offsets.h> 26 #include <asm/thread_info.h> 9 #include <asm/thread_info.h> 27 !! 10 #include <asm/pal.h> 28 #include <asm/page.h> !! 11 #include <asm/errno.h> 29 #include <asm/unistd.h> 12 #include <asm/unistd.h> 30 #include <asm/xilinx_mb_manager.h> << 31 << 32 #include <linux/errno.h> << 33 #include <asm/signal.h> << 34 #include <asm/mmu.h> << 35 << 36 #undef DEBUG << 37 << 38 #ifdef DEBUG << 39 /* Create space for syscalls counting. */ << 40 .section .data << 41 .global syscall_debug_table << 42 .align 4 << 43 syscall_debug_table: << 44 .space (__NR_syscalls * 4) << 45 #endif /* DEBUG */ << 46 << 47 #define C_ENTRY(name) .globl name; .align 4; << 48 13 49 /* !! 14 .text 50 * Various ways of setting and clearing BIP in !! 15 .set noat 51 * This is mucky, but necessary using microbla !! 16 .cfi_sections .debug_frame 52 * allows msr ops to write to BIP !! 17 53 */ !! 18 /* Stack offsets. */ 54 #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR !! 19 #define SP_OFF 184 55 .macro clear_bip !! 20 #define SWITCH_STACK_SIZE 64 56 msrclr r0, MSR_BIP !! 21 57 .endm !! 22 .macro CFI_START_OSF_FRAME func 58 !! 23 .align 4 59 .macro set_bip !! 24 .globl \func 60 msrset r0, MSR_BIP !! 25 .type \func,@function 61 .endm !! 26 \func: 62 !! 27 .cfi_startproc simple 63 .macro clear_eip !! 28 .cfi_return_column 64 64 msrclr r0, MSR_EIP !! 29 .cfi_def_cfa $sp, 48 65 .endm !! 30 .cfi_rel_offset 64, 8 66 !! 31 .cfi_rel_offset $gp, 16 67 .macro set_ee !! 32 .cfi_rel_offset $16, 24 68 msrset r0, MSR_EE !! 33 .cfi_rel_offset $17, 32 69 .endm !! 34 .cfi_rel_offset $18, 40 70 !! 35 .endm 71 .macro disable_irq !! 36 72 msrclr r0, MSR_IE !! 37 .macro CFI_END_OSF_FRAME func 73 .endm !! 38 .cfi_endproc 74 !! 39 .size \func, . - \func 75 .macro enable_irq !! 40 .endm 76 msrset r0, MSR_IE !! 41 77 .endm !! 42 /* 78 !! 43 * This defines the normal kernel pt-regs layout. 79 .macro set_ums !! 44 * 80 msrset r0, MSR_UMS !! 45 * regs 9-15 preserved by C code 81 msrclr r0, MSR_VMS !! 46 * regs 16-18 saved by PAL-code 82 .endm !! 47 * regs 29-30 saved and set up by PAL-code 83 !! 48 * JRP - Save regs 16-18 in a special area of the stack, so that 84 .macro set_vms !! 49 * the palcode-provided values are available to the signal handler. 85 msrclr r0, MSR_UMS !! 50 */ 86 msrset r0, MSR_VMS !! 51 87 .endm !! 52 .macro SAVE_ALL 88 !! 53 subq $sp, SP_OFF, $sp 89 .macro clear_ums !! 54 .cfi_adjust_cfa_offset SP_OFF 90 msrclr r0, MSR_UMS !! 55 stq $0, 0($sp) 91 .endm !! 56 stq $1, 8($sp) 92 !! 57 stq $2, 16($sp) 93 .macro clear_vms_ums !! 58 stq $3, 24($sp) 94 msrclr r0, MSR_VMS | MSR_UMS !! 59 stq $4, 32($sp) 95 .endm !! 60 stq $28, 144($sp) >> 61 .cfi_rel_offset $0, 0 >> 62 .cfi_rel_offset $1, 8 >> 63 .cfi_rel_offset $2, 16 >> 64 .cfi_rel_offset $3, 24 >> 65 .cfi_rel_offset $4, 32 >> 66 .cfi_rel_offset $28, 144 >> 67 lda $2, alpha_mv >> 68 stq $5, 40($sp) >> 69 stq $6, 48($sp) >> 70 stq $7, 56($sp) >> 71 stq $8, 64($sp) >> 72 stq $19, 72($sp) >> 73 stq $20, 80($sp) >> 74 stq $21, 88($sp) >> 75 ldq $2, HAE_CACHE($2) >> 76 stq $22, 96($sp) >> 77 stq $23, 104($sp) >> 78 stq $24, 112($sp) >> 79 stq $25, 120($sp) >> 80 stq $26, 128($sp) >> 81 stq $27, 136($sp) >> 82 stq $2, 152($sp) >> 83 stq $16, 160($sp) >> 84 stq $17, 168($sp) >> 85 stq $18, 176($sp) >> 86 .cfi_rel_offset $5, 40 >> 87 .cfi_rel_offset $6, 48 >> 88 .cfi_rel_offset $7, 56 >> 89 .cfi_rel_offset $8, 64 >> 90 .cfi_rel_offset $19, 72 >> 91 .cfi_rel_offset $20, 80 >> 92 .cfi_rel_offset $21, 88 >> 93 .cfi_rel_offset $22, 96 >> 94 .cfi_rel_offset $23, 104 >> 95 .cfi_rel_offset $24, 112 >> 96 .cfi_rel_offset $25, 120 >> 97 .cfi_rel_offset $26, 128 >> 98 .cfi_rel_offset $27, 136 >> 99 .endm >> 100 >> 101 .macro RESTORE_ALL >> 102 lda $19, alpha_mv >> 103 ldq $0, 0($sp) >> 104 ldq $1, 8($sp) >> 105 ldq $2, 16($sp) >> 106 ldq $3, 24($sp) >> 107 ldq $21, 152($sp) >> 108 ldq $20, HAE_CACHE($19) >> 109 ldq $4, 32($sp) >> 110 ldq $5, 40($sp) >> 111 ldq $6, 48($sp) >> 112 ldq $7, 56($sp) >> 113 subq $20, $21, $20 >> 114 ldq $8, 64($sp) >> 115 beq $20, 99f >> 116 ldq $20, HAE_REG($19) >> 117 stq $21, HAE_CACHE($19) >> 118 stq $21, 0($20) >> 119 99: ldq $19, 72($sp) >> 120 ldq $20, 80($sp) >> 121 ldq $21, 88($sp) >> 122 ldq $22, 96($sp) >> 123 ldq $23, 104($sp) >> 124 ldq $24, 112($sp) >> 125 ldq $25, 120($sp) >> 126 ldq $26, 128($sp) >> 127 ldq $27, 136($sp) >> 128 ldq $28, 144($sp) >> 129 addq $sp, SP_OFF, $sp >> 130 .cfi_restore $0 >> 131 .cfi_restore $1 >> 132 .cfi_restore $2 >> 133 .cfi_restore $3 >> 134 .cfi_restore $4 >> 135 .cfi_restore $5 >> 136 .cfi_restore $6 >> 137 .cfi_restore $7 >> 138 .cfi_restore $8 >> 139 .cfi_restore $19 >> 140 .cfi_restore $20 >> 141 .cfi_restore $21 >> 142 .cfi_restore $22 >> 143 .cfi_restore $23 >> 144 .cfi_restore $24 >> 145 .cfi_restore $25 >> 146 .cfi_restore $26 >> 147 .cfi_restore $27 >> 148 .cfi_restore $28 >> 149 .cfi_adjust_cfa_offset -SP_OFF >> 150 .endm >> 151 >> 152 .macro DO_SWITCH_STACK >> 153 bsr $1, do_switch_stack >> 154 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE >> 155 .cfi_rel_offset $9, 0 >> 156 .cfi_rel_offset $10, 8 >> 157 .cfi_rel_offset $11, 16 >> 158 .cfi_rel_offset $12, 24 >> 159 .cfi_rel_offset $13, 32 >> 160 .cfi_rel_offset $14, 40 >> 161 .cfi_rel_offset $15, 48 >> 162 .endm >> 163 >> 164 .macro UNDO_SWITCH_STACK >> 165 bsr $1, undo_switch_stack >> 166 .cfi_restore $9 >> 167 .cfi_restore $10 >> 168 .cfi_restore $11 >> 169 .cfi_restore $12 >> 170 .cfi_restore $13 >> 171 .cfi_restore $14 >> 172 .cfi_restore $15 >> 173 .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE >> 174 .endm >> 175 >> 176 /* >> 177 * Non-syscall kernel entry points. >> 178 */ >> 179 >> 180 CFI_START_OSF_FRAME entInt >> 181 SAVE_ALL >> 182 lda $8, 0x3fff >> 183 lda $26, ret_from_sys_call >> 184 bic $sp, $8, $8 >> 185 mov $sp, $19 >> 186 jsr $31, do_entInt >> 187 CFI_END_OSF_FRAME entInt >> 188 >> 189 CFI_START_OSF_FRAME entArith >> 190 SAVE_ALL >> 191 lda $8, 0x3fff >> 192 lda $26, ret_from_sys_call >> 193 bic $sp, $8, $8 >> 194 mov $sp, $18 >> 195 jsr $31, do_entArith >> 196 CFI_END_OSF_FRAME entArith >> 197 >> 198 CFI_START_OSF_FRAME entMM >> 199 SAVE_ALL >> 200 /* save $9 - $15 so the inline exception code can manipulate them. */ >> 201 subq $sp, 56, $sp >> 202 .cfi_adjust_cfa_offset 56 >> 203 stq $9, 0($sp) >> 204 stq $10, 8($sp) >> 205 stq $11, 16($sp) >> 206 stq $12, 24($sp) >> 207 stq $13, 32($sp) >> 208 stq $14, 40($sp) >> 209 stq $15, 48($sp) >> 210 .cfi_rel_offset $9, 0 >> 211 .cfi_rel_offset $10, 8 >> 212 .cfi_rel_offset $11, 16 >> 213 .cfi_rel_offset $12, 24 >> 214 .cfi_rel_offset $13, 32 >> 215 .cfi_rel_offset $14, 40 >> 216 .cfi_rel_offset $15, 48 >> 217 addq $sp, 56, $19 >> 218 /* handle the fault */ >> 219 lda $8, 0x3fff >> 220 bic $sp, $8, $8 >> 221 jsr $26, do_page_fault >> 222 /* reload the registers after the exception code played. */ >> 223 ldq $9, 0($sp) >> 224 ldq $10, 8($sp) >> 225 ldq $11, 16($sp) >> 226 ldq $12, 24($sp) >> 227 ldq $13, 32($sp) >> 228 ldq $14, 40($sp) >> 229 ldq $15, 48($sp) >> 230 addq $sp, 56, $sp >> 231 .cfi_restore $9 >> 232 .cfi_restore $10 >> 233 .cfi_restore $11 >> 234 .cfi_restore $12 >> 235 .cfi_restore $13 >> 236 .cfi_restore $14 >> 237 .cfi_restore $15 >> 238 .cfi_adjust_cfa_offset -56 >> 239 /* finish up the syscall as normal. */ >> 240 br ret_from_sys_call >> 241 CFI_END_OSF_FRAME entMM >> 242 >> 243 CFI_START_OSF_FRAME entIF >> 244 SAVE_ALL >> 245 lda $8, 0x3fff >> 246 lda $26, ret_from_sys_call >> 247 bic $sp, $8, $8 >> 248 mov $sp, $17 >> 249 jsr $31, do_entIF >> 250 CFI_END_OSF_FRAME entIF >> 251 >> 252 CFI_START_OSF_FRAME entUna >> 253 lda $sp, -256($sp) >> 254 .cfi_adjust_cfa_offset 256 >> 255 stq $0, 0($sp) >> 256 .cfi_rel_offset $0, 0 >> 257 .cfi_remember_state >> 258 ldq $0, 256($sp) /* get PS */ >> 259 stq $1, 8($sp) >> 260 stq $2, 16($sp) >> 261 stq $3, 24($sp) >> 262 and $0, 8, $0 /* user mode? */ >> 263 stq $4, 32($sp) >> 264 bne $0, entUnaUser /* yup -> do user-level unaligned fault */ >> 265 stq $5, 40($sp) >> 266 stq $6, 48($sp) >> 267 stq $7, 56($sp) >> 268 stq $8, 64($sp) >> 269 stq $9, 72($sp) >> 270 stq $10, 80($sp) >> 271 stq $11, 88($sp) >> 272 stq $12, 96($sp) >> 273 stq $13, 104($sp) >> 274 stq $14, 112($sp) >> 275 stq $15, 120($sp) >> 276 /* 16-18 PAL-saved */ >> 277 stq $19, 152($sp) >> 278 stq $20, 160($sp) >> 279 stq $21, 168($sp) >> 280 stq $22, 176($sp) >> 281 stq $23, 184($sp) >> 282 stq $24, 192($sp) >> 283 stq $25, 200($sp) >> 284 stq $26, 208($sp) >> 285 stq $27, 216($sp) >> 286 stq $28, 224($sp) >> 287 mov $sp, $19 >> 288 stq $gp, 232($sp) >> 289 .cfi_rel_offset $1, 1*8 >> 290 .cfi_rel_offset $2, 2*8 >> 291 .cfi_rel_offset $3, 3*8 >> 292 .cfi_rel_offset $4, 4*8 >> 293 .cfi_rel_offset $5, 5*8 >> 294 .cfi_rel_offset $6, 6*8 >> 295 .cfi_rel_offset $7, 7*8 >> 296 .cfi_rel_offset $8, 8*8 >> 297 .cfi_rel_offset $9, 9*8 >> 298 .cfi_rel_offset $10, 10*8 >> 299 .cfi_rel_offset $11, 11*8 >> 300 .cfi_rel_offset $12, 12*8 >> 301 .cfi_rel_offset $13, 13*8 >> 302 .cfi_rel_offset $14, 14*8 >> 303 .cfi_rel_offset $15, 15*8 >> 304 .cfi_rel_offset $19, 19*8 >> 305 .cfi_rel_offset $20, 20*8 >> 306 .cfi_rel_offset $21, 21*8 >> 307 .cfi_rel_offset $22, 22*8 >> 308 .cfi_rel_offset $23, 23*8 >> 309 .cfi_rel_offset $24, 24*8 >> 310 .cfi_rel_offset $25, 25*8 >> 311 .cfi_rel_offset $26, 26*8 >> 312 .cfi_rel_offset $27, 27*8 >> 313 .cfi_rel_offset $28, 28*8 >> 314 .cfi_rel_offset $29, 29*8 >> 315 lda $8, 0x3fff >> 316 stq $31, 248($sp) >> 317 bic $sp, $8, $8 >> 318 jsr $26, do_entUna >> 319 ldq $0, 0($sp) >> 320 ldq $1, 8($sp) >> 321 ldq $2, 16($sp) >> 322 ldq $3, 24($sp) >> 323 ldq $4, 32($sp) >> 324 ldq $5, 40($sp) >> 325 ldq $6, 48($sp) >> 326 ldq $7, 56($sp) >> 327 ldq $8, 64($sp) >> 328 ldq $9, 72($sp) >> 329 ldq $10, 80($sp) >> 330 ldq $11, 88($sp) >> 331 ldq $12, 96($sp) >> 332 ldq $13, 104($sp) >> 333 ldq $14, 112($sp) >> 334 ldq $15, 120($sp) >> 335 /* 16-18 PAL-saved */ >> 336 ldq $19, 152($sp) >> 337 ldq $20, 160($sp) >> 338 ldq $21, 168($sp) >> 339 ldq $22, 176($sp) >> 340 ldq $23, 184($sp) >> 341 ldq $24, 192($sp) >> 342 ldq $25, 200($sp) >> 343 ldq $26, 208($sp) >> 344 ldq $27, 216($sp) >> 345 ldq $28, 224($sp) >> 346 ldq $gp, 232($sp) >> 347 lda $sp, 256($sp) >> 348 .cfi_restore $1 >> 349 .cfi_restore $2 >> 350 .cfi_restore $3 >> 351 .cfi_restore $4 >> 352 .cfi_restore $5 >> 353 .cfi_restore $6 >> 354 .cfi_restore $7 >> 355 .cfi_restore $8 >> 356 .cfi_restore $9 >> 357 .cfi_restore $10 >> 358 .cfi_restore $11 >> 359 .cfi_restore $12 >> 360 .cfi_restore $13 >> 361 .cfi_restore $14 >> 362 .cfi_restore $15 >> 363 .cfi_restore $19 >> 364 .cfi_restore $20 >> 365 .cfi_restore $21 >> 366 .cfi_restore $22 >> 367 .cfi_restore $23 >> 368 .cfi_restore $24 >> 369 .cfi_restore $25 >> 370 .cfi_restore $26 >> 371 .cfi_restore $27 >> 372 .cfi_restore $28 >> 373 .cfi_restore $29 >> 374 .cfi_adjust_cfa_offset -256 >> 375 call_pal PAL_rti >> 376 >> 377 .align 4 >> 378 entUnaUser: >> 379 .cfi_restore_state >> 380 ldq $0, 0($sp) /* restore original $0 */ >> 381 lda $sp, 256($sp) /* pop entUna's stack frame */ >> 382 .cfi_restore $0 >> 383 .cfi_adjust_cfa_offset -256 >> 384 SAVE_ALL /* setup normal kernel stack */ >> 385 lda $sp, -56($sp) >> 386 .cfi_adjust_cfa_offset 56 >> 387 stq $9, 0($sp) >> 388 stq $10, 8($sp) >> 389 stq $11, 16($sp) >> 390 stq $12, 24($sp) >> 391 stq $13, 32($sp) >> 392 stq $14, 40($sp) >> 393 stq $15, 48($sp) >> 394 .cfi_rel_offset $9, 0 >> 395 .cfi_rel_offset $10, 8 >> 396 .cfi_rel_offset $11, 16 >> 397 .cfi_rel_offset $12, 24 >> 398 .cfi_rel_offset $13, 32 >> 399 .cfi_rel_offset $14, 40 >> 400 .cfi_rel_offset $15, 48 >> 401 lda $8, 0x3fff >> 402 addq $sp, 56, $19 >> 403 bic $sp, $8, $8 >> 404 jsr $26, do_entUnaUser >> 405 ldq $9, 0($sp) >> 406 ldq $10, 8($sp) >> 407 ldq $11, 16($sp) >> 408 ldq $12, 24($sp) >> 409 ldq $13, 32($sp) >> 410 ldq $14, 40($sp) >> 411 ldq $15, 48($sp) >> 412 lda $sp, 56($sp) >> 413 .cfi_restore $9 >> 414 .cfi_restore $10 >> 415 .cfi_restore $11 >> 416 .cfi_restore $12 >> 417 .cfi_restore $13 >> 418 .cfi_restore $14 >> 419 .cfi_restore $15 >> 420 .cfi_adjust_cfa_offset -56 >> 421 br ret_from_sys_call >> 422 CFI_END_OSF_FRAME entUna >> 423 >> 424 CFI_START_OSF_FRAME entDbg >> 425 SAVE_ALL >> 426 lda $8, 0x3fff >> 427 lda $26, ret_from_sys_call >> 428 bic $sp, $8, $8 >> 429 mov $sp, $16 >> 430 jsr $31, do_entDbg >> 431 CFI_END_OSF_FRAME entDbg >> 432 >> 433 /* >> 434 * The system call entry point is special. Most importantly, it looks >> 435 * like a function call to userspace as far as clobbered registers. We >> 436 * do preserve the argument registers (for syscall restarts) and $26 >> 437 * (for leaf syscall functions). >> 438 * >> 439 * So much for theory. We don't take advantage of this yet. >> 440 * >> 441 * Note that a0-a2 are not saved by PALcode as with the other entry points. >> 442 */ >> 443 >> 444 .align 4 >> 445 .globl entSys >> 446 .type entSys, @function >> 447 .cfi_startproc simple >> 448 .cfi_return_column 64 >> 449 .cfi_def_cfa $sp, 48 >> 450 .cfi_rel_offset 64, 8 >> 451 .cfi_rel_offset $gp, 16 >> 452 entSys: >> 453 SAVE_ALL >> 454 lda $8, 0x3fff >> 455 bic $sp, $8, $8 >> 456 lda $4, NR_syscalls($31) >> 457 stq $16, SP_OFF+24($sp) >> 458 lda $5, sys_call_table >> 459 lda $27, sys_ni_syscall >> 460 cmpult $0, $4, $4 >> 461 ldl $3, TI_FLAGS($8) >> 462 stq $17, SP_OFF+32($sp) >> 463 s8addq $0, $5, $5 >> 464 stq $18, SP_OFF+40($sp) >> 465 .cfi_rel_offset $16, SP_OFF+24 >> 466 .cfi_rel_offset $17, SP_OFF+32 >> 467 .cfi_rel_offset $18, SP_OFF+40 >> 468 #ifdef CONFIG_AUDITSYSCALL >> 469 lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT >> 470 and $3, $6, $3 >> 471 bne $3, strace 96 #else 472 #else 97 .macro clear_bip !! 473 blbs $3, strace /* check for SYSCALL_TRACE in disguise */ 98 mfs r11, rmsr << 99 andi r11, r11, ~MSR_BIP << 100 mts rmsr, r11 << 101 .endm << 102 << 103 .macro set_bip << 104 mfs r11, rmsr << 105 ori r11, r11, MSR_BIP << 106 mts rmsr, r11 << 107 .endm << 108 << 109 .macro clear_eip << 110 mfs r11, rmsr << 111 andi r11, r11, ~MSR_EIP << 112 mts rmsr, r11 << 113 .endm << 114 << 115 .macro set_ee << 116 mfs r11, rmsr << 117 ori r11, r11, MSR_EE << 118 mts rmsr, r11 << 119 .endm << 120 << 121 .macro disable_irq << 122 mfs r11, rmsr << 123 andi r11, r11, ~MSR_IE << 124 mts rmsr, r11 << 125 .endm << 126 << 127 .macro enable_irq << 128 mfs r11, rmsr << 129 ori r11, r11, MSR_IE << 130 mts rmsr, r11 << 131 .endm << 132 << 133 .macro set_ums << 134 mfs r11, rmsr << 135 ori r11, r11, MSR_VMS << 136 andni r11, r11, MSR_UMS << 137 mts rmsr, r11 << 138 .endm << 139 << 140 .macro set_vms << 141 mfs r11, rmsr << 142 ori r11, r11, MSR_VMS << 143 andni r11, r11, MSR_UMS << 144 mts rmsr, r11 << 145 .endm << 146 << 147 .macro clear_ums << 148 mfs r11, rmsr << 149 andni r11, r11, MSR_UMS << 150 mts rmsr,r11 << 151 .endm << 152 << 153 .macro clear_vms_ums << 154 mfs r11, rmsr << 155 andni r11, r11, (MSR_VMS|MSR_UMS) << 156 mts rmsr,r11 << 157 .endm << 158 #endif << 159 << 160 /* Define how to call high-level functions. Wi << 161 * enabled when calling the high-level functio << 162 * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL << 163 */ << 164 << 165 /* turn on virtual protected mode save */ << 166 #define VM_ON \ << 167 set_ums; \ << 168 rted r0, 2f; \ << 169 nop; \ << 170 2: << 171 << 172 /* turn off virtual protected mode save and us << 173 #define VM_OFF \ << 174 clear_vms_ums; \ << 175 rted r0, TOPHYS(1f); \ << 176 nop; \ << 177 1: << 178 << 179 #define SAVE_REGS \ << 180 swi r2, r1, PT_R2; /* Save SDA */ << 181 swi r3, r1, PT_R3; << 182 swi r4, r1, PT_R4; << 183 swi r5, r1, PT_R5; << 184 swi r6, r1, PT_R6; << 185 swi r7, r1, PT_R7; << 186 swi r8, r1, PT_R8; << 187 swi r9, r1, PT_R9; << 188 swi r10, r1, PT_R10; << 189 swi r11, r1, PT_R11; /* sav << 190 swi r12, r1, PT_R12; << 191 swi r13, r1, PT_R13; /* Sav << 192 swi r14, r1, PT_PC; /* PC, before << 193 swi r15, r1, PT_R15; /* Sav << 194 swi r16, r1, PT_R16; << 195 swi r17, r1, PT_R17; << 196 swi r18, r1, PT_R18; /* Sav << 197 swi r19, r1, PT_R19; << 198 swi r20, r1, PT_R20; << 199 swi r21, r1, PT_R21; << 200 swi r22, r1, PT_R22; << 201 swi r23, r1, PT_R23; << 202 swi r24, r1, PT_R24; << 203 swi r25, r1, PT_R25; << 204 swi r26, r1, PT_R26; << 205 swi r27, r1, PT_R27; << 206 swi r28, r1, PT_R28; << 207 swi r29, r1, PT_R29; << 208 swi r30, r1, PT_R30; << 209 swi r31, r1, PT_R31; /* Sav << 210 mfs r11, rmsr; /* sav << 211 swi r11, r1, PT_MSR; << 212 << 213 #define RESTORE_REGS_GP \ << 214 lwi r2, r1, PT_R2; /* restore SDA << 215 lwi r3, r1, PT_R3; << 216 lwi r4, r1, PT_R4; << 217 lwi r5, r1, PT_R5; << 218 lwi r6, r1, PT_R6; << 219 lwi r7, r1, PT_R7; << 220 lwi r8, r1, PT_R8; << 221 lwi r9, r1, PT_R9; << 222 lwi r10, r1, PT_R10; << 223 lwi r11, r1, PT_R11; /* res << 224 lwi r12, r1, PT_R12; << 225 lwi r13, r1, PT_R13; /* res << 226 lwi r14, r1, PT_PC; /* RESTORE_LIN << 227 lwi r15, r1, PT_R15; /* res << 228 lwi r16, r1, PT_R16; << 229 lwi r17, r1, PT_R17; << 230 lwi r18, r1, PT_R18; /* res << 231 lwi r19, r1, PT_R19; << 232 lwi r20, r1, PT_R20; << 233 lwi r21, r1, PT_R21; << 234 lwi r22, r1, PT_R22; << 235 lwi r23, r1, PT_R23; << 236 lwi r24, r1, PT_R24; << 237 lwi r25, r1, PT_R25; << 238 lwi r26, r1, PT_R26; << 239 lwi r27, r1, PT_R27; << 240 lwi r28, r1, PT_R28; << 241 lwi r29, r1, PT_R29; << 242 lwi r30, r1, PT_R30; << 243 lwi r31, r1, PT_R31; /* Res << 244 << 245 #define RESTORE_REGS \ << 246 lwi r11, r1, PT_MSR; << 247 mts rmsr , r11; << 248 RESTORE_REGS_GP << 249 << 250 #define RESTORE_REGS_RTBD \ << 251 lwi r11, r1, PT_MSR; << 252 andni r11, r11, MSR_EIP; /* << 253 ori r11, r11, MSR_EE | MSR_BIP; /* << 254 mts rmsr , r11; << 255 RESTORE_REGS_GP << 256 << 257 #define SAVE_STATE \ << 258 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 259 /* See if already in kernel mode.*/ << 260 mfs r1, rmsr; << 261 andi r1, r1, MSR_UMS; << 262 bnei r1, 1f; << 263 /* Kernel-mode state save. */ << 264 /* Reload kernel stack-ptr. */ << 265 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 266 /* FIXME: I can add these two lines to << 267 /* tophys(r1,r1); */ << 268 /* addik r1, r1, -PT_SIZE; */ << 269 addik r1, r1, CONFIG_KERNEL_BASE_ADD << 270 SAVE_REGS << 271 brid 2f; << 272 swi r1, r1, PT_MODE; << 273 1: /* User-mode state save. */ << 274 lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 275 tophys(r1,r1); << 276 lwi r1, r1, TS_THREAD_INFO; /* get << 277 /* MS these three instructions can be << 278 /* addik r1, r1, THREAD_SIZE; * << 279 /* tophys(r1,r1); */ << 280 /* addik r1, r1, -PT_SIZE; */ << 281 addik r1, r1, THREAD_SIZE + CONFIG_KER << 282 SAVE_REGS << 283 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 284 swi r11, r1, PT_R1; /* Store user << 285 swi r0, r1, PT_MODE; /* Was in use << 286 /* MS: I am clearing UMS even in case << 287 clear_ums; << 288 2: lwi CURRENT_TASK, r0, TOPHYS(PER_C << 289 << 290 .text << 291 << 292 .extern cpuinfo << 293 << 294 C_ENTRY(mb_flush_dcache): << 295 addik r1, r1, -PT_SIZE << 296 SAVE_REGS << 297 << 298 addik r3, r0, cpuinfo << 299 lwi r7, r3, CI_DCS << 300 lwi r8, r3, CI_DCL << 301 sub r9, r7, r8 << 302 1: << 303 wdc.flush r9, r0 << 304 bgtid r9, 1b << 305 addk r9, r9, r8 << 306 << 307 RESTORE_REGS << 308 addik r1, r1, PT_SIZE << 309 rtsd r15, 8 << 310 nop << 311 << 312 C_ENTRY(mb_invalidate_icache): << 313 addik r1, r1, -PT_SIZE << 314 SAVE_REGS << 315 << 316 addik r3, r0, cpuinfo << 317 lwi r7, r3, CI_ICS << 318 lwi r8, r3, CI_ICL << 319 sub r9, r7, r8 << 320 1: << 321 wic r9, r0 << 322 bgtid r9, 1b << 323 addk r9, r9, r8 << 324 << 325 RESTORE_REGS << 326 addik r1, r1, PT_SIZE << 327 rtsd r15, 8 << 328 nop << 329 << 330 /* << 331 * User trap. << 332 * << 333 * System calls are handled here. << 334 * << 335 * Syscall protocol: << 336 * Syscall number in r12, args in r5-r10 << 337 * Return value in r3 << 338 * << 339 * Trap entered via brki instruction, so BIP b << 340 * are masked. This is nice, means we don't ha << 341 */ << 342 C_ENTRY(_user_exception): << 343 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 344 addi r14, r14, 4 /* return addr << 345 << 346 lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 347 tophys(r1,r1); << 348 lwi r1, r1, TS_THREAD_INFO; /* get << 349 /* calculate kernel stack pointer from task st << 350 addik r1, r1, THREAD_SIZE; << 351 tophys(r1,r1); << 352 << 353 addik r1, r1, -PT_SIZE; /* Make room << 354 SAVE_REGS << 355 swi r0, r1, PT_R3 << 356 swi r0, r1, PT_R4 << 357 << 358 swi r0, r1, PT_MODE; << 359 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 360 swi r11, r1, PT_R1; /* Sto << 361 clear_ums; << 362 2: lwi CURRENT_TASK, r0, TOPHYS(PER_C << 363 /* Save away the syscall number. */ << 364 swi r12, r1, PT_R0; << 365 tovirt(r1,r1) << 366 << 367 /* where the trap should return need -8 to adj << 368 /* Jump to the appropriate function for the sy << 369 * (r12 is not preserved), or return an error << 370 * register should point to the location where << 371 * the called function should return. [note t << 372 << 373 /* Step into virtual mode */ << 374 rtbd r0, 3f << 375 nop << 376 3: << 377 lwi r11, CURRENT_TASK, TS_THREAD_I << 378 lwi r11, r11, TI_FLAGS /* ge << 379 andi r11, r11, _TIF_WORK_SYSCALL_MA << 380 beqi r11, 4f << 381 << 382 addik r3, r0, -ENOSYS << 383 swi r3, r1, PT_R3 << 384 brlid r15, do_syscall_trace_enter << 385 addik r5, r1, PT_R0 << 386 << 387 # do_syscall_trace_enter returns the n << 388 addk r12, r0, r3 << 389 lwi r5, r1, PT_R5; << 390 lwi r6, r1, PT_R6; << 391 lwi r7, r1, PT_R7; << 392 lwi r8, r1, PT_R8; << 393 lwi r9, r1, PT_R9; << 394 lwi r10, r1, PT_R10; << 395 4: << 396 /* Jump to the appropriate function for the sy << 397 * (r12 is not preserved), or return an error << 398 * The LP register should point to the locatio << 399 * should return. [note that MAKE_SYS_CALL us << 400 /* See if the system call number is va << 401 blti r12, 5f << 402 addi r11, r12, -__NR_syscalls; << 403 bgei r11, 5f; << 404 /* Figure out which function to use fo << 405 /* Note Microblaze barrel shift is opt << 406 add r12, r12, r12; << 407 add r12, r12, r12; << 408 addi r30, r0, 1 << 409 << 410 #ifdef DEBUG << 411 /* Trac syscalls and stored them to sy << 412 /* The first syscall location stores t << 413 lwi r3, r0, syscall_debug_table << 414 addi r3, r3, 1 << 415 swi r3, r0, syscall_debug_table << 416 lwi r3, r12, syscall_debug_table << 417 addi r3, r3, 1 << 418 swi r3, r12, syscall_debug_table << 419 #endif 474 #endif >> 475 beq $4, 1f >> 476 ldq $27, 0($5) >> 477 1: jsr $26, ($27), sys_ni_syscall >> 478 ldgp $gp, 0($26) >> 479 blt $0, $syscall_error /* the call failed */ >> 480 $ret_success: >> 481 stq $0, 0($sp) >> 482 stq $31, 72($sp) /* a3=0 => no error */ >> 483 >> 484 .align 4 >> 485 .globl ret_from_sys_call >> 486 ret_from_sys_call: >> 487 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ >> 488 ldq $0, SP_OFF($sp) >> 489 and $0, 8, $0 >> 490 beq $0, ret_to_kernel >> 491 ret_to_user: >> 492 /* Make sure need_resched and sigpending don't change between >> 493 sampling and the rti. */ >> 494 lda $16, 7 >> 495 call_pal PAL_swpipl >> 496 ldl $17, TI_FLAGS($8) >> 497 and $17, _TIF_WORK_MASK, $2 >> 498 bne $2, work_pending >> 499 restore_all: >> 500 ldl $2, TI_STATUS($8) >> 501 and $2, TS_SAVED_FP | TS_RESTORE_FP, $3 >> 502 bne $3, restore_fpu >> 503 restore_other: >> 504 .cfi_remember_state >> 505 RESTORE_ALL >> 506 call_pal PAL_rti >> 507 >> 508 ret_to_kernel: >> 509 .cfi_restore_state >> 510 lda $16, 7 >> 511 call_pal PAL_swpipl >> 512 br restore_other 420 513 421 # Find and jump into the syscall handl !! 514 .align 3 422 lwi r12, r12, sys_call_table !! 515 $syscall_error: 423 /* where the trap should return need - << 424 addi r15, r0, ret_from_trap-8 << 425 bra r12 << 426 << 427 /* The syscall number is invalid, retu << 428 5: << 429 braid ret_from_trap << 430 addi r3, r0, -ENOSYS; << 431 << 432 /* Entry point used to return from a syscall/t << 433 /* We re-enable BIP bit before state restore * << 434 C_ENTRY(ret_from_trap): << 435 swi r3, r1, PT_R3 << 436 swi r4, r1, PT_R4 << 437 << 438 lwi r11, r1, PT_MODE; << 439 /* See if returning to kernel mode, if so, ski << 440 bnei r11, 2f; << 441 /* We're returning to user mode, so ch << 442 * trigger rescheduling. */ << 443 /* FIXME: Restructure all these flag c << 444 lwi r11, CURRENT_TASK, TS_THREAD_I << 445 lwi r11, r11, TI_FLAGS; << 446 andi r11, r11, _TIF_WORK_SYSCALL_MA << 447 beqi r11, 1f << 448 << 449 brlid r15, do_syscall_trace_leave << 450 addik r5, r1, PT_R0 << 451 1: << 452 /* We're returning to user mode, so ch << 453 * trigger rescheduling. */ << 454 /* get thread info from current task * << 455 lwi r11, CURRENT_TASK, TS_THREAD_I << 456 lwi r19, r11, TI_FLAGS; << 457 andi r11, r19, _TIF_NEED_RESCHED; << 458 beqi r11, 5f; << 459 << 460 bralid r15, schedule; /* Call schedu << 461 nop; /* del << 462 bri 1b << 463 << 464 /* Maybe handle a signal */ << 465 5: << 466 andi r11, r19, _TIF_SIGPENDING | _T << 467 beqi r11, 4f; /* Sig << 468 << 469 addik r5, r1, 0; /* Arg << 470 bralid r15, do_notify_resume; /* Han << 471 add r6, r30, r0; /* Arg << 472 add r30, r0, r0 /* no << 473 bri 1b << 474 << 475 /* Finally, return to user state. */ << 476 4: set_bip; /* In << 477 swi CURRENT_TASK, r0, PER_CPU(CURR << 478 VM_OFF; << 479 tophys(r1,r1); << 480 RESTORE_REGS_RTBD; << 481 addik r1, r1, PT_SIZE /* Cle << 482 lwi r1, r1, PT_R1 - PT_SIZE;/* Res << 483 bri 6f; << 484 << 485 /* Return to kernel state. */ << 486 2: set_bip; /* In << 487 VM_OFF; << 488 tophys(r1,r1); << 489 RESTORE_REGS_RTBD; << 490 addik r1, r1, PT_SIZE /* Cle << 491 tovirt(r1,r1); << 492 6: << 493 TRAP_return: /* Make global symbol << 494 rtbd r14, 0; /* Instructions to ret << 495 nop; << 496 << 497 << 498 /* This the initial entry point for a new chil << 499 stack in place that makes it look like the << 500 syscall. This function is actually `return << 501 (copy_thread makes ret_from_fork the return << 502 saved context). */ << 503 C_ENTRY(ret_from_fork): << 504 bralid r15, schedule_tail; /* ...whic << 505 add r5, r3, r0; /* switch_thre << 506 /* ( in the de << 507 brid ret_from_trap; /* Do normal t << 508 add r3, r0, r0; /* Child's for << 509 << 510 C_ENTRY(ret_from_kernel_thread): << 511 bralid r15, schedule_tail; /* ...whic << 512 add r5, r3, r0; /* switch_thre << 513 /* ( in the de << 514 brald r15, r20 /* fn was left << 515 addk r5, r0, r19 /* ... and arg << 516 brid ret_from_trap << 517 add r3, r0, r0 << 518 << 519 C_ENTRY(sys_rt_sigreturn_wrapper): << 520 addik r30, r0, 0 /* no << 521 brid sys_rt_sigreturn /* Do << 522 addik r5, r1, 0; /* add << 523 << 524 /* << 525 * HW EXCEPTION rutine start << 526 */ << 527 C_ENTRY(full_exception_trap): << 528 /* adjust exception address for privil << 529 * for finding where is it */ << 530 addik r17, r17, -4 << 531 SAVE_STATE /* Save registers */ << 532 /* PC, before IRQ/trap - this is one i << 533 swi r17, r1, PT_PC; << 534 tovirt(r1,r1) << 535 /* FIXME this can be store directly in << 536 * I tested it but there is a fault */ << 537 /* where the trap should return need - << 538 addik r15, r0, ret_from_exc - 8 << 539 mfs r6, resr << 540 mfs r7, rfsr; /* sav << 541 mts rfsr, r0; /* Clear stick << 542 rted r0, full_exception << 543 addik r5, r1, 0 /* pa << 544 << 545 /* << 546 * Unaligned data trap. << 547 * << 548 * Unaligned data trap last on 4k page is hand << 549 * << 550 * Trap entered via exception, so EE bit is se << 551 * are masked. This is nice, means we don't h << 552 * << 553 * The assembler routine is in "arch/microblaz << 554 */ << 555 C_ENTRY(unaligned_data_trap): << 556 /* MS: I have to save r11 value and th << 557 * set_bit, clear_eip, set_ee use r11 << 558 * instructions are not used. We don't << 559 * are used and they use r0 instead of << 560 * I am using ENTRY_SP which should be << 561 * pointer saving. */ << 562 swi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 563 set_bip; /* equalize initial st << 564 clear_eip; << 565 set_ee; << 566 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 567 SAVE_STATE /* Save regist << 568 /* PC, before IRQ/trap - this is one i << 569 swi r17, r1, PT_PC; << 570 tovirt(r1,r1) << 571 /* where the trap should return need - << 572 addik r15, r0, ret_from_exc-8 << 573 mfs r3, resr /* ESR << 574 mfs r4, rear /* EAR << 575 rtbd r0, _unaligned_data_exception << 576 addik r7, r1, 0 /* par << 577 << 578 /* << 579 * Page fault traps. << 580 * << 581 * If the real exception handler (from hw_exce << 582 * the mapping for the process, then we're thr << 583 * << 584 * Trap entered via exceptions, so EE bit is s << 585 * are masked. This is nice, means we don't h << 586 * << 587 * Build a standard exception frame for TLB Ac << 588 * will bail out to this point if they can't r << 589 * << 590 * The C function called is in "arch/microblaz << 591 * void do_page_fault(struct pt_regs *regs, << 592 * unsigned long << 593 * unsigned long << 594 */ << 595 /* data and intruction trap - which is choose << 596 C_ENTRY(page_fault_data_trap): << 597 SAVE_STATE /* Save regist << 598 /* PC, before IRQ/trap - this is one i << 599 swi r17, r1, PT_PC; << 600 tovirt(r1,r1) << 601 /* where the trap should return need - << 602 addik r15, r0, ret_from_exc-8 << 603 mfs r6, rear /* par << 604 mfs r7, resr /* par << 605 rted r0, do_page_fault << 606 addik r5, r1, 0 /* par << 607 << 608 C_ENTRY(page_fault_instr_trap): << 609 SAVE_STATE /* Save regist << 610 /* PC, before IRQ/trap - this is one i << 611 swi r17, r1, PT_PC; << 612 tovirt(r1,r1) << 613 /* where the trap should return need - << 614 addik r15, r0, ret_from_exc-8 << 615 mfs r6, rear /* par << 616 ori r7, r0, 0 /* par << 617 rted r0, do_page_fault << 618 addik r5, r1, 0 /* par << 619 << 620 /* Entry point used to return from an exceptio << 621 C_ENTRY(ret_from_exc): << 622 lwi r11, r1, PT_MODE; << 623 bnei r11, 2f; /* See << 624 /* ... << 625 << 626 /* We're returning to user mode, so ch << 627 trigger rescheduling. */ << 628 1: << 629 lwi r11, CURRENT_TASK, TS_THREAD_I << 630 lwi r19, r11, TI_FLAGS; /* get << 631 andi r11, r19, _TIF_NEED_RESCHED; << 632 beqi r11, 5f; << 633 << 634 /* Call the scheduler before returning from a << 635 bralid r15, schedule; /* Call schedu << 636 nop; /* del << 637 bri 1b << 638 << 639 /* Maybe handle a signal */ << 640 5: andi r11, r19, _TIF_SIGPENDING | _T << 641 beqi r11, 4f; /* Sig << 642 << 643 /* 516 /* 644 * Handle a signal return; Pending sig !! 517 * Some system calls (e.g., ptrace) can return arbitrary 645 * !! 518 * values which might normally be mistaken as error numbers. 646 * Not all registers are saved by the !! 519 * Those functions must zero $0 (v0) directly in the stack 647 * points (for instance, call-saved re !! 520 * frame to indicate that a negative return value wasn't an 648 * C-compiler calling sequence in the !! 521 * error number.. 649 * preserved), and call-clobbered regi << 650 * traps), but signal handlers may wan << 651 * complete register state. Here we s << 652 * the normal entry sequence, so that << 653 * (in a possibly modified form) after << 654 addik r5, r1, 0; /* Arg << 655 bralid r15, do_notify_resume; /* Han << 656 addi r6, r0, 0; /* Arg << 657 bri 1b << 658 << 659 /* Finally, return to user state. */ << 660 4: set_bip; /* Int << 661 swi CURRENT_TASK, r0, PER_CPU(CURR << 662 VM_OFF; << 663 tophys(r1,r1); << 664 << 665 RESTORE_REGS_RTBD; << 666 addik r1, r1, PT_SIZE /* Cle << 667 << 668 lwi r1, r1, PT_R1 - PT_SIZE; /* Re << 669 bri 6f; << 670 /* Return to kernel state. */ << 671 2: set_bip; /* Int << 672 VM_OFF; << 673 tophys(r1,r1); << 674 RESTORE_REGS_RTBD; << 675 addik r1, r1, PT_SIZE /* Cle << 676 << 677 tovirt(r1,r1); << 678 6: << 679 EXC_return: /* Make global symbol << 680 rtbd r14, 0; /* Instructions to ret << 681 nop; << 682 << 683 /* << 684 * HW EXCEPTION rutine end << 685 */ << 686 << 687 /* << 688 * Hardware maskable interrupts. << 689 * << 690 * The stack-pointer (r1) should have already << 691 * location PER_CPU(ENTRY_SP). << 692 */ << 693 C_ENTRY(_interrupt): << 694 /* MS: we are in physical address */ << 695 /* Save registers, switch to proper stack, con << 696 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 697 /* MS: See if already in kernel mode. << 698 mfs r1, rmsr << 699 nop << 700 andi r1, r1, MSR_UMS << 701 bnei r1, 1f << 702 << 703 /* Kernel-mode state save. */ << 704 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S << 705 tophys(r1,r1); /* MS: I have in r1 phy << 706 /* save registers */ << 707 /* MS: Make room on the stack -> activation re << 708 addik r1, r1, -PT_SIZE; << 709 SAVE_REGS << 710 brid 2f; << 711 swi r1, r1, PT_MODE; /* 0 - user m << 712 1: << 713 /* User-mode state save. */ << 714 /* MS: get the saved current */ << 715 lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 716 tophys(r1,r1); << 717 lwi r1, r1, TS_THREAD_INFO; << 718 addik r1, r1, THREAD_SIZE; << 719 tophys(r1,r1); << 720 /* save registers */ << 721 addik r1, r1, -PT_SIZE; << 722 SAVE_REGS << 723 /* calculate mode */ << 724 swi r0, r1, PT_MODE; << 725 lwi r11, r0, TOPHYS(PER_CPU(ENTRY_ << 726 swi r11, r1, PT_R1; << 727 clear_ums; << 728 2: << 729 lwi CURRENT_TASK, r0, TOPHYS(PER_C << 730 tovirt(r1,r1) << 731 addik r15, r0, irq_call; << 732 irq_call:rtbd r0, do_IRQ; << 733 addik r5, r1, 0; << 734 << 735 /* MS: we are in virtual mode */ << 736 ret_from_irq: << 737 lwi r11, r1, PT_MODE; << 738 bnei r11, 2f; << 739 << 740 1: << 741 lwi r11, CURRENT_TASK, TS_THREAD_I << 742 lwi r19, r11, TI_FLAGS; /* MS: get << 743 andi r11, r19, _TIF_NEED_RESCHED; << 744 beqi r11, 5f << 745 bralid r15, schedule; << 746 nop; /* delay slot */ << 747 bri 1b << 748 << 749 /* Maybe handle a signal */ << 750 5: andi r11, r19, _TIF_SIGPENDING | _T << 751 beqid r11, no_intr_resched << 752 /* Handle a signal return; Pending signals sho << 753 addik r5, r1, 0; /* Arg 1: struct pt << 754 bralid r15, do_notify_resume; /* Han << 755 addi r6, r0, 0; /* Arg 2: int in_sy << 756 bri 1b << 757 << 758 /* Finally, return to user state. */ << 759 no_intr_resched: << 760 /* Disable interrupts, we are now committe << 761 disable_irq << 762 swi CURRENT_TASK, r0, PER_CPU(CURR << 763 VM_OFF; << 764 tophys(r1,r1); << 765 RESTORE_REGS << 766 addik r1, r1, PT_SIZE /* MS: Clean u << 767 lwi r1, r1, PT_R1 - PT_SIZE; << 768 bri 6f; << 769 /* MS: Return to kernel state. */ << 770 2: << 771 #ifdef CONFIG_PREEMPTION << 772 lwi r11, CURRENT_TASK, TS_THREAD_I << 773 /* MS: get preempt_count from thread i << 774 lwi r5, r11, TI_PREEMPT_COUNT; << 775 bgti r5, restore; << 776 << 777 lwi r5, r11, TI_FLAGS; << 778 andi r5, r5, _TIF_NEED_RESCHED; << 779 beqi r5, restore /* if zero jump ov << 780 << 781 /* interrupts are off that's why I am << 782 bralid r15, preempt_schedule_irq << 783 nop << 784 restore: << 785 #endif << 786 VM_OFF /* MS: turn off MMU */ << 787 tophys(r1,r1) << 788 RESTORE_REGS << 789 addik r1, r1, PT_SIZE /* MS: Clean u << 790 tovirt(r1,r1); << 791 6: << 792 IRQ_return: /* MS: Make global symbol for debu << 793 rtid r14, 0 << 794 nop << 795 << 796 #ifdef CONFIG_MB_MANAGER << 797 << 798 #define PT_PID PT_SIZE << 799 #define PT_TLBI PT_SIZE + 4 << 800 #define PT_ZPR PT_SIZE + 8 << 801 #define PT_TLBL0 PT_SIZE + 12 << 802 #define PT_TLBH0 PT_SIZE + 16 << 803 << 804 C_ENTRY(_xtmr_manager_reset): << 805 lwi r1, r0, xmb_manager_stackpoint << 806 << 807 /* Restore MSR */ << 808 lwi r2, r1, PT_MSR << 809 mts rmsr, r2 << 810 bri 4 << 811 << 812 /* restore Special purpose registers * << 813 lwi r2, r1, PT_PID << 814 mts rpid, r2 << 815 << 816 lwi r2, r1, PT_TLBI << 817 mts rtlbx, r2 << 818 << 819 lwi r2, r1, PT_ZPR << 820 mts rzpr, r2 << 821 << 822 #if CONFIG_XILINX_MICROBLAZE0_USE_FPU << 823 lwi r2, r1, PT_FSR << 824 mts rfsr, r2 << 825 #endif << 826 << 827 /* restore all the tlb's */ << 828 addik r3, r0, TOPHYS(tlb_skip) << 829 addik r6, r0, PT_TLBL0 << 830 addik r7, r0, PT_TLBH0 << 831 restore_tlb: << 832 add r6, r6, r1 << 833 add r7, r7, r1 << 834 lwi r2, r6, 0 << 835 mts rtlblo, r2 << 836 lwi r2, r7, 0 << 837 mts rtlbhi, r2 << 838 addik r6, r6, 4 << 839 addik r7, r7, 4 << 840 bgtid r3, restore_tlb << 841 addik r3, r3, -1 << 842 << 843 lwi r5, r0, TOPHYS(xmb_manager_dev << 844 lwi r8, r0, TOPHYS(xmb_manager_res << 845 set_vms << 846 /* return from reset need -8 to adjust << 847 addik r15, r0, ret_from_reset - 8 << 848 rtbd r8, 0 << 849 nop << 850 << 851 ret_from_reset: << 852 set_bip /* Ints masked for state resto << 853 VM_OFF << 854 /* MS: Restore all regs */ << 855 RESTORE_REGS << 856 lwi r14, r1, PT_R14 << 857 lwi r16, r1, PT_PC << 858 addik r1, r1, PT_SIZE + 36 << 859 rtbd r16, 0 << 860 nop << 861 << 862 /* << 863 * Break handler for MB Manager. Enter to _xmb << 864 * injecting fault in one of the TMR Microblaz << 865 * FIXME: This break handler supports getting << 866 * called from kernel space only. << 867 */ << 868 C_ENTRY(_xmb_manager_break): << 869 /* << 870 * Reserve memory in the stack for con << 871 * (which includes memory for storing << 872 */ << 873 addik r1, r1, -PT_SIZE - 36 << 874 swi r1, r0, xmb_manager_stackpoint << 875 SAVE_REGS << 876 swi r14, r1, PT_R14 /* rewrite sav << 877 swi r16, r1, PT_PC; /* PC and r16 << 878 << 879 lwi r6, r0, TOPHYS(xmb_manager_bas << 880 lwi r7, r0, TOPHYS(xmb_manager_crv << 881 /* << 882 * When the break vector gets asserted << 883 * the break signal must be blocked be << 884 * break handler, below code configure << 885 * control register to block break sig << 886 */ 522 */ 887 swi r7, r6, 0 !! 523 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 888 !! 524 beq $18, $ret_success 889 /* Save the special purpose registers << 890 mfs r2, rpid << 891 swi r2, r1, PT_PID << 892 << 893 mfs r2, rtlbx << 894 swi r2, r1, PT_TLBI << 895 525 896 mfs r2, rzpr !! 526 ldq $19, 72($sp) /* .. and this a3 */ 897 swi r2, r1, PT_ZPR !! 527 subq $31, $0, $0 /* with error in v0 */ 898 !! 528 addq $31, 1, $1 /* set a3 for errno return */ 899 #if CONFIG_XILINX_MICROBLAZE0_USE_FPU !! 529 stq $0, 0($sp) 900 mfs r2, rfsr !! 530 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 901 swi r2, r1, PT_FSR !! 531 stq $1, 72($sp) /* a3 for return */ 902 #endif !! 532 br ret_from_sys_call 903 mfs r2, rmsr !! 533 904 swi r2, r1, PT_MSR !! 534 /* 905 !! 535 * Do all cleanup when returning from all interrupts and system calls. 906 /* Save all the tlb's */ !! 536 * 907 addik r3, r0, TOPHYS(tlb_skip) !! 537 * Arguments: 908 addik r6, r0, PT_TLBL0 !! 538 * $8: current. 909 addik r7, r0, PT_TLBH0 !! 539 * $17: TI_FLAGS. 910 save_tlb: !! 540 * $18: The old syscall number, or zero if this is not a return 911 add r6, r6, r1 !! 541 * from a syscall that errored and is possibly restartable. 912 add r7, r7, r1 !! 542 * $19: The old a3 value 913 mfs r2, rtlblo !! 543 */ 914 swi r2, r6, 0 !! 544 915 mfs r2, rtlbhi !! 545 .align 4 916 swi r2, r7, 0 !! 546 .type work_pending, @function 917 addik r6, r6, 4 !! 547 work_pending: 918 addik r7, r7, 4 !! 548 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL, $2 919 bgtid r3, save_tlb !! 549 bne $2, $work_notifysig 920 addik r3, r3, -1 << 921 << 922 lwi r5, r0, TOPHYS(xmb_manager_dev << 923 lwi r8, r0, TOPHYS(xmb_manager_cal << 924 /* return from break need -8 to adjust << 925 addik r15, r0, ret_from_break - 8 << 926 rtbd r8, 0 << 927 nop << 928 << 929 ret_from_break: << 930 /* flush the d-cache */ << 931 bralid r15, mb_flush_dcache << 932 nop << 933 550 >> 551 $work_resched: 934 /* 552 /* 935 * To make sure microblaze i-cache is !! 553 * We can get here only if we returned from syscall without SIGPENDING 936 * invalidate the i-cache. !! 554 * or got through work_notifysig already. Either case means no syscall >> 555 * restarts for us, so let $18 and $19 burn. 937 */ 556 */ 938 bralid r15, mb_invalidate_icache !! 557 jsr $26, schedule 939 nop !! 558 mov 0, $18 940 !! 559 br ret_to_user 941 set_bip; /* Ints masked for state rest !! 560 942 VM_OFF; !! 561 $work_notifysig: 943 mbar 1 !! 562 mov $sp, $16 944 mbar 2 !! 563 DO_SWITCH_STACK 945 bri 4 !! 564 jsr $26, do_work_pending 946 suspend !! 565 UNDO_SWITCH_STACK 947 nop !! 566 br restore_all 948 #endif !! 567 949 !! 568 /* 950 /* !! 569 * PTRACE syscall handler 951 * Debug trap for KGDB. Enter to _debug_except !! 570 */ 952 * and call handling function with saved pt_re !! 571 953 */ !! 572 .align 4 954 C_ENTRY(_debug_exception): !! 573 .type strace, @function 955 /* BIP bit is set on entry, no interru !! 574 strace: 956 swi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 575 /* set up signal stack, call syscall_trace */ 957 !! 576 // NB: if anyone adds preemption, this block will need to be protected 958 mfs r1, rmsr !! 577 ldl $1, TI_STATUS($8) 959 nop !! 578 and $1, TS_SAVED_FP, $3 960 andi r1, r1, MSR_UMS !! 579 or $1, TS_SAVED_FP, $2 961 bnei r1, 1f !! 580 bne $3, 1f 962 /* MS: Kernel-mode state save - kgdb */ !! 581 stl $2, TI_STATUS($8) 963 lwi r1, r0, TOPHYS(PER_CPU(ENTRY_S !! 582 bsr $26, __save_fpu 964 << 965 /* BIP bit is set on entry, no interru << 966 addik r1, r1, CONFIG_KERNEL_BASE_ADD << 967 SAVE_REGS; << 968 /* save all regs to pt_reg structure * << 969 swi r0, r1, PT_R0; /* R0 must be << 970 swi r14, r1, PT_R14 /* rewrite sav << 971 swi r16, r1, PT_PC; /* PC and r16 << 972 /* save special purpose registers to p << 973 mfs r11, rear; << 974 swi r11, r1, PT_EAR; << 975 mfs r11, resr; << 976 swi r11, r1, PT_ESR; << 977 mfs r11, rfsr; << 978 swi r11, r1, PT_FSR; << 979 << 980 /* stack pointer is in physical addres << 981 * by PT_SIZE but we need to get corre << 982 addik r11, r1, CONFIG_KERNEL_START - << 983 swi r11, r1, PT_R1 << 984 /* MS: r31 - current pointer isn't cha << 985 tovirt(r1,r1) << 986 #ifdef CONFIG_KGDB << 987 addi r5, r1, 0 /* pass pt_reg addre << 988 addik r15, r0, dbtrap_call; /* retur << 989 rtbd r0, microblaze_kgdb_break << 990 nop; << 991 #endif << 992 /* MS: Place handler for brki from ker << 993 * It is very unlikely that another br << 994 bri 0 << 995 << 996 /* MS: User-mode state save - gdb */ << 997 1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT << 998 tophys(r1,r1); << 999 lwi r1, r1, TS_THREAD_INFO; /* get << 1000 addik r1, r1, THREAD_SIZE; /* ca << 1001 tophys(r1,r1); << 1002 << 1003 addik r1, r1, -PT_SIZE; /* Make roo << 1004 SAVE_REGS; << 1005 swi r16, r1, PT_PC; /* Save LP */ << 1006 swi r0, r1, PT_MODE; /* Was in us << 1007 lwi r11, r0, TOPHYS(PER_CPU(ENTRY << 1008 swi r11, r1, PT_R1; /* Store user << 1009 lwi CURRENT_TASK, r0, TOPHYS(PER_ << 1010 tovirt(r1,r1) << 1011 set_vms; << 1012 addik r5, r1, 0; << 1013 addik r15, r0, dbtrap_call; << 1014 dbtrap_call: /* Return point for kernel/user << 1015 rtbd r0, sw_exception << 1016 nop << 1017 << 1018 /* MS: The first instruction for the << 1019 set_bip; /* Ints masked for state res << 1020 lwi r11, r1, PT_MODE; << 1021 bnei r11, 2f; << 1022 /* MS: Return to user space - gdb */ << 1023 1: 583 1: 1024 /* Get current task ptr into r11 */ !! 584 DO_SWITCH_STACK 1025 lwi r11, CURRENT_TASK, TS_THREAD_ !! 585 jsr $26, syscall_trace_enter /* returns the syscall number */ 1026 lwi r19, r11, TI_FLAGS; /* ge !! 586 UNDO_SWITCH_STACK 1027 andi r11, r19, _TIF_NEED_RESCHED; !! 587 1028 beqi r11, 5f; !! 588 /* get the arguments back.. */ 1029 !! 589 ldq $16, SP_OFF+24($sp) 1030 /* Call the scheduler before returnin !! 590 ldq $17, SP_OFF+32($sp) 1031 bralid r15, schedule; /* Call sched !! 591 ldq $18, SP_OFF+40($sp) 1032 nop; /* de !! 592 ldq $19, 72($sp) 1033 bri 1b !! 593 ldq $20, 80($sp) 1034 !! 594 ldq $21, 88($sp) 1035 /* Maybe handle a signal */ !! 595 1036 5: andi r11, r19, _TIF_SIGPENDING | _ !! 596 /* get the system call pointer.. */ 1037 beqi r11, 4f; /* Si !! 597 lda $1, NR_syscalls($31) 1038 !! 598 lda $2, sys_call_table 1039 addik r5, r1, 0; /* Ar !! 599 lda $27, sys_ni_syscall 1040 bralid r15, do_notify_resume; /* Ha !! 600 cmpult $0, $1, $1 1041 addi r6, r0, 0; /* Arg 2: int !! 601 s8addq $0, $2, $2 1042 bri 1b !! 602 beq $1, 1f 1043 !! 603 ldq $27, 0($2) 1044 /* Finally, return to user state. */ !! 604 1: jsr $26, ($27), sys_gettimeofday 1045 4: swi CURRENT_TASK, r0, PER_CPU(CUR !! 605 ret_from_straced: 1046 VM_OFF; !! 606 ldgp $gp, 0($26) 1047 tophys(r1,r1); !! 607 1048 /* MS: Restore all regs */ !! 608 /* check return.. */ 1049 RESTORE_REGS_RTBD !! 609 blt $0, $strace_error /* the call failed */ 1050 addik r1, r1, PT_SIZE /* Clean up !! 610 $strace_success: 1051 lwi r1, r1, PT_R1 - PT_SIZE; /* R !! 611 stq $31, 72($sp) /* a3=0 => no error */ 1052 DBTRAP_return_user: /* MS: Make global symbol !! 612 stq $0, 0($sp) /* save return value */ 1053 rtbd r16, 0; /* MS: Instructions t !! 613 1054 nop; !! 614 DO_SWITCH_STACK 1055 !! 615 jsr $26, syscall_trace_leave 1056 /* MS: Return to kernel state - kgdb */ !! 616 UNDO_SWITCH_STACK 1057 2: VM_OFF; !! 617 br $31, ret_from_sys_call 1058 tophys(r1,r1); !! 618 1059 /* MS: Restore all regs */ !! 619 .align 3 1060 RESTORE_REGS_RTBD !! 620 $strace_error: 1061 lwi r14, r1, PT_R14; !! 621 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 1062 lwi r16, r1, PT_PC; !! 622 beq $18, $strace_success 1063 addik r1, r1, PT_SIZE; /* MS: Clean !! 623 ldq $19, 72($sp) /* .. and this a3 */ 1064 tovirt(r1,r1); !! 624 1065 DBTRAP_return_kernel: /* MS: Make global symb !! 625 subq $31, $0, $0 /* with error in v0 */ 1066 rtbd r16, 0; /* MS: Instructions t !! 626 addq $31, 1, $1 /* set a3 for errno return */ 1067 nop; !! 627 stq $0, 0($sp) 1068 !! 628 stq $1, 72($sp) /* a3 for return */ 1069 !! 629 1070 ENTRY(_switch_to) !! 630 DO_SWITCH_STACK 1071 /* prepare return value */ !! 631 mov $18, $9 /* save old syscall number */ 1072 addk r3, r0, CURRENT_TASK !! 632 mov $19, $10 /* save old a3 */ 1073 !! 633 jsr $26, syscall_trace_leave 1074 /* save registers in cpu_context */ !! 634 mov $9, $18 1075 /* use r11 and r12, volatile register !! 635 mov $10, $19 1076 /* give start of cpu_context for prev !! 636 UNDO_SWITCH_STACK 1077 addik r11, r5, TI_CPU_CONTEXT !! 637 1078 swi r1, r11, CC_R1 !! 638 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 1079 swi r2, r11, CC_R2 !! 639 br ret_from_sys_call 1080 /* skip volatile registers. !! 640 CFI_END_OSF_FRAME entSys 1081 * they are saved on stack when we ju !! 641 1082 /* dedicated registers */ !! 642 /* 1083 swi r13, r11, CC_R13 !! 643 * Save and restore the switch stack -- aka the balance of the user context. 1084 swi r14, r11, CC_R14 !! 644 */ 1085 swi r15, r11, CC_R15 !! 645 1086 swi r16, r11, CC_R16 !! 646 .align 4 1087 swi r17, r11, CC_R17 !! 647 .type do_switch_stack, @function 1088 swi r18, r11, CC_R18 !! 648 .cfi_startproc simple 1089 /* save non-volatile registers */ !! 649 .cfi_return_column 64 1090 swi r19, r11, CC_R19 !! 650 .cfi_def_cfa $sp, 0 1091 swi r20, r11, CC_R20 !! 651 .cfi_register 64, $1 1092 swi r21, r11, CC_R21 !! 652 do_switch_stack: 1093 swi r22, r11, CC_R22 !! 653 lda $sp, -SWITCH_STACK_SIZE($sp) 1094 swi r23, r11, CC_R23 !! 654 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE 1095 swi r24, r11, CC_R24 !! 655 stq $9, 0($sp) 1096 swi r25, r11, CC_R25 !! 656 stq $10, 8($sp) 1097 swi r26, r11, CC_R26 !! 657 stq $11, 16($sp) 1098 swi r27, r11, CC_R27 !! 658 stq $12, 24($sp) 1099 swi r28, r11, CC_R28 !! 659 stq $13, 32($sp) 1100 swi r29, r11, CC_R29 !! 660 stq $14, 40($sp) 1101 swi r30, r11, CC_R30 !! 661 stq $15, 48($sp) 1102 /* special purpose registers */ !! 662 stq $26, 56($sp) 1103 mfs r12, rmsr !! 663 ret $31, ($1), 1 1104 swi r12, r11, CC_MSR !! 664 .cfi_endproc 1105 mfs r12, rear !! 665 .size do_switch_stack, .-do_switch_stack 1106 swi r12, r11, CC_EAR !! 666 1107 mfs r12, resr !! 667 .align 4 1108 swi r12, r11, CC_ESR !! 668 .type undo_switch_stack, @function 1109 mfs r12, rfsr !! 669 .cfi_startproc simple 1110 swi r12, r11, CC_FSR !! 670 .cfi_def_cfa $sp, 0 1111 !! 671 .cfi_register 64, $1 1112 /* update r31, the current-give me po !! 672 undo_switch_stack: 1113 lwi CURRENT_TASK, r6, TI_TASK !! 673 ldq $9, 0($sp) 1114 /* stored it to current_save too */ !! 674 ldq $10, 8($sp) 1115 swi CURRENT_TASK, r0, PER_CPU(CUR !! 675 ldq $11, 16($sp) 1116 !! 676 ldq $12, 24($sp) 1117 /* get new process' cpu context and r !! 677 ldq $13, 32($sp) 1118 /* give me start where start context !! 678 ldq $14, 40($sp) 1119 addik r11, r6, TI_CPU_CONTEXT !! 679 ldq $15, 48($sp) 1120 !! 680 ldq $26, 56($sp) 1121 /* non-volatile registers */ !! 681 lda $sp, SWITCH_STACK_SIZE($sp) 1122 lwi r30, r11, CC_R30 !! 682 ret $31, ($1), 1 1123 lwi r29, r11, CC_R29 !! 683 .cfi_endproc 1124 lwi r28, r11, CC_R28 !! 684 .size undo_switch_stack, .-undo_switch_stack 1125 lwi r27, r11, CC_R27 !! 685 1126 lwi r26, r11, CC_R26 !! 686 #define FR(n) n * 8 + TI_FP($8) 1127 lwi r25, r11, CC_R25 !! 687 .align 4 1128 lwi r24, r11, CC_R24 !! 688 .globl __save_fpu 1129 lwi r23, r11, CC_R23 !! 689 .type __save_fpu, @function 1130 lwi r22, r11, CC_R22 !! 690 __save_fpu: 1131 lwi r21, r11, CC_R21 !! 691 #define V(n) stt $f##n, FR(n) 1132 lwi r20, r11, CC_R20 !! 692 V( 0); V( 1); V( 2); V( 3) 1133 lwi r19, r11, CC_R19 !! 693 V( 4); V( 5); V( 6); V( 7) 1134 /* dedicated registers */ !! 694 V( 8); V( 9); V(10); V(11) 1135 lwi r18, r11, CC_R18 !! 695 V(12); V(13); V(14); V(15) 1136 lwi r17, r11, CC_R17 !! 696 V(16); V(17); V(18); V(19) 1137 lwi r16, r11, CC_R16 !! 697 V(20); V(21); V(22); V(23) 1138 lwi r15, r11, CC_R15 !! 698 V(24); V(25); V(26); V(27) 1139 lwi r14, r11, CC_R14 !! 699 mf_fpcr $f0 # get fpcr 1140 lwi r13, r11, CC_R13 !! 700 V(28); V(29); V(30) 1141 /* skip volatile registers */ !! 701 stt $f0, FR(31) # save fpcr in slot of $f31 1142 lwi r2, r11, CC_R2 !! 702 ldt $f0, FR(0) # don't let "__save_fpu" change fp state. 1143 lwi r1, r11, CC_R1 !! 703 ret 1144 !! 704 #undef V 1145 /* special purpose registers */ !! 705 .size __save_fpu, .-__save_fpu 1146 lwi r12, r11, CC_FSR !! 706 1147 mts rfsr, r12 !! 707 .align 4 1148 lwi r12, r11, CC_MSR !! 708 restore_fpu: 1149 mts rmsr, r12 !! 709 and $3, TS_RESTORE_FP, $3 1150 !! 710 bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2 1151 rtsd r15, 8 !! 711 beq $3, 1f 1152 nop !! 712 #define V(n) ldt $f##n, FR(n) 1153 !! 713 ldt $f30, FR(31) # get saved fpcr 1154 #ifdef CONFIG_MB_MANAGER !! 714 V( 0); V( 1); V( 2); V( 3) 1155 .global xmb_inject_err !! 715 mt_fpcr $f30 # install saved fpcr 1156 .section .text !! 716 V( 4); V( 5); V( 6); V( 7) 1157 .align 2 !! 717 V( 8); V( 9); V(10); V(11) 1158 .ent xmb_inject_err !! 718 V(12); V(13); V(14); V(15) 1159 .type xmb_inject_err, @function !! 719 V(16); V(17); V(18); V(19) 1160 xmb_inject_err: !! 720 V(20); V(21); V(22); V(23) 1161 addik r1, r1, -PT_SIZE !! 721 V(24); V(25); V(26); V(27) 1162 SAVE_REGS !! 722 V(28); V(29); V(30) 1163 !! 723 1: stl $2, TI_STATUS($8) 1164 /* Switch to real mode */ !! 724 br restore_other 1165 VM_OFF; !! 725 #undef V 1166 set_bip; !! 726 1167 mbar 1 !! 727 1168 mbar 2 !! 728 /* 1169 bralid r15, XMB_INJECT_ERR_OFFSET !! 729 * The meat of the context switch code. 1170 nop; !! 730 */ 1171 !! 731 .align 4 1172 /* enable virtual mode */ !! 732 .globl alpha_switch_to 1173 set_vms; !! 733 .type alpha_switch_to, @function 1174 /* barrier for instructions and data !! 734 .cfi_startproc 1175 mbar 1 !! 735 alpha_switch_to: 1176 mbar 2 !! 736 DO_SWITCH_STACK 1177 /* !! 737 ldl $1, TI_STATUS($8) 1178 * Enable Interrupts, Virtual Protect !! 738 and $1, TS_RESTORE_FP, $3 1179 * initial state for all possible ent !! 739 bne $3, 1f 1180 */ !! 740 or $1, TS_RESTORE_FP | TS_SAVED_FP, $2 1181 rtbd r0, 1f !! 741 and $1, TS_SAVED_FP, $3 1182 nop; !! 742 stl $2, TI_STATUS($8) >> 743 bne $3, 1f >> 744 bsr $26, __save_fpu 1183 1: 745 1: 1184 RESTORE_REGS !! 746 call_pal PAL_swpctx 1185 addik r1, r1, PT_SIZE !! 747 lda $8, 0x3fff 1186 rtsd r15, 8; !! 748 UNDO_SWITCH_STACK 1187 nop; !! 749 bic $sp, $8, $8 1188 .end xmb_inject_err !! 750 mov $17, $0 1189 !! 751 ret 1190 .section .data !! 752 .cfi_endproc 1191 .global xmb_manager_dev !! 753 .size alpha_switch_to, .-alpha_switch_to 1192 .global xmb_manager_baseaddr !! 754 1193 .global xmb_manager_crval !! 755 /* 1194 .global xmb_manager_callback !! 756 * New processes begin life here. 1195 .global xmb_manager_reset_callback !! 757 */ 1196 .global xmb_manager_stackpointer !! 758 1197 .align 4 !! 759 .globl ret_from_fork 1198 xmb_manager_dev: !! 760 .align 4 1199 .long 0 !! 761 .ent ret_from_fork 1200 xmb_manager_baseaddr: !! 762 ret_from_fork: 1201 .long 0 !! 763 lda $26, ret_to_user 1202 xmb_manager_crval: !! 764 mov $17, $16 1203 .long 0 !! 765 jmp $31, schedule_tail 1204 xmb_manager_callback: !! 766 .end ret_from_fork 1205 .long 0 << 1206 xmb_manager_reset_callback: << 1207 .long 0 << 1208 xmb_manager_stackpointer: << 1209 .long 0 << 1210 767 1211 /* 768 /* 1212 * When the break vector gets asserted becaus !! 769 * ... and new kernel threads - here 1213 * the break signal must be blocked before ex << 1214 * break handler, Below api updates the manag << 1215 * control register and error count callback << 1216 * which will be used by the break handler to << 1217 * break and call the callback function. << 1218 */ 770 */ 1219 .global xmb_manager_register << 1220 .section .text << 1221 .align 2 << 1222 .ent xmb_manager_register << 1223 .type xmb_manager_register, @function << 1224 xmb_manager_register: << 1225 swi r5, r0, xmb_manager_baseaddr << 1226 swi r6, r0, xmb_manager_crval << 1227 swi r7, r0, xmb_manager_callback << 1228 swi r8, r0, xmb_manager_dev << 1229 swi r9, r0, xmb_manager_reset_cal << 1230 << 1231 rtsd r15, 8; << 1232 nop; << 1233 .end xmb_manager_register << 1234 #endif << 1235 << 1236 ENTRY(_reset) << 1237 VM_OFF << 1238 brai 0; /* Jump to reset vector */ << 1239 << 1240 /* These are compiled and loaded into << 1241 * copied into place in mach_early_se << 1242 .section .init.ivt, "ax" << 1243 #if CONFIG_MANUAL_RESET_VECTOR && !defined(CO << 1244 .org 0x0 << 1245 brai CONFIG_MANUAL_RESET_VECTOR << 1246 #elif defined(CONFIG_MB_MANAGER) << 1247 .org 0x0 << 1248 brai TOPHYS(_xtmr_manager_reset); << 1249 #endif << 1250 .org 0x8 << 1251 brai TOPHYS(_user_exception); /* s << 1252 .org 0x10 << 1253 brai TOPHYS(_interrupt); /* In << 1254 #ifdef CONFIG_MB_MANAGER << 1255 .org 0x18 << 1256 brai TOPHYS(_xmb_manager_break); << 1257 #else << 1258 .org 0x18 << 1259 brai TOPHYS(_debug_exception); << 1260 #endif << 1261 .org 0x20 << 1262 brai TOPHYS(_hw_exception_handler) << 1263 << 1264 #ifdef CONFIG_MB_MANAGER << 1265 /* << 1266 * For TMR Inject API which injects t << 1267 * be executed from LMB. << 1268 * TMR Inject is programmed with addr << 1269 * when program counter matches with << 1270 * be injected. 0x200 is expected to << 1271 * offset, hence used for this api. << 1272 */ << 1273 .org XMB_INJECT_ERR_OFFSET << 1274 xmb_inject_error: << 1275 nop << 1276 rtsd r15, 8 << 1277 nop << 1278 #endif << 1279 << 1280 .section .rodata,"a" << 1281 #include "syscall_table.S" << 1282 << 1283 syscall_table_size=(.-sys_call_table) << 1284 << 1285 type_SYSCALL: << 1286 .ascii "SYSCALL\0" << 1287 type_IRQ: << 1288 .ascii "IRQ\0" << 1289 type_IRQ_PREEMPT: << 1290 .ascii "IRQ (PREEMPTED)\0" << 1291 type_SYSCALL_PREEMPT: << 1292 .ascii " SYSCALL (PREEMPTED)\0" << 1293 << 1294 /* << 1295 * Trap decoding for stack unwinder << 1296 * Tuples are (start addr, end addr, << 1297 * If return address lies on [start a << 1298 * unwinder displays 'string' << 1299 */ << 1300 << 1301 .align 4 771 .align 4 1302 .global microblaze_trap_handlers !! 772 .globl ret_from_kernel_thread 1303 microblaze_trap_handlers: !! 773 .ent ret_from_kernel_thread 1304 /* Exact matches come first */ !! 774 ret_from_kernel_thread: 1305 .word ret_from_trap; .word ret_from_t !! 775 mov $17, $16 1306 .word ret_from_irq ; .word ret_from_i !! 776 jsr $26, schedule_tail 1307 /* Fuzzy matches go here */ !! 777 mov $9, $27 1308 .word ret_from_irq ; .word no_intr_re !! 778 mov $10, $16 1309 .word ret_from_trap; .word TRAP_retur !! 779 jsr $26, ($9) 1310 /* End of table */ !! 780 br $31, ret_to_user 1311 .word 0 ; .word 0 !! 781 .end ret_from_kernel_thread >> 782 >> 783 >> 784 /* >> 785 * Special system calls. Most of these are special in that they either >> 786 * have to play switch_stack games. >> 787 */ >> 788 >> 789 .macro fork_like name >> 790 .align 4 >> 791 .globl alpha_\name >> 792 .ent alpha_\name >> 793 alpha_\name: >> 794 .prologue 0 >> 795 bsr $1, do_switch_stack >> 796 // NB: if anyone adds preemption, this block will need to be protected >> 797 ldl $1, TI_STATUS($8) >> 798 and $1, TS_SAVED_FP, $3 >> 799 or $1, TS_SAVED_FP, $2 >> 800 bne $3, 1f >> 801 stl $2, TI_STATUS($8) >> 802 bsr $26, __save_fpu >> 803 1: >> 804 jsr $26, sys_\name >> 805 ldq $26, 56($sp) >> 806 lda $sp, SWITCH_STACK_SIZE($sp) >> 807 ret >> 808 .end alpha_\name >> 809 .endm >> 810 >> 811 fork_like fork >> 812 fork_like vfork >> 813 fork_like clone >> 814 fork_like clone3 >> 815 >> 816 .macro sigreturn_like name >> 817 .align 4 >> 818 .globl sys_\name >> 819 .ent sys_\name >> 820 sys_\name: >> 821 .prologue 0 >> 822 lda $9, ret_from_straced >> 823 cmpult $26, $9, $9 >> 824 lda $sp, -SWITCH_STACK_SIZE($sp) >> 825 jsr $26, do_\name >> 826 bne $9, 1f >> 827 jsr $26, syscall_trace_leave >> 828 1: br $1, undo_switch_stack >> 829 br ret_from_sys_call >> 830 .end sys_\name >> 831 .endm >> 832 >> 833 sigreturn_like sigreturn >> 834 sigreturn_like rt_sigreturn >> 835 >> 836 .align 4 >> 837 .globl alpha_syscall_zero >> 838 .ent alpha_syscall_zero >> 839 alpha_syscall_zero: >> 840 .prologue 0 >> 841 /* Special because it needs to do something opposite to >> 842 force_successful_syscall_return(). We use the saved >> 843 syscall number for that, zero meaning "not an error". >> 844 That works nicely, but for real syscall 0 we need to >> 845 make sure that this logics doesn't get confused. >> 846 Store a non-zero there - -ENOSYS we need in register >> 847 for our return value will do just fine. >> 848 */ >> 849 lda $0, -ENOSYS >> 850 unop >> 851 stq $0, 0($sp) >> 852 ret >> 853 .end alpha_syscall_zero
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.