1/* 2 * arch/alpha/kernel/entry.S 3 * 4 * Kernel entry-points. 5 */ 6 7#include <asm/asm-offsets.h> 8#include <asm/thread_info.h> 9#include <asm/pal.h> 10#include <asm/errno.h> 11#include <asm/unistd.h> 12 13 .text 14 .set noat 15 16/* Stack offsets. */ 17#define SP_OFF 184 18#define SWITCH_STACK_SIZE 320 19 20/* 21 * This defines the normal kernel pt-regs layout. 22 * 23 * regs 9-15 preserved by C code 24 * regs 16-18 saved by PAL-code 25 * regs 29-30 saved and set up by PAL-code 26 * JRP - Save regs 16-18 in a special area of the stack, so that 27 * the palcode-provided values are available to the signal handler. 28 */ 29 30#define SAVE_ALL \ 31 subq $sp, SP_OFF, $sp; \ 32 stq $0, 0($sp); \ 33 stq $1, 8($sp); \ 34 stq $2, 16($sp); \ 35 stq $3, 24($sp); \ 36 stq $4, 32($sp); \ 37 stq $28, 144($sp); \ 38 lda $2, alpha_mv; \ 39 stq $5, 40($sp); \ 40 stq $6, 48($sp); \ 41 stq $7, 56($sp); \ 42 stq $8, 64($sp); \ 43 stq $19, 72($sp); \ 44 stq $20, 80($sp); \ 45 stq $21, 88($sp); \ 46 ldq $2, HAE_CACHE($2); \ 47 stq $22, 96($sp); \ 48 stq $23, 104($sp); \ 49 stq $24, 112($sp); \ 50 stq $25, 120($sp); \ 51 stq $26, 128($sp); \ 52 stq $27, 136($sp); \ 53 stq $2, 152($sp); \ 54 stq $16, 160($sp); \ 55 stq $17, 168($sp); \ 56 stq $18, 176($sp) 57 58#define RESTORE_ALL \ 59 lda $19, alpha_mv; \ 60 ldq $0, 0($sp); \ 61 ldq $1, 8($sp); \ 62 ldq $2, 16($sp); \ 63 ldq $3, 24($sp); \ 64 ldq $21, 152($sp); \ 65 ldq $20, HAE_CACHE($19); \ 66 ldq $4, 32($sp); \ 67 ldq $5, 40($sp); \ 68 ldq $6, 48($sp); \ 69 ldq $7, 56($sp); \ 70 subq $20, $21, $20; \ 71 ldq $8, 64($sp); \ 72 beq $20, 99f; \ 73 ldq $20, HAE_REG($19); \ 74 stq $21, HAE_CACHE($19); \ 75 stq $21, 0($20); \ 7699:; \ 77 ldq $19, 72($sp); \ 78 ldq $20, 80($sp); \ 79 ldq $21, 88($sp); \ 80 ldq $22, 96($sp); \ 81 ldq $23, 104($sp); \ 82 ldq $24, 112($sp); \ 83 ldq $25, 120($sp); \ 84 ldq $26, 128($sp); \ 85 ldq $27, 136($sp); \ 86 ldq $28, 144($sp); \ 87 addq $sp, SP_OFF, $sp 88 89/* 90 * Non-syscall kernel entry points. 91 */ 92 93 .align 4 94 .globl entInt 95 .ent entInt 96entInt: 97 SAVE_ALL 98 lda $8, 0x3fff 99 lda $26, ret_from_sys_call 100 bic $sp, $8, $8 101 mov $sp, $19 102 jsr $31, do_entInt 103.end entInt 104 105 .align 4 106 .globl entArith 107 .ent entArith 108entArith: 109 SAVE_ALL 110 lda $8, 0x3fff 111 lda $26, ret_from_sys_call 112 bic $sp, $8, $8 113 mov $sp, $18 114 jsr $31, do_entArith 115.end entArith 116 117 .align 4 118 .globl entMM 119 .ent entMM 120entMM: 121 SAVE_ALL 122/* save $9 - $15 so the inline exception code can manipulate them. */ 123 subq $sp, 56, $sp 124 stq $9, 0($sp) 125 stq $10, 8($sp) 126 stq $11, 16($sp) 127 stq $12, 24($sp) 128 stq $13, 32($sp) 129 stq $14, 40($sp) 130 stq $15, 48($sp) 131 addq $sp, 56, $19 132/* handle the fault */ 133 lda $8, 0x3fff 134 bic $sp, $8, $8 135 jsr $26, do_page_fault 136/* reload the registers after the exception code played. */ 137 ldq $9, 0($sp) 138 ldq $10, 8($sp) 139 ldq $11, 16($sp) 140 ldq $12, 24($sp) 141 ldq $13, 32($sp) 142 ldq $14, 40($sp) 143 ldq $15, 48($sp) 144 addq $sp, 56, $sp 145/* finish up the syscall as normal. */ 146 br ret_from_sys_call 147.end entMM 148 149 .align 4 150 .globl entIF 151 .ent entIF 152entIF: 153 SAVE_ALL 154 lda $8, 0x3fff 155 lda $26, ret_from_sys_call 156 bic $sp, $8, $8 157 mov $sp, $17 158 jsr $31, do_entIF 159.end entIF 160 161 .align 4 162 .globl entUna 163 .ent entUna 164entUna: 165 lda $sp, -256($sp) 166 stq $0, 0($sp) 167 ldq $0, 256($sp) /* get PS */ 168 stq $1, 8($sp) 169 stq $2, 16($sp) 170 stq $3, 24($sp) 171 and $0, 8, $0 /* user mode? */ 172 stq $4, 32($sp) 173 bne $0, entUnaUser /* yup -> do user-level unaligned fault */ 174 stq $5, 40($sp) 175 stq $6, 48($sp) 176 stq $7, 56($sp) 177 stq $8, 64($sp) 178 stq $9, 72($sp) 179 stq $10, 80($sp) 180 stq $11, 88($sp) 181 stq $12, 96($sp) 182 stq $13, 104($sp) 183 stq $14, 112($sp) 184 stq $15, 120($sp) 185 /* 16-18 PAL-saved */ 186 stq $19, 152($sp) 187 stq $20, 160($sp) 188 stq $21, 168($sp) 189 stq $22, 176($sp) 190 stq $23, 184($sp) 191 stq $24, 192($sp) 192 stq $25, 200($sp) 193 stq $26, 208($sp) 194 stq $27, 216($sp) 195 stq $28, 224($sp) 196 mov $sp, $19 197 stq $gp, 232($sp) 198 lda $8, 0x3fff 199 stq $31, 248($sp) 200 bic $sp, $8, $8 201 jsr $26, do_entUna 202 ldq $0, 0($sp) 203 ldq $1, 8($sp) 204 ldq $2, 16($sp) 205 ldq $3, 24($sp) 206 ldq $4, 32($sp) 207 ldq $5, 40($sp) 208 ldq $6, 48($sp) 209 ldq $7, 56($sp) 210 ldq $8, 64($sp) 211 ldq $9, 72($sp) 212 ldq $10, 80($sp) 213 ldq $11, 88($sp) 214 ldq $12, 96($sp) 215 ldq $13, 104($sp) 216 ldq $14, 112($sp) 217 ldq $15, 120($sp) 218 /* 16-18 PAL-saved */ 219 ldq $19, 152($sp) 220 ldq $20, 160($sp) 221 ldq $21, 168($sp) 222 ldq $22, 176($sp) 223 ldq $23, 184($sp) 224 ldq $24, 192($sp) 225 ldq $25, 200($sp) 226 ldq $26, 208($sp) 227 ldq $27, 216($sp) 228 ldq $28, 224($sp) 229 ldq $gp, 232($sp) 230 lda $sp, 256($sp) 231 call_pal PAL_rti 232.end entUna 233 234 .align 4 235 .ent entUnaUser 236entUnaUser: 237 ldq $0, 0($sp) /* restore original $0 */ 238 lda $sp, 256($sp) /* pop entUna's stack frame */ 239 SAVE_ALL /* setup normal kernel stack */ 240 lda $sp, -56($sp) 241 stq $9, 0($sp) 242 stq $10, 8($sp) 243 stq $11, 16($sp) 244 stq $12, 24($sp) 245 stq $13, 32($sp) 246 stq $14, 40($sp) 247 stq $15, 48($sp) 248 lda $8, 0x3fff 249 addq $sp, 56, $19 250 bic $sp, $8, $8 251 jsr $26, do_entUnaUser 252 ldq $9, 0($sp) 253 ldq $10, 8($sp) 254 ldq $11, 16($sp) 255 ldq $12, 24($sp) 256 ldq $13, 32($sp) 257 ldq $14, 40($sp) 258 ldq $15, 48($sp) 259 lda $sp, 56($sp) 260 br ret_from_sys_call 261.end entUnaUser 262 263 .align 4 264 .globl entDbg 265 .ent entDbg 266entDbg: 267 SAVE_ALL 268 lda $8, 0x3fff 269 lda $26, ret_from_sys_call 270 bic $sp, $8, $8 271 mov $sp, $16 272 jsr $31, do_entDbg 273.end entDbg 274 275/* 276 * The system call entry point is special. Most importantly, it looks 277 * like a function call to userspace as far as clobbered registers. We 278 * do preserve the argument registers (for syscall restarts) and $26 279 * (for leaf syscall functions). 280 * 281 * So much for theory. We don't take advantage of this yet. 282 * 283 * Note that a0-a2 are not saved by PALcode as with the other entry points. 284 */ 285 286 .align 4 287 .globl entSys 288 .globl ret_from_sys_call 289 .ent entSys 290entSys: 291 SAVE_ALL 292 lda $8, 0x3fff 293 bic $sp, $8, $8 294 lda $4, NR_SYSCALLS($31) 295 stq $16, SP_OFF+24($sp) 296 lda $5, sys_call_table 297 lda $27, sys_ni_syscall 298 cmpult $0, $4, $4 299 ldl $3, TI_FLAGS($8) 300 stq $17, SP_OFF+32($sp) 301 s8addq $0, $5, $5 302 stq $18, SP_OFF+40($sp) 303 blbs $3, strace 304 beq $4, 1f 305 ldq $27, 0($5) 3061: jsr $26, ($27), alpha_ni_syscall 307 ldgp $gp, 0($26) 308 blt $0, $syscall_error /* the call failed */ 309 stq $0, 0($sp) 310 stq $31, 72($sp) /* a3=0 => no error */ 311 312 .align 4 313ret_from_sys_call: 314 cmovne $26, 0, $18 /* $18 = 0 => non-restartable */ 315 ldq $0, SP_OFF($sp) 316 and $0, 8, $0 317 beq $0, ret_to_kernel 318ret_to_user: 319 /* Make sure need_resched and sigpending don't change between 320 sampling and the rti. */ 321 lda $16, 7 322 call_pal PAL_swpipl 323 ldl $17, TI_FLAGS($8) 324 and $17, _TIF_WORK_MASK, $2 325 bne $2, work_pending 326restore_all: 327 RESTORE_ALL 328 call_pal PAL_rti 329 330ret_to_kernel: 331 lda $16, 7 332 call_pal PAL_swpipl 333 br restore_all 334 335 .align 3 336$syscall_error: 337 /* 338 * Some system calls (e.g., ptrace) can return arbitrary 339 * values which might normally be mistaken as error numbers. 340 * Those functions must zero $0 (v0) directly in the stack 341 * frame to indicate that a negative return value wasn't an 342 * error number.. 343 */ 344 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 345 beq $18, $ret_success 346 347 ldq $19, 72($sp) /* .. and this a3 */ 348 subq $31, $0, $0 /* with error in v0 */ 349 addq $31, 1, $1 /* set a3 for errno return */ 350 stq $0, 0($sp) 351 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 352 stq $1, 72($sp) /* a3 for return */ 353 br ret_from_sys_call 354 355$ret_success: 356 stq $0, 0($sp) 357 stq $31, 72($sp) /* a3=0 => no error */ 358 br ret_from_sys_call 359.end entSys 360 361/* 362 * Do all cleanup when returning from all interrupts and system calls. 363 * 364 * Arguments: 365 * $8: current. 366 * $17: TI_FLAGS. 367 * $18: The old syscall number, or zero if this is not a return 368 * from a syscall that errored and is possibly restartable. 369 * $19: The old a3 value 370 */ 371 372 .align 4 373 .ent work_pending 374work_pending: 375 and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2 376 bne $2, $work_notifysig 377 378$work_resched: 379 /* 380 * We can get here only if we returned from syscall without SIGPENDING 381 * or got through work_notifysig already. Either case means no syscall 382 * restarts for us, so let $18 and $19 burn. 383 */ 384 jsr $26, schedule 385 mov 0, $18 386 br ret_to_user 387 388$work_notifysig: 389 mov $sp, $16 390 bsr $1, do_switch_stack 391 jsr $26, do_work_pending 392 bsr $1, undo_switch_stack 393 br restore_all 394.end work_pending 395 396/* 397 * PTRACE syscall handler 398 */ 399 400 .align 4 401 .ent strace 402strace: 403 /* set up signal stack, call syscall_trace */ 404 bsr $1, do_switch_stack 405 jsr $26, syscall_trace_enter /* returns the syscall number */ 406 bsr $1, undo_switch_stack 407 408 /* get the arguments back.. */ 409 ldq $16, SP_OFF+24($sp) 410 ldq $17, SP_OFF+32($sp) 411 ldq $18, SP_OFF+40($sp) 412 ldq $19, 72($sp) 413 ldq $20, 80($sp) 414 ldq $21, 88($sp) 415 416 /* get the system call pointer.. */ 417 lda $1, NR_SYSCALLS($31) 418 lda $2, sys_call_table 419 lda $27, alpha_ni_syscall 420 cmpult $0, $1, $1 421 s8addq $0, $2, $2 422 beq $1, 1f 423 ldq $27, 0($2) 4241: jsr $26, ($27), sys_gettimeofday 425ret_from_straced: 426 ldgp $gp, 0($26) 427 428 /* check return.. */ 429 blt $0, $strace_error /* the call failed */ 430 stq $31, 72($sp) /* a3=0 => no error */ 431$strace_success: 432 stq $0, 0($sp) /* save return value */ 433 434 bsr $1, do_switch_stack 435 jsr $26, syscall_trace_leave 436 bsr $1, undo_switch_stack 437 br $31, ret_from_sys_call 438 439 .align 3 440$strace_error: 441 ldq $18, 0($sp) /* old syscall nr (zero if success) */ 442 beq $18, $strace_success 443 ldq $19, 72($sp) /* .. and this a3 */ 444 445 subq $31, $0, $0 /* with error in v0 */ 446 addq $31, 1, $1 /* set a3 for errno return */ 447 stq $0, 0($sp) 448 stq $1, 72($sp) /* a3 for return */ 449 450 bsr $1, do_switch_stack 451 mov $18, $9 /* save old syscall number */ 452 mov $19, $10 /* save old a3 */ 453 jsr $26, syscall_trace_leave 454 mov $9, $18 455 mov $10, $19 456 bsr $1, undo_switch_stack 457 458 mov $31, $26 /* tell "ret_from_sys_call" we can restart */ 459 br ret_from_sys_call 460.end strace 461 462/* 463 * Save and restore the switch stack -- aka the balance of the user context. 464 */ 465 466 .align 4 467 .ent do_switch_stack 468do_switch_stack: 469 lda $sp, -SWITCH_STACK_SIZE($sp) 470 stq $9, 0($sp) 471 stq $10, 8($sp) 472 stq $11, 16($sp) 473 stq $12, 24($sp) 474 stq $13, 32($sp) 475 stq $14, 40($sp) 476 stq $15, 48($sp) 477 stq $26, 56($sp) 478 stt $f0, 64($sp) 479 stt $f1, 72($sp) 480 stt $f2, 80($sp) 481 stt $f3, 88($sp) 482 stt $f4, 96($sp) 483 stt $f5, 104($sp) 484 stt $f6, 112($sp) 485 stt $f7, 120($sp) 486 stt $f8, 128($sp) 487 stt $f9, 136($sp) 488 stt $f10, 144($sp) 489 stt $f11, 152($sp) 490 stt $f12, 160($sp) 491 stt $f13, 168($sp) 492 stt $f14, 176($sp) 493 stt $f15, 184($sp) 494 stt $f16, 192($sp) 495 stt $f17, 200($sp) 496 stt $f18, 208($sp) 497 stt $f19, 216($sp) 498 stt $f20, 224($sp) 499 stt $f21, 232($sp) 500 stt $f22, 240($sp) 501 stt $f23, 248($sp) 502 stt $f24, 256($sp) 503 stt $f25, 264($sp) 504 stt $f26, 272($sp) 505 stt $f27, 280($sp) 506 mf_fpcr $f0 # get fpcr 507 stt $f28, 288($sp) 508 stt $f29, 296($sp) 509 stt $f30, 304($sp) 510 stt $f0, 312($sp) # save fpcr in slot of $f31 511 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state. 512 ret $31, ($1), 1 513.end do_switch_stack 514 515 .align 4 516 .ent undo_switch_stack 517undo_switch_stack: 518 ldq $9, 0($sp) 519 ldq $10, 8($sp) 520 ldq $11, 16($sp) 521 ldq $12, 24($sp) 522 ldq $13, 32($sp) 523 ldq $14, 40($sp) 524 ldq $15, 48($sp) 525 ldq $26, 56($sp) 526 ldt $f30, 312($sp) # get saved fpcr 527 ldt $f0, 64($sp) 528 ldt $f1, 72($sp) 529 ldt $f2, 80($sp) 530 ldt $f3, 88($sp) 531 mt_fpcr $f30 # install saved fpcr 532 ldt $f4, 96($sp) 533 ldt $f5, 104($sp) 534 ldt $f6, 112($sp) 535 ldt $f7, 120($sp) 536 ldt $f8, 128($sp) 537 ldt $f9, 136($sp) 538 ldt $f10, 144($sp) 539 ldt $f11, 152($sp) 540 ldt $f12, 160($sp) 541 ldt $f13, 168($sp) 542 ldt $f14, 176($sp) 543 ldt $f15, 184($sp) 544 ldt $f16, 192($sp) 545 ldt $f17, 200($sp) 546 ldt $f18, 208($sp) 547 ldt $f19, 216($sp) 548 ldt $f20, 224($sp) 549 ldt $f21, 232($sp) 550 ldt $f22, 240($sp) 551 ldt $f23, 248($sp) 552 ldt $f24, 256($sp) 553 ldt $f25, 264($sp) 554 ldt $f26, 272($sp) 555 ldt $f27, 280($sp) 556 ldt $f28, 288($sp) 557 ldt $f29, 296($sp) 558 ldt $f30, 304($sp) 559 lda $sp, SWITCH_STACK_SIZE($sp) 560 ret $31, ($1), 1 561.end undo_switch_stack 562 563/* 564 * The meat of the context switch code. 565 */ 566 567 .align 4 568 .globl alpha_switch_to 569 .ent alpha_switch_to 570alpha_switch_to: 571 .prologue 0 572 bsr $1, do_switch_stack 573 call_pal PAL_swpctx 574 lda $8, 0x3fff 575 bsr $1, undo_switch_stack 576 bic $sp, $8, $8 577 mov $17, $0 578 ret 579.end alpha_switch_to 580 581/* 582 * New processes begin life here. 583 */ 584 585 .globl ret_from_fork 586 .align 4 587 .ent ret_from_fork 588ret_from_fork: 589 lda $26, ret_from_sys_call 590 mov $17, $16 591 jmp $31, schedule_tail 592.end ret_from_fork 593 594/* 595 * ... and new kernel threads - here 596 */ 597 .align 4 598 .globl ret_from_kernel_thread 599 .ent ret_from_kernel_thread 600ret_from_kernel_thread: 601 mov $17, $16 602 jsr $26, schedule_tail 603 mov $9, $27 604 mov $10, $16 605 jsr $26, ($9) 606 mov $31, $19 /* to disable syscall restarts */ 607 br $31, ret_to_user 608.end ret_from_kernel_thread 609 610 611/* 612 * Special system calls. Most of these are special in that they either 613 * have to play switch_stack games or in some way use the pt_regs struct. 614 */ 615 616.macro fork_like name 617 .align 4 618 .globl alpha_\name 619 .ent alpha_\name 620alpha_\name: 621 .prologue 0 622 bsr $1, do_switch_stack 623 jsr $26, sys_\name 624 ldq $26, 56($sp) 625 lda $sp, SWITCH_STACK_SIZE($sp) 626 ret 627.end alpha_\name 628.endm 629 630fork_like fork 631fork_like vfork 632fork_like clone 633 634 .align 4 635 .globl sys_sigreturn 636 .ent sys_sigreturn 637sys_sigreturn: 638 .prologue 0 639 lda $9, ret_from_straced 640 cmpult $26, $9, $9 641 lda $sp, -SWITCH_STACK_SIZE($sp) 642 jsr $26, do_sigreturn 643 bne $9, 1f 644 jsr $26, syscall_trace_leave 6451: br $1, undo_switch_stack 646 br ret_from_sys_call 647.end sys_sigreturn 648 649 .align 4 650 .globl sys_rt_sigreturn 651 .ent sys_rt_sigreturn 652sys_rt_sigreturn: 653 .prologue 0 654 lda $9, ret_from_straced 655 cmpult $26, $9, $9 656 lda $sp, -SWITCH_STACK_SIZE($sp) 657 jsr $26, do_rt_sigreturn 658 bne $9, 1f 659 jsr $26, syscall_trace_leave 6601: br $1, undo_switch_stack 661 br ret_from_sys_call 662.end sys_rt_sigreturn 663 664 .align 4 665 .globl alpha_ni_syscall 666 .ent alpha_ni_syscall 667alpha_ni_syscall: 668 .prologue 0 669 /* Special because it also implements overflow handling via 670 syscall number 0. And if you recall, zero is a special 671 trigger for "not an error". Store large non-zero there. */ 672 lda $0, -ENOSYS 673 unop 674 stq $0, 0($sp) 675 ret 676.end alpha_ni_syscall 677