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 /* Stack offsets. */ 19 #define SP_OFF 184 20 #define SWITCH_STACK_SIZE 64 21 22 .macro CFI_START_OSF_FRAME func 23 .align 4 24 .globl \func 25 .type \func,@function 26 \func: 27 .cfi_startproc simple 28 .cfi_return_column 64 29 .cfi_def_cfa $sp, 48 30 .cfi_rel_offset 64, 8 31 .cfi_rel_offset $gp, 16 32 .cfi_rel_offset $16, 24 33 .cfi_rel_offset $17, 32 34 .cfi_rel_offset $18, 40 35 .endm 36 37 .macro CFI_END_OSF_FRAME func 38 .cfi_endproc 39 .size \func, . - \func 40 .endm 41 42 /* 43 * This defines the normal kernel pt-regs layout. 44 * 45 * regs 9-15 preserved by C code 46 * regs 16-18 saved by PAL-code 47 * regs 29-30 saved and set up by PAL-code 48 * JRP - Save regs 16-18 in a special area of the stack, so that 49 * the palcode-provided values are available to the signal handler. 50 */ 51 52 .macro SAVE_ALL 53 subq $sp, SP_OFF, $sp 54 .cfi_adjust_cfa_offset SP_OFF 55 stq $0, 0($sp) 56 stq $1, 8($sp) 57 stq $2, 16($sp) 58 stq $3, 24($sp) 59 stq $4, 32($sp) 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 472 #else 473 blbs $3, strace /* check for SYSCALL_TRACE in disguise */ 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 513 514 .align 3 515 $syscall_error: 516 /* 517 * Some system calls (e.g., ptrace) can return arbitrary 518 * values which might normally be mistaken as error numbers. 519 * Those functions must zero $0 (v0) directly in the stack 520 * frame to indicate that a negative return value wasn't an 521 * error number.. 522 */ 523 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 524 beq $18, $ret_success 525 526 ldq $19, 72($sp) /* .. and this a3 */ 527 subq $31, $0, $0 /* with error in v0 */ 528 addq $31, 1, $1 /* set a3 for errno return */ 529 stq $0, 0($sp) 530 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 531 stq $1, 72($sp) /* a3 for return */ 532 br ret_from_sys_call 533 534 /* 535 * Do all cleanup when returning from all interrupts and system calls. 536 * 537 * Arguments: 538 * $8: current. 539 * $17: TI_FLAGS. 540 * $18: The old syscall number, or zero if this is not a return 541 * from a syscall that errored and is possibly restartable. 542 * $19: The old a3 value 543 */ 544 545 .align 4 546 .type work_pending, @function 547 work_pending: 548 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL, $2 549 bne $2, $work_notifysig 550 551 $work_resched: 552 /* 553 * We can get here only if we returned from syscall without SIGPENDING 554 * or got through work_notifysig already. Either case means no syscall 555 * restarts for us, so let $18 and $19 burn. 556 */ 557 jsr $26, schedule 558 mov 0, $18 559 br ret_to_user 560 561 $work_notifysig: 562 mov $sp, $16 563 DO_SWITCH_STACK 564 jsr $26, do_work_pending 565 UNDO_SWITCH_STACK 566 br restore_all 567 568 /* 569 * PTRACE syscall handler 570 */ 571 572 .align 4 573 .type strace, @function 574 strace: 575 /* set up signal stack, call syscall_trace */ 576 // NB: if anyone adds preemption, this block will need to be protected 577 ldl $1, TI_STATUS($8) 578 and $1, TS_SAVED_FP, $3 579 or $1, TS_SAVED_FP, $2 580 bne $3, 1f 581 stl $2, TI_STATUS($8) 582 bsr $26, __save_fpu 583 1: 584 DO_SWITCH_STACK 585 jsr $26, syscall_trace_enter /* returns the syscall number */ 586 UNDO_SWITCH_STACK 587 588 /* get the arguments back.. */ 589 ldq $16, SP_OFF+24($sp) 590 ldq $17, SP_OFF+32($sp) 591 ldq $18, SP_OFF+40($sp) 592 ldq $19, 72($sp) 593 ldq $20, 80($sp) 594 ldq $21, 88($sp) 595 596 /* get the system call pointer.. */ 597 lda $1, NR_syscalls($31) 598 lda $2, sys_call_table 599 lda $27, sys_ni_syscall 600 cmpult $0, $1, $1 601 s8addq $0, $2, $2 602 beq $1, 1f 603 ldq $27, 0($2) 604 1: jsr $26, ($27), sys_gettimeofday 605 ret_from_straced: 606 ldgp $gp, 0($26) 607 608 /* check return.. */ 609 blt $0, $strace_error /* the call failed */ 610 $strace_success: 611 stq $31, 72($sp) /* a3=0 => no error */ 612 stq $0, 0($sp) /* save return value */ 613 614 DO_SWITCH_STACK 615 jsr $26, syscall_trace_leave 616 UNDO_SWITCH_STACK 617 br $31, ret_from_sys_call 618 619 .align 3 620 $strace_error: 621 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 622 beq $18, $strace_success 623 ldq $19, 72($sp) /* .. and this a3 */ 624 625 subq $31, $0, $0 /* with error in v0 */ 626 addq $31, 1, $1 /* set a3 for errno return */ 627 stq $0, 0($sp) 628 stq $1, 72($sp) /* a3 for return */ 629 630 DO_SWITCH_STACK 631 mov $18, $9 /* save old syscall number */ 632 mov $19, $10 /* save old a3 */ 633 jsr $26, syscall_trace_leave 634 mov $9, $18 635 mov $10, $19 636 UNDO_SWITCH_STACK 637 638 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 639 br ret_from_sys_call 640 CFI_END_OSF_FRAME entSys 641 642 /* 643 * Save and restore the switch stack -- aka the balance of the user context. 644 */ 645 646 .align 4 647 .type do_switch_stack, @function 648 .cfi_startproc simple 649 .cfi_return_column 64 650 .cfi_def_cfa $sp, 0 651 .cfi_register 64, $1 652 do_switch_stack: 653 lda $sp, -SWITCH_STACK_SIZE($sp) 654 .cfi_adjust_cfa_offset SWITCH_STACK_SIZE 655 stq $9, 0($sp) 656 stq $10, 8($sp) 657 stq $11, 16($sp) 658 stq $12, 24($sp) 659 stq $13, 32($sp) 660 stq $14, 40($sp) 661 stq $15, 48($sp) 662 stq $26, 56($sp) 663 ret $31, ($1), 1 664 .cfi_endproc 665 .size do_switch_stack, .-do_switch_stack 666 667 .align 4 668 .type undo_switch_stack, @function 669 .cfi_startproc simple 670 .cfi_def_cfa $sp, 0 671 .cfi_register 64, $1 672 undo_switch_stack: 673 ldq $9, 0($sp) 674 ldq $10, 8($sp) 675 ldq $11, 16($sp) 676 ldq $12, 24($sp) 677 ldq $13, 32($sp) 678 ldq $14, 40($sp) 679 ldq $15, 48($sp) 680 ldq $26, 56($sp) 681 lda $sp, SWITCH_STACK_SIZE($sp) 682 ret $31, ($1), 1 683 .cfi_endproc 684 .size undo_switch_stack, .-undo_switch_stack 685 686 #define FR(n) n * 8 + TI_FP($8) 687 .align 4 688 .globl __save_fpu 689 .type __save_fpu, @function 690 __save_fpu: 691 #define V(n) stt $f##n, FR(n) 692 V( 0); V( 1); V( 2); V( 3) 693 V( 4); V( 5); V( 6); V( 7) 694 V( 8); V( 9); V(10); V(11) 695 V(12); V(13); V(14); V(15) 696 V(16); V(17); V(18); V(19) 697 V(20); V(21); V(22); V(23) 698 V(24); V(25); V(26); V(27) 699 mf_fpcr $f0 # get fpcr 700 V(28); V(29); V(30) 701 stt $f0, FR(31) # save fpcr in slot of $f31 702 ldt $f0, FR(0) # don't let "__save_fpu" change fp state. 703 ret 704 #undef V 705 .size __save_fpu, .-__save_fpu 706 707 .align 4 708 restore_fpu: 709 and $3, TS_RESTORE_FP, $3 710 bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2 711 beq $3, 1f 712 #define V(n) ldt $f##n, FR(n) 713 ldt $f30, FR(31) # get saved fpcr 714 V( 0); V( 1); V( 2); V( 3) 715 mt_fpcr $f30 # install saved fpcr 716 V( 4); V( 5); V( 6); V( 7) 717 V( 8); V( 9); V(10); V(11) 718 V(12); V(13); V(14); V(15) 719 V(16); V(17); V(18); V(19) 720 V(20); V(21); V(22); V(23) 721 V(24); V(25); V(26); V(27) 722 V(28); V(29); V(30) 723 1: stl $2, TI_STATUS($8) 724 br restore_other 725 #undef V 726 727 728 /* 729 * The meat of the context switch code. 730 */ 731 .align 4 732 .globl alpha_switch_to 733 .type alpha_switch_to, @function 734 .cfi_startproc 735 alpha_switch_to: 736 DO_SWITCH_STACK 737 ldl $1, TI_STATUS($8) 738 and $1, TS_RESTORE_FP, $3 739 bne $3, 1f 740 or $1, TS_RESTORE_FP | TS_SAVED_FP, $2 741 and $1, TS_SAVED_FP, $3 742 stl $2, TI_STATUS($8) 743 bne $3, 1f 744 bsr $26, __save_fpu 745 1: 746 call_pal PAL_swpctx 747 lda $8, 0x3fff 748 UNDO_SWITCH_STACK 749 bic $sp, $8, $8 750 mov $17, $0 751 ret 752 .cfi_endproc 753 .size alpha_switch_to, .-alpha_switch_to 754 755 /* 756 * New processes begin life here. 757 */ 758 759 .globl ret_from_fork 760 .align 4 761 .ent ret_from_fork 762 ret_from_fork: 763 lda $26, ret_to_user 764 mov $17, $16 765 jmp $31, schedule_tail 766 .end ret_from_fork 767 768 /* 769 * ... and new kernel threads - here 770 */ 771 .align 4 772 .globl ret_from_kernel_thread 773 .ent ret_from_kernel_thread 774 ret_from_kernel_thread: 775 mov $17, $16 776 jsr $26, schedule_tail 777 mov $9, $27 778 mov $10, $16 779 jsr $26, ($9) 780 br $31, ret_to_user 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.