1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * arch/alpha/kernel/entry.S 4 * 5 * Kernel entry-points. 6 */ 7 8#include <asm/asm-offsets.h> 9#include <asm/thread_info.h> 10#include <asm/pal.h> 11#include <asm/errno.h> 12#include <asm/unistd.h> 13#include <linux/errno.h> 14 15 .text 16 .set noat 17 .cfi_sections .debug_frame 18 19.macro CFI_START_OSF_FRAME func 20 .align 4 21 .globl \func 22 .type \func,@function 23\func: 24 .cfi_startproc simple 25 .cfi_return_column 64 26 .cfi_def_cfa $sp, 48 27 .cfi_rel_offset 64, 8 28 .cfi_rel_offset $gp, 16 29 .cfi_rel_offset $16, 24 30 .cfi_rel_offset $17, 32 31 .cfi_rel_offset $18, 40 32.endm 33 34.macro CFI_END_OSF_FRAME func 35 .cfi_endproc 36 .size \func, . - \func 37.endm 38 39/* 40 * SYSCALL_SKIP_RETURN_RESTART_GATE 41 * 42 * Used when syscall dispatch is skipped (seccomp/ptrace injected nr=-1). 43 * - Ensure we never return r0==-1 with a3==0 (success); convert to ENOSYS. 44 * - Gate whether syscall restart is allowed by preserving restart context 45 * only for ERESTART* returns. Result: 46 * $26 = 0 => restart allowed 47 * $26 = 1 => restart NOT allowed 48 * $18 = preserved syscall nr (regs->r2) if restart allowed, else 0 49 */ 50.macro SYSCALL_SKIP_RETURN_RESTART_GATE 51 /* Fix up invalid "-1 success" return state. */ 52 ldq $19, 72($sp) /* a3 */ 53 bne $19, 1f /* already error => skip fixup */ 54 55 ldq $20, 0($sp) /* r0 */ 56 lda $21, -1($31) 57 cmpeq $20, $21, $22 58 beq $22, 1f /* r0 != -1 => skip fixup */ 59 60 61 lda $20, ENOSYS($31) 62 stq $20, 0($sp) /* r0 = ENOSYS */ 63 lda $19, 1($31) 64 stq $19, 72($sp) /* a3 = 1 */ 651: 66 /* Restart gating: success is never restartable here. */ 67 ldq $19, 72($sp) /* a3 */ 68 beq $19, 3f /* success => not restartable */ 69 70 ldq $20, 0($sp) /* r0 (positive errno if a3==1) */ 71 lda $21, ERESTARTSYS($31) 72 cmpeq $20, $21, $22 73 bne $22, 2f 74 lda $21, ERESTARTNOINTR($31) 75 cmpeq $20, $21, $22 76 bne $22, 2f 77 lda $21, ERESTARTNOHAND($31) 78 cmpeq $20, $21, $22 79 bne $22, 2f 80 lda $21, ERESTART_RESTARTBLOCK($31) 81 cmpeq $20, $21, $22 82 bne $22, 2f 83 843: /* Not a restart code (or success) => restart NOT allowed. */ 85 addq $31, 1, $26 /* $26=1 => restart NOT allowed */ 86 mov 0, $18 87 br 4f 88 892: /* Restart allowed. */ 90 ldq $18, 16($sp) /* preserved syscall nr (regs->r2) */ 91 mov $31, $26 /* $26=0 => restart allowed */ 92 br 4f 934: 94.endm 95 96.macro LOCKDEP_HARDIRQS_ON_RESTORE 97#ifdef CONFIG_PROVE_LOCKING 98 /* a0 = saved PS */ 99 ldq $16, SP_OFF($sp) 100 101 /* a1 = callsite IP for lockdep */ 102 lda $17, 1f 103 104 jsr $26, lockdep_on_restore 105 ldgp $gp, 0($26) 1061: 107#endif 108.endm 109 110/* 111 * This defines the normal kernel pt-regs layout. 112 * 113 * regs 9-15 preserved by C code 114 * regs 16-18 saved by PAL-code 115 * regs 29-30 saved and set up by PAL-code 116 * JRP - Save regs 16-18 in a special area of the stack, so that 117 * the palcode-provided values are available to the signal handler. 118 */ 119 120.macro SAVE_ALL 121 subq $sp, SP_OFF, $sp 122 .cfi_adjust_cfa_offset SP_OFF 123 stq $0, 0($sp) 124 stq $1, 8($sp) 125 stq $2, 16($sp) 126 stq $3, 24($sp) 127 stq $4, 32($sp) 128 stq $28, 144($sp) 129 .cfi_rel_offset $0, 0 130 .cfi_rel_offset $1, 8 131 .cfi_rel_offset $2, 16 132 .cfi_rel_offset $3, 24 133 .cfi_rel_offset $4, 32 134 .cfi_rel_offset $28, 144 135 lda $2, alpha_mv 136 stq $5, 40($sp) 137 stq $6, 48($sp) 138 stq $7, 56($sp) 139 stq $8, 64($sp) 140 stq $19, 72($sp) 141 stq $20, 80($sp) 142 stq $21, 88($sp) 143 ldq $2, HAE_CACHE($2) 144 stq $22, 96($sp) 145 stq $23, 104($sp) 146 stq $24, 112($sp) 147 stq $25, 120($sp) 148 stq $26, 128($sp) 149 stq $27, 136($sp) 150 stq $2, 152($sp) 151 stq $16, 160($sp) 152 stq $17, 168($sp) 153 stq $18, 176($sp) 154 .cfi_rel_offset $5, 40 155 .cfi_rel_offset $6, 48 156 .cfi_rel_offset $7, 56 157 .cfi_rel_offset $8, 64 158 .cfi_rel_offset $19, 72 159 .cfi_rel_offset $20, 80 160 .cfi_rel_offset $21, 88 161 .cfi_rel_offset $22, 96 162 .cfi_rel_offset $23, 104 163 .cfi_rel_offset $24, 112 164 .cfi_rel_offset $25, 120 165 .cfi_rel_offset $26, 128 166 .cfi_rel_offset $27, 136 167.endm 168 169.macro RESTORE_ALL 170 lda $19, alpha_mv 171 ldq $0, 0($sp) 172 ldq $1, 8($sp) 173 ldq $2, 16($sp) 174 ldq $3, 24($sp) 175 ldq $21, 152($sp) 176 ldq $20, HAE_CACHE($19) 177 ldq $4, 32($sp) 178 ldq $5, 40($sp) 179 ldq $6, 48($sp) 180 ldq $7, 56($sp) 181 subq $20, $21, $20 182 ldq $8, 64($sp) 183 beq $20, 99f 184 ldq $20, HAE_REG($19) 185 stq $21, HAE_CACHE($19) 186 stq $21, 0($20) 18799: ldq $19, 72($sp) 188 ldq $20, 80($sp) 189 ldq $21, 88($sp) 190 ldq $22, 96($sp) 191 ldq $23, 104($sp) 192 ldq $24, 112($sp) 193 ldq $25, 120($sp) 194 ldq $26, 128($sp) 195 ldq $27, 136($sp) 196 ldq $28, 144($sp) 197 addq $sp, SP_OFF, $sp 198 .cfi_restore $0 199 .cfi_restore $1 200 .cfi_restore $2 201 .cfi_restore $3 202 .cfi_restore $4 203 .cfi_restore $5 204 .cfi_restore $6 205 .cfi_restore $7 206 .cfi_restore $8 207 .cfi_restore $19 208 .cfi_restore $20 209 .cfi_restore $21 210 .cfi_restore $22 211 .cfi_restore $23 212 .cfi_restore $24 213 .cfi_restore $25 214 .cfi_restore $26 215 .cfi_restore $27 216 .cfi_restore $28 217 .cfi_adjust_cfa_offset -SP_OFF 218.endm 219 220.macro DO_SWITCH_STACK 221 bsr $1, do_switch_stack 222 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE 223 .cfi_rel_offset $9, 0 224 .cfi_rel_offset $10, 8 225 .cfi_rel_offset $11, 16 226 .cfi_rel_offset $12, 24 227 .cfi_rel_offset $13, 32 228 .cfi_rel_offset $14, 40 229 .cfi_rel_offset $15, 48 230.endm 231 232.macro UNDO_SWITCH_STACK 233 bsr $1, undo_switch_stack 234 .cfi_restore $9 235 .cfi_restore $10 236 .cfi_restore $11 237 .cfi_restore $12 238 .cfi_restore $13 239 .cfi_restore $14 240 .cfi_restore $15 241 .cfi_adjust_cfa_offset -SWITCH_STACK_SIZE 242.endm 243 244/* 245 * Non-syscall kernel entry points. 246 */ 247 248CFI_START_OSF_FRAME entInt 249 SAVE_ALL 250 lda $8, 0x3fff 251 lda $26, ret_from_sys_call 252 bic $sp, $8, $8 253 mov $sp, $19 254 jsr $31, do_entInt 255CFI_END_OSF_FRAME entInt 256 257CFI_START_OSF_FRAME entArith 258 SAVE_ALL 259 lda $8, 0x3fff 260 lda $26, ret_from_sys_call 261 bic $sp, $8, $8 262 mov $sp, $18 263 jsr $31, do_entArith 264CFI_END_OSF_FRAME entArith 265 266CFI_START_OSF_FRAME entMM 267 SAVE_ALL 268/* save $9 - $15 so the inline exception code can manipulate them. */ 269 subq $sp, 64, $sp 270 .cfi_adjust_cfa_offset 64 271 stq $9, 0($sp) 272 stq $10, 8($sp) 273 stq $11, 16($sp) 274 stq $12, 24($sp) 275 stq $13, 32($sp) 276 stq $14, 40($sp) 277 stq $15, 48($sp) 278 .cfi_rel_offset $9, 0 279 .cfi_rel_offset $10, 8 280 .cfi_rel_offset $11, 16 281 .cfi_rel_offset $12, 24 282 .cfi_rel_offset $13, 32 283 .cfi_rel_offset $14, 40 284 .cfi_rel_offset $15, 48 285 addq $sp, 64, $19 286/* handle the fault */ 287 lda $8, 0x3fff 288 bic $sp, $8, $8 289 jsr $26, do_page_fault 290/* reload the registers after the exception code played. */ 291 ldq $9, 0($sp) 292 ldq $10, 8($sp) 293 ldq $11, 16($sp) 294 ldq $12, 24($sp) 295 ldq $13, 32($sp) 296 ldq $14, 40($sp) 297 ldq $15, 48($sp) 298 addq $sp, 64, $sp 299 .cfi_restore $9 300 .cfi_restore $10 301 .cfi_restore $11 302 .cfi_restore $12 303 .cfi_restore $13 304 .cfi_restore $14 305 .cfi_restore $15 306 .cfi_adjust_cfa_offset -64 307/* finish up the syscall as normal. */ 308 br ret_from_sys_call 309CFI_END_OSF_FRAME entMM 310 311CFI_START_OSF_FRAME entIF 312 SAVE_ALL 313 lda $8, 0x3fff 314 lda $26, ret_from_sys_call 315 bic $sp, $8, $8 316 mov $sp, $17 317 jsr $31, do_entIF 318CFI_END_OSF_FRAME entIF 319 320CFI_START_OSF_FRAME entUna 321 lda $sp, -256($sp) 322 .cfi_adjust_cfa_offset 256 323 stq $0, 0($sp) 324 .cfi_rel_offset $0, 0 325 .cfi_remember_state 326 ldq $0, 256($sp) /* get PS */ 327 stq $1, 8($sp) 328 stq $2, 16($sp) 329 stq $3, 24($sp) 330 and $0, 8, $0 /* user mode? */ 331 stq $4, 32($sp) 332 bne $0, entUnaUser /* yup -> do user-level unaligned fault */ 333 stq $5, 40($sp) 334 stq $6, 48($sp) 335 stq $7, 56($sp) 336 stq $8, 64($sp) 337 stq $9, 72($sp) 338 stq $10, 80($sp) 339 stq $11, 88($sp) 340 stq $12, 96($sp) 341 stq $13, 104($sp) 342 stq $14, 112($sp) 343 stq $15, 120($sp) 344 /* 16-18 PAL-saved */ 345 stq $19, 152($sp) 346 stq $20, 160($sp) 347 stq $21, 168($sp) 348 stq $22, 176($sp) 349 stq $23, 184($sp) 350 stq $24, 192($sp) 351 stq $25, 200($sp) 352 stq $26, 208($sp) 353 stq $27, 216($sp) 354 stq $28, 224($sp) 355 mov $sp, $19 356 stq $gp, 232($sp) 357 .cfi_rel_offset $1, 1*8 358 .cfi_rel_offset $2, 2*8 359 .cfi_rel_offset $3, 3*8 360 .cfi_rel_offset $4, 4*8 361 .cfi_rel_offset $5, 5*8 362 .cfi_rel_offset $6, 6*8 363 .cfi_rel_offset $7, 7*8 364 .cfi_rel_offset $8, 8*8 365 .cfi_rel_offset $9, 9*8 366 .cfi_rel_offset $10, 10*8 367 .cfi_rel_offset $11, 11*8 368 .cfi_rel_offset $12, 12*8 369 .cfi_rel_offset $13, 13*8 370 .cfi_rel_offset $14, 14*8 371 .cfi_rel_offset $15, 15*8 372 .cfi_rel_offset $19, 19*8 373 .cfi_rel_offset $20, 20*8 374 .cfi_rel_offset $21, 21*8 375 .cfi_rel_offset $22, 22*8 376 .cfi_rel_offset $23, 23*8 377 .cfi_rel_offset $24, 24*8 378 .cfi_rel_offset $25, 25*8 379 .cfi_rel_offset $26, 26*8 380 .cfi_rel_offset $27, 27*8 381 .cfi_rel_offset $28, 28*8 382 .cfi_rel_offset $29, 29*8 383 lda $8, 0x3fff 384 stq $31, 248($sp) 385 bic $sp, $8, $8 386 jsr $26, do_entUna 387 ldq $0, 0($sp) 388 ldq $1, 8($sp) 389 ldq $2, 16($sp) 390 ldq $3, 24($sp) 391 ldq $4, 32($sp) 392 ldq $5, 40($sp) 393 ldq $6, 48($sp) 394 ldq $7, 56($sp) 395 ldq $8, 64($sp) 396 ldq $9, 72($sp) 397 ldq $10, 80($sp) 398 ldq $11, 88($sp) 399 ldq $12, 96($sp) 400 ldq $13, 104($sp) 401 ldq $14, 112($sp) 402 ldq $15, 120($sp) 403 /* 16-18 PAL-saved */ 404 ldq $19, 152($sp) 405 ldq $20, 160($sp) 406 ldq $21, 168($sp) 407 ldq $22, 176($sp) 408 ldq $23, 184($sp) 409 ldq $24, 192($sp) 410 ldq $25, 200($sp) 411 ldq $26, 208($sp) 412 ldq $27, 216($sp) 413 ldq $28, 224($sp) 414 ldq $gp, 232($sp) 415 lda $sp, 256($sp) 416 .cfi_restore $1 417 .cfi_restore $2 418 .cfi_restore $3 419 .cfi_restore $4 420 .cfi_restore $5 421 .cfi_restore $6 422 .cfi_restore $7 423 .cfi_restore $8 424 .cfi_restore $9 425 .cfi_restore $10 426 .cfi_restore $11 427 .cfi_restore $12 428 .cfi_restore $13 429 .cfi_restore $14 430 .cfi_restore $15 431 .cfi_restore $19 432 .cfi_restore $20 433 .cfi_restore $21 434 .cfi_restore $22 435 .cfi_restore $23 436 .cfi_restore $24 437 .cfi_restore $25 438 .cfi_restore $26 439 .cfi_restore $27 440 .cfi_restore $28 441 .cfi_restore $29 442 .cfi_adjust_cfa_offset -256 443 LOCKDEP_HARDIRQS_ON_RESTORE 444 call_pal PAL_rti 445 446 .align 4 447entUnaUser: 448 .cfi_restore_state 449 ldq $0, 0($sp) /* restore original $0 */ 450 lda $sp, 256($sp) /* pop entUna's stack frame */ 451 .cfi_restore $0 452 .cfi_adjust_cfa_offset -256 453 SAVE_ALL /* setup normal kernel stack */ 454 lda $sp, -64($sp) 455 .cfi_adjust_cfa_offset 64 456 stq $9, 0($sp) 457 stq $10, 8($sp) 458 stq $11, 16($sp) 459 stq $12, 24($sp) 460 stq $13, 32($sp) 461 stq $14, 40($sp) 462 stq $15, 48($sp) 463 .cfi_rel_offset $9, 0 464 .cfi_rel_offset $10, 8 465 .cfi_rel_offset $11, 16 466 .cfi_rel_offset $12, 24 467 .cfi_rel_offset $13, 32 468 .cfi_rel_offset $14, 40 469 .cfi_rel_offset $15, 48 470 lda $8, 0x3fff 471 addq $sp, 64, $19 472 bic $sp, $8, $8 473 jsr $26, do_entUnaUser 474 ldq $9, 0($sp) 475 ldq $10, 8($sp) 476 ldq $11, 16($sp) 477 ldq $12, 24($sp) 478 ldq $13, 32($sp) 479 ldq $14, 40($sp) 480 ldq $15, 48($sp) 481 lda $sp, 64($sp) 482 .cfi_restore $9 483 .cfi_restore $10 484 .cfi_restore $11 485 .cfi_restore $12 486 .cfi_restore $13 487 .cfi_restore $14 488 .cfi_restore $15 489 .cfi_adjust_cfa_offset -64 490 br ret_from_sys_call 491CFI_END_OSF_FRAME entUna 492 493CFI_START_OSF_FRAME entDbg 494 SAVE_ALL 495 lda $8, 0x3fff 496 lda $26, ret_from_sys_call 497 bic $sp, $8, $8 498 mov $sp, $16 499 jsr $31, do_entDbg 500CFI_END_OSF_FRAME entDbg 501 502/* 503 * The system call entry point is special. Most importantly, it looks 504 * like a function call to userspace as far as clobbered registers. We 505 * do preserve the argument registers (for syscall restarts) and $26 506 * (for leaf syscall functions). 507 * 508 * So much for theory. We don't take advantage of this yet. 509 * 510 * Note that a0-a2 are not saved by PALcode as with the other entry points. 511 * 512 * Alpha syscall ABI uses: 513 * - r0 for return value 514 * - r19 ("a3") as error indicator (0=success, 1=error; r0 holds errno) 515 * 516 * For seccomp/ptrace/generic syscall helpers we track the syscall 517 * number separately: 518 * - regs->r1: current (mutable) syscall number (may be changed or set to -1) 519 * - regs->r2: original syscall number for restart/rollback 520 * 521 * On entry PAL provides the syscall number in r0; copy it into r1/r2. 522 */ 523 524 .align 4 525 .globl entSys 526 .type entSys, @function 527 .cfi_startproc simple 528 .cfi_return_column 64 529 .cfi_def_cfa $sp, 48 530 .cfi_rel_offset 64, 8 531 .cfi_rel_offset $gp, 16 532entSys: 533 SAVE_ALL 534 ldq $1, 0($sp) /* syscall nr from saved r0 */ 535 stq $1, 8($sp) /* regs->r1 = shadow syscall nr */ 536 stq $1, 16($sp) /* regs->r2 = restart syscall nr */ 537 /* Syscalls always enter from user mode: snapshot USP into pt_regs->usp */ 538 mov $0, $8 539 call_pal PAL_rdusp 540 stq $0, PT_REGS_USP($sp) 541 mov $8, $0 542 543 544 lda $8, 0x3fff 545 bic $sp, $8, $8 546 lda $4, NR_syscalls($31) 547 stq $16, SP_OFF+24($sp) 548 lda $5, sys_call_table 549 lda $27, sys_ni_syscall 550 cmpult $0, $4, $4 551 ldl $3, TI_FLAGS($8) 552 stq $17, SP_OFF+32($sp) 553 s8addq $0, $5, $5 554 stq $18, SP_OFF+40($sp) 555 .cfi_rel_offset $16, SP_OFF+24 556 .cfi_rel_offset $17, SP_OFF+32 557 .cfi_rel_offset $18, SP_OFF+40 558 lda $6, _TIF_SYSCALL_WORK 559 and $3, $6, $3 560 bne $3, strace 561 562 beq $4, 1f 563 ldq $27, 0($5) 5641: ldq $0, 8($sp) /* syscall nr shadow (regs->r1) */ 565 566 jsr $26, ($27), sys_ni_syscall 567 ldgp $gp, 0($26) 568 blt $0, $syscall_error /* the call failed */ 569$ret_success: 570 stq $0, 0($sp) 571 stq $31, 72($sp) /* a3=0 => no error */ 572 573 .align 4 574 .globl ret_from_sys_call 575ret_from_sys_call: 576 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ 577 ldq $0, SP_OFF($sp) 578 and $0, 8, $0 579 beq $0, ret_to_kernel 580ret_to_user: 581 /* Make sure need_resched and sigpending don't change between 582 sampling and the rti. */ 583 lda $16, 7 584 call_pal PAL_swpipl 585 ldl $17, TI_FLAGS($8) 586 and $17, _TIF_WORK_MASK, $2 587 bne $2, work_pending 588restore_all: 589 ldl $2, TI_STATUS($8) 590 and $2, TS_SAVED_FP | TS_RESTORE_FP, $3 591 bne $3, restore_fpu 592restore_other: 593 .cfi_remember_state 594 LOCKDEP_HARDIRQS_ON_RESTORE 595 RESTORE_ALL 596 call_pal PAL_rti 597 598ret_to_kernel: 599 .cfi_restore_state 600 lda $16, 7 601 call_pal PAL_swpipl 602 br restore_other 603 604 .align 3 605$syscall_error: 606 /* Restart syscall nr comes from saved r2 (preserved even if r0 overwritten). */ 607 ldq $18, 16($sp) /* old syscall nr for restart */ 608 609 ldq $19, 72($sp) /* .. and this a3 */ 610 subq $31, $0, $0 /* with error in v0 */ 611 addq $31, 1, $1 /* set a3 for errno return */ 612 stq $0, 0($sp) 613 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 614 stq $1, 72($sp) /* a3 for return */ 615 br ret_from_sys_call 616 617/* 618 * Do all cleanup when returning from all interrupts and system calls. 619 * 620 * Arguments: 621 * $8: current. 622 * $17: TI_FLAGS. 623 * $18: The old syscall number, or zero if this is not a return 624 * from a syscall that errored and is possibly restartable. 625 * $19: The old a3 value 626 */ 627 628 .align 4 629 .type work_pending, @function 630work_pending: 631 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL, $2 632 bne $2, $work_notifysig 633 634$work_resched: 635 /* 636 * We can get here only if we returned from syscall without SIGPENDING 637 * or got through work_notifysig already. Either case means no syscall 638 * restarts for us, so let $18 and $19 burn. 639 */ 640 jsr $26, alpha_schedule_user_work 641 mov 0, $18 642 br ret_to_user 643 644$work_notifysig: 645 mov $sp, $16 646 DO_SWITCH_STACK 647 jsr $26, do_work_pending 648 UNDO_SWITCH_STACK 649 br restore_all 650 651/* 652 * PTRACE syscall handler 653 */ 654 655 .align 4 656 .type strace, @function 657strace: 658 /* set up signal stack, call syscall_trace */ 659 // NB: if anyone adds preemption, this block will need to be protected 660 ldl $1, TI_STATUS($8) 661 and $1, TS_SAVED_FP, $3 662 or $1, TS_SAVED_FP, $2 663 bne $3, 1f 664 stl $2, TI_STATUS($8) 665 bsr $26, __save_fpu 6661: 667 DO_SWITCH_STACK 668 jsr $26, syscall_trace_enter /* returns the syscall number */ 669 UNDO_SWITCH_STACK 670 671 stq $0, 8($sp) /* regs->r1 = shadow syscall nr */ 672 673 /* get the arguments back.. */ 674 ldq $16, SP_OFF+24($sp) 675 ldq $17, SP_OFF+32($sp) 676 ldq $18, SP_OFF+40($sp) 677 ldq $19, 72($sp) 678 ldq $20, 80($sp) 679 ldq $21, 88($sp) 680 681 /* nr == -1: internal skip-dispatch or userspace syscall(-1)? */ 682 lda $6, -1($31) 683 cmpeq $0, $6, $6 684 bne $6, $strace_skip_call /* nr == -1 => dispatch */ 685 686 /* get the system call pointer.. */ 687 lda $1, NR_syscalls($31) 688 lda $2, sys_call_table 689 lda $27, sys_ni_syscall 690 cmpult $0, $1, $1 691 s8addq $0, $2, $2 692 beq $1, 1f 693 ldq $27, 0($2) 6941: jsr $26, ($27), sys_gettimeofday 695ret_from_straced: 696 ldgp $gp, 0($26) 697 698 /* check return.. */ 699 blt $0, $strace_error /* the call failed */ 700$strace_success: 701 stq $31, 72($sp) /* a3=0 => no error */ 702 stq $0, 0($sp) /* save return value */ 703 704$strace_skip_call: 705 SYSCALL_SKIP_RETURN_RESTART_GATE 706 DO_SWITCH_STACK 707 jsr $26, syscall_trace_leave 708 UNDO_SWITCH_STACK 709 br $31, ret_from_sys_call 710 711 .align 3 712$strace_error: 713 ldq $18, 16($sp) /* restart syscall nr */ 714 ldq $19, 72($sp) /* .. and this a3 */ 715 716 subq $31, $0, $0 /* with error in v0 */ 717 addq $31, 1, $1 /* set a3 for errno return */ 718 stq $0, 0($sp) 719 stq $1, 72($sp) /* a3 for return */ 720 721 DO_SWITCH_STACK 722 mov $18, $9 /* save old syscall number */ 723 mov $19, $10 /* save old a3 */ 724 jsr $26, syscall_trace_leave 725 mov $9, $18 726 mov $10, $19 727 UNDO_SWITCH_STACK 728 729 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 730 br ret_from_sys_call 731CFI_END_OSF_FRAME entSys 732 733/* 734 * Save and restore the switch stack -- aka the balance of the user context. 735 */ 736 737 .align 4 738 .type do_switch_stack, @function 739 .cfi_startproc simple 740 .cfi_return_column 64 741 .cfi_def_cfa $sp, 0 742 .cfi_register 64, $1 743do_switch_stack: 744 lda $sp, -SWITCH_STACK_SIZE($sp) 745 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE 746 stq $9, 0($sp) 747 stq $10, 8($sp) 748 stq $11, 16($sp) 749 stq $12, 24($sp) 750 stq $13, 32($sp) 751 stq $14, 40($sp) 752 stq $15, 48($sp) 753 stq $26, 56($sp) 754 ret $31, ($1), 1 755 .cfi_endproc 756 .size do_switch_stack, .-do_switch_stack 757 758 .align 4 759 .type undo_switch_stack, @function 760 .cfi_startproc simple 761 .cfi_def_cfa $sp, 0 762 .cfi_register 64, $1 763undo_switch_stack: 764 ldq $9, 0($sp) 765 ldq $10, 8($sp) 766 ldq $11, 16($sp) 767 ldq $12, 24($sp) 768 ldq $13, 32($sp) 769 ldq $14, 40($sp) 770 ldq $15, 48($sp) 771 ldq $26, 56($sp) 772 lda $sp, SWITCH_STACK_SIZE($sp) 773 ret $31, ($1), 1 774 .cfi_endproc 775 .size undo_switch_stack, .-undo_switch_stack 776 777#define FR(n) n * 8 + TI_FP($8) 778 .align 4 779 .globl __save_fpu 780 .type __save_fpu, @function 781__save_fpu: 782#define V(n) stt $f##n, FR(n) 783 V( 0); V( 1); V( 2); V( 3) 784 V( 4); V( 5); V( 6); V( 7) 785 V( 8); V( 9); V(10); V(11) 786 V(12); V(13); V(14); V(15) 787 V(16); V(17); V(18); V(19) 788 V(20); V(21); V(22); V(23) 789 V(24); V(25); V(26); V(27) 790 mf_fpcr $f0 # get fpcr 791 V(28); V(29); V(30) 792 stt $f0, FR(31) # save fpcr in slot of $f31 793 ldt $f0, FR(0) # don't let "__save_fpu" change fp state. 794 ret 795#undef V 796 .size __save_fpu, .-__save_fpu 797 798 .align 4 799restore_fpu: 800 and $3, TS_RESTORE_FP, $3 801 bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2 802 beq $3, 1f 803#define V(n) ldt $f##n, FR(n) 804 ldt $f30, FR(31) # get saved fpcr 805 V( 0); V( 1); V( 2); V( 3) 806 mt_fpcr $f30 # install saved fpcr 807 V( 4); V( 5); V( 6); V( 7) 808 V( 8); V( 9); V(10); V(11) 809 V(12); V(13); V(14); V(15) 810 V(16); V(17); V(18); V(19) 811 V(20); V(21); V(22); V(23) 812 V(24); V(25); V(26); V(27) 813 V(28); V(29); V(30) 8141: stl $2, TI_STATUS($8) 815 br restore_other 816#undef V 817 818 819/* 820 * The meat of the context switch code. 821 */ 822 .align 4 823 .globl alpha_switch_to 824 .type alpha_switch_to, @function 825 .cfi_startproc 826alpha_switch_to: 827 DO_SWITCH_STACK 828 ldl $1, TI_STATUS($8) 829 and $1, TS_RESTORE_FP, $3 830 bne $3, 1f 831 or $1, TS_RESTORE_FP | TS_SAVED_FP, $2 832 and $1, TS_SAVED_FP, $3 833 stl $2, TI_STATUS($8) 834 bne $3, 1f 835 bsr $26, __save_fpu 8361: 837 call_pal PAL_swpctx 838 lda $8, 0x3fff 839 UNDO_SWITCH_STACK 840 bic $sp, $8, $8 841 mov $17, $0 842 ret 843 .cfi_endproc 844 .size alpha_switch_to, .-alpha_switch_to 845 846/* 847 * New processes begin life here. 848 */ 849 850 .globl ret_from_fork 851 .align 4 852 .ent ret_from_fork 853ret_from_fork: 854 lda $26, ret_to_user 855 mov $17, $16 856 jmp $31, schedule_tail 857.end ret_from_fork 858 859/* 860 * ... and new kernel threads - here 861 */ 862 .align 4 863 .globl ret_from_kernel_thread 864 .ent ret_from_kernel_thread 865ret_from_kernel_thread: 866 mov $17, $16 867 jsr $26, schedule_tail 868 mov $9, $27 869 mov $10, $16 870 jsr $26, ($9) 871 br $31, ret_to_user 872.end ret_from_kernel_thread 873 874 875/* 876 * Special system calls. Most of these are special in that they either 877 * have to play switch_stack games. 878 */ 879 880.macro fork_like name 881 .align 4 882 .globl alpha_\name 883 .ent alpha_\name 884alpha_\name: 885 .prologue 0 886 bsr $1, do_switch_stack 887 // NB: if anyone adds preemption, this block will need to be protected 888 ldl $1, TI_STATUS($8) 889 and $1, TS_SAVED_FP, $3 890 or $1, TS_SAVED_FP, $2 891 bne $3, 1f 892 stl $2, TI_STATUS($8) 893 bsr $26, __save_fpu 8941: 895 jsr $26, sys_\name 896 ldq $26, 56($sp) 897 lda $sp, SWITCH_STACK_SIZE($sp) 898 ret 899.end alpha_\name 900.endm 901 902fork_like fork 903fork_like vfork 904fork_like clone 905fork_like clone3 906 907.macro sigreturn_like name 908 .align 4 909 .globl sys_\name 910 .ent sys_\name 911sys_\name: 912 .prologue 0 913 lda $9, ret_from_straced 914 cmpult $26, $9, $9 915 lda $sp, -SWITCH_STACK_SIZE($sp) 916 jsr $26, do_\name 917 bne $9, 1f 918 jsr $26, syscall_trace_leave 9191: br $1, undo_switch_stack 920 br ret_from_sys_call 921.end sys_\name 922.endm 923 924sigreturn_like sigreturn 925sigreturn_like rt_sigreturn 926 927 .align 4 928 .globl alpha_syscall_zero 929 .ent alpha_syscall_zero 930alpha_syscall_zero: 931 .prologue 0 932 /* Special because it needs to do something opposite to 933 force_successful_syscall_return(). We use the saved 934 syscall number for that, zero meaning "not an error". 935 That works nicely, but for real syscall 0 we need to 936 make sure that this logics doesn't get confused. 937 Store a non-zero there - -ENOSYS we need in register 938 for our return value will do just fine. 939 */ 940 lda $0, -ENOSYS 941 unop 942 stq $0, 0($sp) 943 ret 944.end alpha_syscall_zero 945