>> 1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* 2 /* 2 * This file is subject to the terms and condi !! 3 * arch/alpha/kernel/entry.S 3 * License. See the file "COPYING" in the mai << 4 * for more details. << 5 * 4 * 6 * Copyright (C) 1994 - 2000, 2001, 2003 Ralf !! 5 * Kernel entry-points. 7 * Copyright (C) 1999, 2000 Silicon Graphics, << 8 * Copyright (C) 2001 MIPS Technologies, Inc. << 9 */ 6 */ 10 7 11 #include <asm/asm.h> !! 8 #include <asm/asm-offsets.h> 12 #include <asm/asmmacro.h> << 13 #include <asm/compiler.h> << 14 #include <asm/irqflags.h> << 15 #include <asm/regdef.h> << 16 #include <asm/mipsregs.h> << 17 #include <asm/stackframe.h> << 18 #include <asm/isadep.h> << 19 #include <asm/thread_info.h> 9 #include <asm/thread_info.h> 20 !! 10 #include <asm/pal.h> 21 #ifndef CONFIG_PREEMPTION !! 11 #include <asm/errno.h> 22 #define resume_kernel restore_all !! 12 #include <asm/unistd.h> 23 #else << 24 #define __ret_from_irq ret_from_exception << 25 #endif << 26 13 27 .text 14 .text 28 .align 5 !! 15 .set noat 29 #ifndef CONFIG_PREEMPTION !! 16 .cfi_sections .debug_frame 30 FEXPORT(ret_from_exception) << 31 local_irq_disable << 32 b __ret_from_irq << 33 #endif << 34 FEXPORT(ret_from_irq) << 35 LONG_S s0, TI_REGS($28) << 36 FEXPORT(__ret_from_irq) << 37 /* << 38 * We can be coming here from a syscall done i << 39 * e.g. a failed kernel_execve(). << 40 */ << 41 resume_userspace_check: << 42 LONG_L t0, PT_STATUS(sp) << 43 andi t0, t0, KU_USER << 44 beqz t0, resume_kernel << 45 << 46 resume_userspace: << 47 local_irq_disable # make << 48 # inte << 49 # betw << 50 LONG_L a2, TI_FLAGS($28) # curr << 51 andi t0, a2, _TIF_WORK_MASK # (ign << 52 bnez t0, work_pending << 53 j restore_all << 54 << 55 #ifdef CONFIG_PREEMPTION << 56 resume_kernel: << 57 local_irq_disable << 58 lw t0, TI_PRE_COUNT($28) << 59 bnez t0, restore_all << 60 LONG_L t0, TI_FLAGS($28) << 61 andi t1, t0, _TIF_NEED_RESCHED << 62 beqz t1, restore_all << 63 LONG_L t0, PT_STATUS(sp) << 64 andi t0, 1 << 65 beqz t0, restore_all << 66 PTR_LA ra, restore_all << 67 j preempt_schedule_irq << 68 #endif << 69 17 70 FEXPORT(ret_from_kernel_thread) !! 18 /* Stack offsets. */ 71 jal schedule_tail # a0 = !! 19 #define SP_OFF 184 72 move a0, s1 !! 20 #define SWITCH_STACK_SIZE 320 73 jal s0 !! 21 74 j syscall_exit !! 22 .macro CFI_START_OSF_FRAME func 75 !! 23 .align 4 76 FEXPORT(ret_from_fork) !! 24 .globl \func 77 jal schedule_tail # a0 = !! 25 .type \func,@function 78 !! 26 \func: 79 FEXPORT(syscall_exit) !! 27 .cfi_startproc simple 80 #ifdef CONFIG_DEBUG_RSEQ !! 28 .cfi_return_column 64 81 move a0, sp !! 29 .cfi_def_cfa $sp, 48 82 jal rseq_syscall !! 30 .cfi_rel_offset 64, 8 83 #endif !! 31 .cfi_rel_offset $gp, 16 84 local_irq_disable # make !! 32 .cfi_rel_offset $16, 24 85 # sign !! 33 .cfi_rel_offset $17, 32 86 # samp !! 34 .cfi_rel_offset $18, 40 87 LONG_L a2, TI_FLAGS($28) # curr !! 35 .endm 88 li t0, _TIF_ALLWORK_MASK !! 36 89 and t0, a2, t0 !! 37 .macro CFI_END_OSF_FRAME func 90 bnez t0, syscall_exit_work !! 38 .cfi_endproc 91 !! 39 .size \func, . - \func 92 restore_all: # rest !! 40 .endm 93 .set noat !! 41 94 RESTORE_TEMP !! 42 /* 95 RESTORE_AT !! 43 * This defines the normal kernel pt-regs layout. 96 RESTORE_STATIC !! 44 * 97 restore_partial: # restore part !! 45 * regs 9-15 preserved by C code 98 #ifdef CONFIG_TRACE_IRQFLAGS !! 46 * regs 16-18 saved by PAL-code 99 SAVE_STATIC !! 47 * regs 29-30 saved and set up by PAL-code 100 SAVE_AT !! 48 * JRP - Save regs 16-18 in a special area of the stack, so that 101 SAVE_TEMP !! 49 * the palcode-provided values are available to the signal handler. 102 LONG_L v0, PT_STATUS(sp) !! 50 */ 103 #if defined(CONFIG_CPU_R3000) !! 51 104 and v0, ST0_IEP !! 52 .macro SAVE_ALL 105 #else !! 53 subq $sp, SP_OFF, $sp 106 and v0, ST0_IE !! 54 .cfi_adjust_cfa_offset SP_OFF 107 #endif !! 55 stq $0, 0($sp) 108 beqz v0, 1f !! 56 stq $1, 8($sp) 109 jal trace_hardirqs_on !! 57 stq $2, 16($sp) 110 b 2f !! 58 stq $3, 24($sp) 111 1: jal trace_hardirqs_off !! 59 stq $4, 32($sp) 112 2: !! 60 stq $28, 144($sp) 113 RESTORE_TEMP !! 61 .cfi_rel_offset $0, 0 114 RESTORE_AT !! 62 .cfi_rel_offset $1, 8 115 RESTORE_STATIC !! 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 /* We don't really care about the FP registers for debugging. */ >> 163 .endm >> 164 >> 165 .macro UNDO_SWITCH_STACK >> 166 bsr $1, undo_switch_stack >> 167 .cfi_restore $9 >> 168 .cfi_restore $10 >> 169 .cfi_restore $11 >> 170 .cfi_restore $12 >> 171 .cfi_restore $13 >> 172 .cfi_restore $14 >> 173 .cfi_restore $15 >> 174 .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE >> 175 .endm >> 176 >> 177 /* >> 178 * Non-syscall kernel entry points. >> 179 */ >> 180 >> 181 CFI_START_OSF_FRAME entInt >> 182 SAVE_ALL >> 183 lda $8, 0x3fff >> 184 lda $26, ret_from_sys_call >> 185 bic $sp, $8, $8 >> 186 mov $sp, $19 >> 187 jsr $31, do_entInt >> 188 CFI_END_OSF_FRAME entInt >> 189 >> 190 CFI_START_OSF_FRAME entArith >> 191 SAVE_ALL >> 192 lda $8, 0x3fff >> 193 lda $26, ret_from_sys_call >> 194 bic $sp, $8, $8 >> 195 mov $sp, $18 >> 196 jsr $31, do_entArith >> 197 CFI_END_OSF_FRAME entArith >> 198 >> 199 CFI_START_OSF_FRAME entMM >> 200 SAVE_ALL >> 201 /* save $9 - $15 so the inline exception code can manipulate them. */ >> 202 subq $sp, 56, $sp >> 203 .cfi_adjust_cfa_offset 56 >> 204 stq $9, 0($sp) >> 205 stq $10, 8($sp) >> 206 stq $11, 16($sp) >> 207 stq $12, 24($sp) >> 208 stq $13, 32($sp) >> 209 stq $14, 40($sp) >> 210 stq $15, 48($sp) >> 211 .cfi_rel_offset $9, 0 >> 212 .cfi_rel_offset $10, 8 >> 213 .cfi_rel_offset $11, 16 >> 214 .cfi_rel_offset $12, 24 >> 215 .cfi_rel_offset $13, 32 >> 216 .cfi_rel_offset $14, 40 >> 217 .cfi_rel_offset $15, 48 >> 218 addq $sp, 56, $19 >> 219 /* handle the fault */ >> 220 lda $8, 0x3fff >> 221 bic $sp, $8, $8 >> 222 jsr $26, do_page_fault >> 223 /* reload the registers after the exception code played. */ >> 224 ldq $9, 0($sp) >> 225 ldq $10, 8($sp) >> 226 ldq $11, 16($sp) >> 227 ldq $12, 24($sp) >> 228 ldq $13, 32($sp) >> 229 ldq $14, 40($sp) >> 230 ldq $15, 48($sp) >> 231 addq $sp, 56, $sp >> 232 .cfi_restore $9 >> 233 .cfi_restore $10 >> 234 .cfi_restore $11 >> 235 .cfi_restore $12 >> 236 .cfi_restore $13 >> 237 .cfi_restore $14 >> 238 .cfi_restore $15 >> 239 .cfi_adjust_cfa_offset -56 >> 240 /* finish up the syscall as normal. */ >> 241 br ret_from_sys_call >> 242 CFI_END_OSF_FRAME entMM >> 243 >> 244 CFI_START_OSF_FRAME entIF >> 245 SAVE_ALL >> 246 lda $8, 0x3fff >> 247 lda $26, ret_from_sys_call >> 248 bic $sp, $8, $8 >> 249 mov $sp, $17 >> 250 jsr $31, do_entIF >> 251 CFI_END_OSF_FRAME entIF >> 252 >> 253 CFI_START_OSF_FRAME entUna >> 254 lda $sp, -256($sp) >> 255 .cfi_adjust_cfa_offset 256 >> 256 stq $0, 0($sp) >> 257 .cfi_rel_offset $0, 0 >> 258 .cfi_remember_state >> 259 ldq $0, 256($sp) /* get PS */ >> 260 stq $1, 8($sp) >> 261 stq $2, 16($sp) >> 262 stq $3, 24($sp) >> 263 and $0, 8, $0 /* user mode? */ >> 264 stq $4, 32($sp) >> 265 bne $0, entUnaUser /* yup -> do user-level unaligned fault */ >> 266 stq $5, 40($sp) >> 267 stq $6, 48($sp) >> 268 stq $7, 56($sp) >> 269 stq $8, 64($sp) >> 270 stq $9, 72($sp) >> 271 stq $10, 80($sp) >> 272 stq $11, 88($sp) >> 273 stq $12, 96($sp) >> 274 stq $13, 104($sp) >> 275 stq $14, 112($sp) >> 276 stq $15, 120($sp) >> 277 /* 16-18 PAL-saved */ >> 278 stq $19, 152($sp) >> 279 stq $20, 160($sp) >> 280 stq $21, 168($sp) >> 281 stq $22, 176($sp) >> 282 stq $23, 184($sp) >> 283 stq $24, 192($sp) >> 284 stq $25, 200($sp) >> 285 stq $26, 208($sp) >> 286 stq $27, 216($sp) >> 287 stq $28, 224($sp) >> 288 mov $sp, $19 >> 289 stq $gp, 232($sp) >> 290 .cfi_rel_offset $1, 1*8 >> 291 .cfi_rel_offset $2, 2*8 >> 292 .cfi_rel_offset $3, 3*8 >> 293 .cfi_rel_offset $4, 4*8 >> 294 .cfi_rel_offset $5, 5*8 >> 295 .cfi_rel_offset $6, 6*8 >> 296 .cfi_rel_offset $7, 7*8 >> 297 .cfi_rel_offset $8, 8*8 >> 298 .cfi_rel_offset $9, 9*8 >> 299 .cfi_rel_offset $10, 10*8 >> 300 .cfi_rel_offset $11, 11*8 >> 301 .cfi_rel_offset $12, 12*8 >> 302 .cfi_rel_offset $13, 13*8 >> 303 .cfi_rel_offset $14, 14*8 >> 304 .cfi_rel_offset $15, 15*8 >> 305 .cfi_rel_offset $19, 19*8 >> 306 .cfi_rel_offset $20, 20*8 >> 307 .cfi_rel_offset $21, 21*8 >> 308 .cfi_rel_offset $22, 22*8 >> 309 .cfi_rel_offset $23, 23*8 >> 310 .cfi_rel_offset $24, 24*8 >> 311 .cfi_rel_offset $25, 25*8 >> 312 .cfi_rel_offset $26, 26*8 >> 313 .cfi_rel_offset $27, 27*8 >> 314 .cfi_rel_offset $28, 28*8 >> 315 .cfi_rel_offset $29, 29*8 >> 316 lda $8, 0x3fff >> 317 stq $31, 248($sp) >> 318 bic $sp, $8, $8 >> 319 jsr $26, do_entUna >> 320 ldq $0, 0($sp) >> 321 ldq $1, 8($sp) >> 322 ldq $2, 16($sp) >> 323 ldq $3, 24($sp) >> 324 ldq $4, 32($sp) >> 325 ldq $5, 40($sp) >> 326 ldq $6, 48($sp) >> 327 ldq $7, 56($sp) >> 328 ldq $8, 64($sp) >> 329 ldq $9, 72($sp) >> 330 ldq $10, 80($sp) >> 331 ldq $11, 88($sp) >> 332 ldq $12, 96($sp) >> 333 ldq $13, 104($sp) >> 334 ldq $14, 112($sp) >> 335 ldq $15, 120($sp) >> 336 /* 16-18 PAL-saved */ >> 337 ldq $19, 152($sp) >> 338 ldq $20, 160($sp) >> 339 ldq $21, 168($sp) >> 340 ldq $22, 176($sp) >> 341 ldq $23, 184($sp) >> 342 ldq $24, 192($sp) >> 343 ldq $25, 200($sp) >> 344 ldq $26, 208($sp) >> 345 ldq $27, 216($sp) >> 346 ldq $28, 224($sp) >> 347 ldq $gp, 232($sp) >> 348 lda $sp, 256($sp) >> 349 .cfi_restore $1 >> 350 .cfi_restore $2 >> 351 .cfi_restore $3 >> 352 .cfi_restore $4 >> 353 .cfi_restore $5 >> 354 .cfi_restore $6 >> 355 .cfi_restore $7 >> 356 .cfi_restore $8 >> 357 .cfi_restore $9 >> 358 .cfi_restore $10 >> 359 .cfi_restore $11 >> 360 .cfi_restore $12 >> 361 .cfi_restore $13 >> 362 .cfi_restore $14 >> 363 .cfi_restore $15 >> 364 .cfi_restore $19 >> 365 .cfi_restore $20 >> 366 .cfi_restore $21 >> 367 .cfi_restore $22 >> 368 .cfi_restore $23 >> 369 .cfi_restore $24 >> 370 .cfi_restore $25 >> 371 .cfi_restore $26 >> 372 .cfi_restore $27 >> 373 .cfi_restore $28 >> 374 .cfi_restore $29 >> 375 .cfi_adjust_cfa_offset -256 >> 376 call_pal PAL_rti >> 377 >> 378 .align 4 >> 379 entUnaUser: >> 380 .cfi_restore_state >> 381 ldq $0, 0($sp) /* restore original $0 */ >> 382 lda $sp, 256($sp) /* pop entUna's stack frame */ >> 383 .cfi_restore $0 >> 384 .cfi_adjust_cfa_offset -256 >> 385 SAVE_ALL /* setup normal kernel stack */ >> 386 lda $sp, -56($sp) >> 387 .cfi_adjust_cfa_offset 56 >> 388 stq $9, 0($sp) >> 389 stq $10, 8($sp) >> 390 stq $11, 16($sp) >> 391 stq $12, 24($sp) >> 392 stq $13, 32($sp) >> 393 stq $14, 40($sp) >> 394 stq $15, 48($sp) >> 395 .cfi_rel_offset $9, 0 >> 396 .cfi_rel_offset $10, 8 >> 397 .cfi_rel_offset $11, 16 >> 398 .cfi_rel_offset $12, 24 >> 399 .cfi_rel_offset $13, 32 >> 400 .cfi_rel_offset $14, 40 >> 401 .cfi_rel_offset $15, 48 >> 402 lda $8, 0x3fff >> 403 addq $sp, 56, $19 >> 404 bic $sp, $8, $8 >> 405 jsr $26, do_entUnaUser >> 406 ldq $9, 0($sp) >> 407 ldq $10, 8($sp) >> 408 ldq $11, 16($sp) >> 409 ldq $12, 24($sp) >> 410 ldq $13, 32($sp) >> 411 ldq $14, 40($sp) >> 412 ldq $15, 48($sp) >> 413 lda $sp, 56($sp) >> 414 .cfi_restore $9 >> 415 .cfi_restore $10 >> 416 .cfi_restore $11 >> 417 .cfi_restore $12 >> 418 .cfi_restore $13 >> 419 .cfi_restore $14 >> 420 .cfi_restore $15 >> 421 .cfi_adjust_cfa_offset -56 >> 422 br ret_from_sys_call >> 423 CFI_END_OSF_FRAME entUna >> 424 >> 425 CFI_START_OSF_FRAME entDbg >> 426 SAVE_ALL >> 427 lda $8, 0x3fff >> 428 lda $26, ret_from_sys_call >> 429 bic $sp, $8, $8 >> 430 mov $sp, $16 >> 431 jsr $31, do_entDbg >> 432 CFI_END_OSF_FRAME entDbg >> 433 >> 434 /* >> 435 * The system call entry point is special. Most importantly, it looks >> 436 * like a function call to userspace as far as clobbered registers. We >> 437 * do preserve the argument registers (for syscall restarts) and $26 >> 438 * (for leaf syscall functions). >> 439 * >> 440 * So much for theory. We don't take advantage of this yet. >> 441 * >> 442 * Note that a0-a2 are not saved by PALcode as with the other entry points. >> 443 */ >> 444 >> 445 .align 4 >> 446 .globl entSys >> 447 .type entSys, @function >> 448 .cfi_startproc simple >> 449 .cfi_return_column 64 >> 450 .cfi_def_cfa $sp, 48 >> 451 .cfi_rel_offset 64, 8 >> 452 .cfi_rel_offset $gp, 16 >> 453 entSys: >> 454 SAVE_ALL >> 455 lda $8, 0x3fff >> 456 bic $sp, $8, $8 >> 457 lda $4, NR_SYSCALLS($31) >> 458 stq $16, SP_OFF+24($sp) >> 459 lda $5, sys_call_table >> 460 lda $27, sys_ni_syscall >> 461 cmpult $0, $4, $4 >> 462 ldl $3, TI_FLAGS($8) >> 463 stq $17, SP_OFF+32($sp) >> 464 s8addq $0, $5, $5 >> 465 stq $18, SP_OFF+40($sp) >> 466 .cfi_rel_offset $16, SP_OFF+24 >> 467 .cfi_rel_offset $17, SP_OFF+32 >> 468 .cfi_rel_offset $18, SP_OFF+40 >> 469 #ifdef CONFIG_AUDITSYSCALL >> 470 lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT >> 471 and $3, $6, $3 116 #endif 472 #endif 117 RESTORE_SOME !! 473 bne $3, strace 118 RESTORE_SP_AND_RET !! 474 beq $4, 1f 119 .set at !! 475 ldq $27, 0($5) >> 476 1: jsr $26, ($27), sys_ni_syscall >> 477 ldgp $gp, 0($26) >> 478 blt $0, $syscall_error /* the call failed */ >> 479 stq $0, 0($sp) >> 480 stq $31, 72($sp) /* a3=0 => no error */ >> 481 >> 482 .align 4 >> 483 .globl ret_from_sys_call >> 484 ret_from_sys_call: >> 485 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ >> 486 ldq $0, SP_OFF($sp) >> 487 and $0, 8, $0 >> 488 beq $0, ret_to_kernel >> 489 ret_to_user: >> 490 /* Make sure need_resched and sigpending don't change between >> 491 sampling and the rti. */ >> 492 lda $16, 7 >> 493 call_pal PAL_swpipl >> 494 ldl $17, TI_FLAGS($8) >> 495 and $17, _TIF_WORK_MASK, $2 >> 496 bne $2, work_pending >> 497 restore_all: >> 498 .cfi_remember_state >> 499 RESTORE_ALL >> 500 call_pal PAL_rti >> 501 >> 502 ret_to_kernel: >> 503 .cfi_restore_state >> 504 lda $16, 7 >> 505 call_pal PAL_swpipl >> 506 br restore_all >> 507 >> 508 .align 3 >> 509 $syscall_error: >> 510 /* >> 511 * Some system calls (e.g., ptrace) can return arbitrary >> 512 * values which might normally be mistaken as error numbers. >> 513 * Those functions must zero $0 (v0) directly in the stack >> 514 * frame to indicate that a negative return value wasn't an >> 515 * error number.. >> 516 */ >> 517 ldq $18, 0($sp) /* old syscall nr (zero if success) */ >> 518 beq $18, $ret_success >> 519 >> 520 ldq $19, 72($sp) /* .. and this a3 */ >> 521 subq $31, $0, $0 /* with error in v0 */ >> 522 addq $31, 1, $1 /* set a3 for errno return */ >> 523 stq $0, 0($sp) >> 524 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ >> 525 stq $1, 72($sp) /* a3 for return */ >> 526 br ret_from_sys_call >> 527 >> 528 $ret_success: >> 529 stq $0, 0($sp) >> 530 stq $31, 72($sp) /* a3=0 => no error */ >> 531 br ret_from_sys_call 120 532 >> 533 /* >> 534 * Do all cleanup when returning from all interrupts and system calls. >> 535 * >> 536 * Arguments: >> 537 * $8: current. >> 538 * $17: TI_FLAGS. >> 539 * $18: The old syscall number, or zero if this is not a return >> 540 * from a syscall that errored and is possibly restartable. >> 541 * $19: The old a3 value >> 542 */ >> 543 >> 544 .align 4 >> 545 .type work_pending, @function 121 work_pending: 546 work_pending: 122 andi t0, a2, _TIF_NEED_RESCHED # a2 !! 547 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2 123 beqz t0, work_notifysig !! 548 bne $2, $work_notifysig 124 work_resched: << 125 TRACE_IRQS_OFF << 126 jal schedule << 127 << 128 local_irq_disable # make << 129 # sign << 130 # samp << 131 LONG_L a2, TI_FLAGS($28) << 132 andi t0, a2, _TIF_WORK_MASK # is t << 133 # othe << 134 beqz t0, restore_all << 135 andi t0, a2, _TIF_NEED_RESCHED << 136 bnez t0, work_resched << 137 << 138 work_notifysig: # deal << 139 # noti << 140 move a0, sp << 141 li a1, 0 << 142 jal do_notify_resume # a2 a << 143 j resume_userspace_check << 144 << 145 FEXPORT(syscall_exit_partial) << 146 #ifdef CONFIG_DEBUG_RSEQ << 147 move a0, sp << 148 jal rseq_syscall << 149 #endif << 150 local_irq_disable # make << 151 # chan << 152 LONG_L a2, TI_FLAGS($28) # curr << 153 li t0, _TIF_ALLWORK_MASK << 154 and t0, a2 << 155 beqz t0, restore_partial << 156 SAVE_STATIC << 157 syscall_exit_work: << 158 LONG_L t0, PT_STATUS(sp) << 159 andi t0, t0, KU_USER << 160 beqz t0, resume_kernel << 161 li t0, _TIF_WORK_SYSCALL_EXIT << 162 and t0, a2 # a2 i << 163 beqz t0, work_pending # trac << 164 local_irq_enable # coul << 165 # call << 166 TRACE_IRQS_ON << 167 move a0, sp << 168 jal syscall_trace_leave << 169 b resume_userspace << 170 549 171 #if defined(CONFIG_CPU_MIPSR2) || defined(CONF !! 550 $work_resched: 172 defined(CONFIG_CPU_MIPSR6) || defined(CONF !! 551 /* >> 552 * We can get here only if we returned from syscall without SIGPENDING >> 553 * or got through work_notifysig already. Either case means no syscall >> 554 * restarts for us, so let $18 and $19 burn. >> 555 */ >> 556 jsr $26, schedule >> 557 mov 0, $18 >> 558 br ret_to_user >> 559 >> 560 $work_notifysig: >> 561 mov $sp, $16 >> 562 DO_SWITCH_STACK >> 563 jsr $26, do_work_pending >> 564 UNDO_SWITCH_STACK >> 565 br restore_all 173 566 174 /* 567 /* 175 * MIPS32R2 Instruction Hazard Barrier - must !! 568 * PTRACE syscall handler 176 * !! 569 */ 177 * For C code use the inline version named ins !! 570 >> 571 .align 4 >> 572 .type strace, @function >> 573 strace: >> 574 /* set up signal stack, call syscall_trace */ >> 575 DO_SWITCH_STACK >> 576 jsr $26, syscall_trace_enter /* returns the syscall number */ >> 577 UNDO_SWITCH_STACK >> 578 >> 579 /* get the arguments back.. */ >> 580 ldq $16, SP_OFF+24($sp) >> 581 ldq $17, SP_OFF+32($sp) >> 582 ldq $18, SP_OFF+40($sp) >> 583 ldq $19, 72($sp) >> 584 ldq $20, 80($sp) >> 585 ldq $21, 88($sp) >> 586 >> 587 /* get the system call pointer.. */ >> 588 lda $1, NR_SYSCALLS($31) >> 589 lda $2, sys_call_table >> 590 lda $27, sys_ni_syscall >> 591 cmpult $0, $1, $1 >> 592 s8addq $0, $2, $2 >> 593 beq $1, 1f >> 594 ldq $27, 0($2) >> 595 1: jsr $26, ($27), sys_gettimeofday >> 596 ret_from_straced: >> 597 ldgp $gp, 0($26) >> 598 >> 599 /* check return.. */ >> 600 blt $0, $strace_error /* the call failed */ >> 601 stq $31, 72($sp) /* a3=0 => no error */ >> 602 $strace_success: >> 603 stq $0, 0($sp) /* save return value */ >> 604 >> 605 DO_SWITCH_STACK >> 606 jsr $26, syscall_trace_leave >> 607 UNDO_SWITCH_STACK >> 608 br $31, ret_from_sys_call >> 609 >> 610 .align 3 >> 611 $strace_error: >> 612 ldq $18, 0($sp) /* old syscall nr (zero if success) */ >> 613 beq $18, $strace_success >> 614 ldq $19, 72($sp) /* .. and this a3 */ >> 615 >> 616 subq $31, $0, $0 /* with error in v0 */ >> 617 addq $31, 1, $1 /* set a3 for errno return */ >> 618 stq $0, 0($sp) >> 619 stq $1, 72($sp) /* a3 for return */ >> 620 >> 621 DO_SWITCH_STACK >> 622 mov $18, $9 /* save old syscall number */ >> 623 mov $19, $10 /* save old a3 */ >> 624 jsr $26, syscall_trace_leave >> 625 mov $9, $18 >> 626 mov $10, $19 >> 627 UNDO_SWITCH_STACK >> 628 >> 629 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ >> 630 br ret_from_sys_call >> 631 CFI_END_OSF_FRAME entSys >> 632 >> 633 /* >> 634 * Save and restore the switch stack -- aka the balance of the user context. >> 635 */ >> 636 >> 637 .align 4 >> 638 .type do_switch_stack, @function >> 639 .cfi_startproc simple >> 640 .cfi_return_column 64 >> 641 .cfi_def_cfa $sp, 0 >> 642 .cfi_register 64, $1 >> 643 do_switch_stack: >> 644 lda $sp, -SWITCH_STACK_SIZE($sp) >> 645 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE >> 646 stq $9, 0($sp) >> 647 stq $10, 8($sp) >> 648 stq $11, 16($sp) >> 649 stq $12, 24($sp) >> 650 stq $13, 32($sp) >> 651 stq $14, 40($sp) >> 652 stq $15, 48($sp) >> 653 stq $26, 56($sp) >> 654 stt $f0, 64($sp) >> 655 stt $f1, 72($sp) >> 656 stt $f2, 80($sp) >> 657 stt $f3, 88($sp) >> 658 stt $f4, 96($sp) >> 659 stt $f5, 104($sp) >> 660 stt $f6, 112($sp) >> 661 stt $f7, 120($sp) >> 662 stt $f8, 128($sp) >> 663 stt $f9, 136($sp) >> 664 stt $f10, 144($sp) >> 665 stt $f11, 152($sp) >> 666 stt $f12, 160($sp) >> 667 stt $f13, 168($sp) >> 668 stt $f14, 176($sp) >> 669 stt $f15, 184($sp) >> 670 stt $f16, 192($sp) >> 671 stt $f17, 200($sp) >> 672 stt $f18, 208($sp) >> 673 stt $f19, 216($sp) >> 674 stt $f20, 224($sp) >> 675 stt $f21, 232($sp) >> 676 stt $f22, 240($sp) >> 677 stt $f23, 248($sp) >> 678 stt $f24, 256($sp) >> 679 stt $f25, 264($sp) >> 680 stt $f26, 272($sp) >> 681 stt $f27, 280($sp) >> 682 mf_fpcr $f0 # get fpcr >> 683 stt $f28, 288($sp) >> 684 stt $f29, 296($sp) >> 685 stt $f30, 304($sp) >> 686 stt $f0, 312($sp) # save fpcr in slot of $f31 >> 687 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state. >> 688 ret $31, ($1), 1 >> 689 .cfi_endproc >> 690 .size do_switch_stack, .-do_switch_stack >> 691 >> 692 .align 4 >> 693 .type undo_switch_stack, @function >> 694 .cfi_startproc simple >> 695 .cfi_def_cfa $sp, 0 >> 696 .cfi_register 64, $1 >> 697 undo_switch_stack: >> 698 ldq $9, 0($sp) >> 699 ldq $10, 8($sp) >> 700 ldq $11, 16($sp) >> 701 ldq $12, 24($sp) >> 702 ldq $13, 32($sp) >> 703 ldq $14, 40($sp) >> 704 ldq $15, 48($sp) >> 705 ldq $26, 56($sp) >> 706 ldt $f30, 312($sp) # get saved fpcr >> 707 ldt $f0, 64($sp) >> 708 ldt $f1, 72($sp) >> 709 ldt $f2, 80($sp) >> 710 ldt $f3, 88($sp) >> 711 mt_fpcr $f30 # install saved fpcr >> 712 ldt $f4, 96($sp) >> 713 ldt $f5, 104($sp) >> 714 ldt $f6, 112($sp) >> 715 ldt $f7, 120($sp) >> 716 ldt $f8, 128($sp) >> 717 ldt $f9, 136($sp) >> 718 ldt $f10, 144($sp) >> 719 ldt $f11, 152($sp) >> 720 ldt $f12, 160($sp) >> 721 ldt $f13, 168($sp) >> 722 ldt $f14, 176($sp) >> 723 ldt $f15, 184($sp) >> 724 ldt $f16, 192($sp) >> 725 ldt $f17, 200($sp) >> 726 ldt $f18, 208($sp) >> 727 ldt $f19, 216($sp) >> 728 ldt $f20, 224($sp) >> 729 ldt $f21, 232($sp) >> 730 ldt $f22, 240($sp) >> 731 ldt $f23, 248($sp) >> 732 ldt $f24, 256($sp) >> 733 ldt $f25, 264($sp) >> 734 ldt $f26, 272($sp) >> 735 ldt $f27, 280($sp) >> 736 ldt $f28, 288($sp) >> 737 ldt $f29, 296($sp) >> 738 ldt $f30, 304($sp) >> 739 lda $sp, SWITCH_STACK_SIZE($sp) >> 740 ret $31, ($1), 1 >> 741 .cfi_endproc >> 742 .size undo_switch_stack, .-undo_switch_stack >> 743 >> 744 /* >> 745 * The meat of the context switch code. >> 746 */ >> 747 >> 748 .align 4 >> 749 .globl alpha_switch_to >> 750 .type alpha_switch_to, @function >> 751 .cfi_startproc >> 752 alpha_switch_to: >> 753 DO_SWITCH_STACK >> 754 call_pal PAL_swpctx >> 755 lda $8, 0x3fff >> 756 UNDO_SWITCH_STACK >> 757 bic $sp, $8, $8 >> 758 mov $17, $0 >> 759 ret >> 760 .cfi_endproc >> 761 .size alpha_switch_to, .-alpha_switch_to >> 762 >> 763 /* >> 764 * New processes begin life here. >> 765 */ >> 766 >> 767 .globl ret_from_fork >> 768 .align 4 >> 769 .ent ret_from_fork >> 770 ret_from_fork: >> 771 lda $26, ret_from_sys_call >> 772 mov $17, $16 >> 773 jmp $31, schedule_tail >> 774 .end ret_from_fork >> 775 >> 776 /* >> 777 * ... and new kernel threads - here >> 778 */ >> 779 .align 4 >> 780 .globl ret_from_kernel_thread >> 781 .ent ret_from_kernel_thread >> 782 ret_from_kernel_thread: >> 783 mov $17, $16 >> 784 jsr $26, schedule_tail >> 785 mov $9, $27 >> 786 mov $10, $16 >> 787 jsr $26, ($9) >> 788 br $31, ret_to_user >> 789 .end ret_from_kernel_thread >> 790 >> 791 >> 792 /* >> 793 * Special system calls. Most of these are special in that they either >> 794 * have to play switch_stack games. 178 */ 795 */ 179 LEAF(mips_ihb) << 180 .set MIPS_ISA_LEVEL_RAW << 181 jr.hb ra << 182 nop << 183 END(mips_ihb) << 184 796 185 #endif /* CONFIG_CPU_MIPSR2 - CONFIG_CPU_MIPSR !! 797 .macro fork_like name >> 798 .align 4 >> 799 .globl alpha_\name >> 800 .ent alpha_\name >> 801 alpha_\name: >> 802 .prologue 0 >> 803 bsr $1, do_switch_stack >> 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 >> 815 .macro sigreturn_like name >> 816 .align 4 >> 817 .globl sys_\name >> 818 .ent sys_\name >> 819 sys_\name: >> 820 .prologue 0 >> 821 lda $9, ret_from_straced >> 822 cmpult $26, $9, $9 >> 823 lda $sp, -SWITCH_STACK_SIZE($sp) >> 824 jsr $26, do_\name >> 825 bne $9, 1f >> 826 jsr $26, syscall_trace_leave >> 827 1: br $1, undo_switch_stack >> 828 br ret_from_sys_call >> 829 .end sys_\name >> 830 .endm >> 831 >> 832 sigreturn_like sigreturn >> 833 sigreturn_like rt_sigreturn >> 834 >> 835 .align 4 >> 836 .globl alpha_syscall_zero >> 837 .ent alpha_syscall_zero >> 838 alpha_syscall_zero: >> 839 .prologue 0 >> 840 /* Special because it needs to do something opposite to >> 841 force_successful_syscall_return(). We use the saved >> 842 syscall number for that, zero meaning "not an error". >> 843 That works nicely, but for real syscall 0 we need to >> 844 make sure that this logics doesn't get confused. >> 845 Store a non-zero there - -ENOSYS we need in register >> 846 for our return value will do just fine. >> 847 */ >> 848 lda $0, -ENOSYS >> 849 unop >> 850 stq $0, 0($sp) >> 851 ret >> 852 .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.