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