ia64/linux-2.6.18-xen.hg

annotate arch/alpha/kernel/entry.S @ 912:dd42cdb0ab89

[IA64] Build blktap2 driver by default in x86 builds.

add CONFIG_XEN_BLKDEV_TAP2=y to buildconfigs/linux-defconfig_xen_ia64.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Mon Jun 29 12:09:16 2009 +0900 (2009-06-29)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * arch/alpha/kernel/entry.S
ian@0 3 *
ian@0 4 * Kernel entry-points.
ian@0 5 */
ian@0 6
ian@0 7 #include <asm/asm-offsets.h>
ian@0 8 #include <asm/thread_info.h>
ian@0 9 #include <asm/pal.h>
ian@0 10 #include <asm/errno.h>
ian@0 11 #include <asm/unistd.h>
ian@0 12
ian@0 13 .text
ian@0 14 .set noat
ian@0 15
ian@0 16 /* Stack offsets. */
ian@0 17 #define SP_OFF 184
ian@0 18 #define SWITCH_STACK_SIZE 320
ian@0 19
ian@0 20 /*
ian@0 21 * This defines the normal kernel pt-regs layout.
ian@0 22 *
ian@0 23 * regs 9-15 preserved by C code
ian@0 24 * regs 16-18 saved by PAL-code
ian@0 25 * regs 29-30 saved and set up by PAL-code
ian@0 26 * JRP - Save regs 16-18 in a special area of the stack, so that
ian@0 27 * the palcode-provided values are available to the signal handler.
ian@0 28 */
ian@0 29
ian@0 30 #define SAVE_ALL \
ian@0 31 subq $sp, SP_OFF, $sp; \
ian@0 32 stq $0, 0($sp); \
ian@0 33 stq $1, 8($sp); \
ian@0 34 stq $2, 16($sp); \
ian@0 35 stq $3, 24($sp); \
ian@0 36 stq $4, 32($sp); \
ian@0 37 stq $28, 144($sp); \
ian@0 38 lda $2, alpha_mv; \
ian@0 39 stq $5, 40($sp); \
ian@0 40 stq $6, 48($sp); \
ian@0 41 stq $7, 56($sp); \
ian@0 42 stq $8, 64($sp); \
ian@0 43 stq $19, 72($sp); \
ian@0 44 stq $20, 80($sp); \
ian@0 45 stq $21, 88($sp); \
ian@0 46 ldq $2, HAE_CACHE($2); \
ian@0 47 stq $22, 96($sp); \
ian@0 48 stq $23, 104($sp); \
ian@0 49 stq $24, 112($sp); \
ian@0 50 stq $25, 120($sp); \
ian@0 51 stq $26, 128($sp); \
ian@0 52 stq $27, 136($sp); \
ian@0 53 stq $2, 152($sp); \
ian@0 54 stq $16, 160($sp); \
ian@0 55 stq $17, 168($sp); \
ian@0 56 stq $18, 176($sp)
ian@0 57
ian@0 58 #define RESTORE_ALL \
ian@0 59 lda $19, alpha_mv; \
ian@0 60 ldq $0, 0($sp); \
ian@0 61 ldq $1, 8($sp); \
ian@0 62 ldq $2, 16($sp); \
ian@0 63 ldq $3, 24($sp); \
ian@0 64 ldq $21, 152($sp); \
ian@0 65 ldq $20, HAE_CACHE($19); \
ian@0 66 ldq $4, 32($sp); \
ian@0 67 ldq $5, 40($sp); \
ian@0 68 ldq $6, 48($sp); \
ian@0 69 ldq $7, 56($sp); \
ian@0 70 subq $20, $21, $20; \
ian@0 71 ldq $8, 64($sp); \
ian@0 72 beq $20, 99f; \
ian@0 73 ldq $20, HAE_REG($19); \
ian@0 74 stq $21, HAE_CACHE($19); \
ian@0 75 stq $21, 0($20); \
ian@0 76 ldq $0, 0($sp); \
ian@0 77 ldq $1, 8($sp); \
ian@0 78 99:; \
ian@0 79 ldq $19, 72($sp); \
ian@0 80 ldq $20, 80($sp); \
ian@0 81 ldq $21, 88($sp); \
ian@0 82 ldq $22, 96($sp); \
ian@0 83 ldq $23, 104($sp); \
ian@0 84 ldq $24, 112($sp); \
ian@0 85 ldq $25, 120($sp); \
ian@0 86 ldq $26, 128($sp); \
ian@0 87 ldq $27, 136($sp); \
ian@0 88 ldq $28, 144($sp); \
ian@0 89 addq $sp, SP_OFF, $sp
ian@0 90
ian@0 91 /*
ian@0 92 * Non-syscall kernel entry points.
ian@0 93 */
ian@0 94
ian@0 95 .align 4
ian@0 96 .globl entInt
ian@0 97 .ent entInt
ian@0 98 entInt:
ian@0 99 SAVE_ALL
ian@0 100 lda $8, 0x3fff
ian@0 101 lda $26, ret_from_sys_call
ian@0 102 bic $sp, $8, $8
ian@0 103 mov $sp, $19
ian@0 104 jsr $31, do_entInt
ian@0 105 .end entInt
ian@0 106
ian@0 107 .align 4
ian@0 108 .globl entArith
ian@0 109 .ent entArith
ian@0 110 entArith:
ian@0 111 SAVE_ALL
ian@0 112 lda $8, 0x3fff
ian@0 113 lda $26, ret_from_sys_call
ian@0 114 bic $sp, $8, $8
ian@0 115 mov $sp, $18
ian@0 116 jsr $31, do_entArith
ian@0 117 .end entArith
ian@0 118
ian@0 119 .align 4
ian@0 120 .globl entMM
ian@0 121 .ent entMM
ian@0 122 entMM:
ian@0 123 SAVE_ALL
ian@0 124 /* save $9 - $15 so the inline exception code can manipulate them. */
ian@0 125 subq $sp, 56, $sp
ian@0 126 stq $9, 0($sp)
ian@0 127 stq $10, 8($sp)
ian@0 128 stq $11, 16($sp)
ian@0 129 stq $12, 24($sp)
ian@0 130 stq $13, 32($sp)
ian@0 131 stq $14, 40($sp)
ian@0 132 stq $15, 48($sp)
ian@0 133 addq $sp, 56, $19
ian@0 134 /* handle the fault */
ian@0 135 lda $8, 0x3fff
ian@0 136 bic $sp, $8, $8
ian@0 137 jsr $26, do_page_fault
ian@0 138 /* reload the registers after the exception code played. */
ian@0 139 ldq $9, 0($sp)
ian@0 140 ldq $10, 8($sp)
ian@0 141 ldq $11, 16($sp)
ian@0 142 ldq $12, 24($sp)
ian@0 143 ldq $13, 32($sp)
ian@0 144 ldq $14, 40($sp)
ian@0 145 ldq $15, 48($sp)
ian@0 146 addq $sp, 56, $sp
ian@0 147 /* finish up the syscall as normal. */
ian@0 148 br ret_from_sys_call
ian@0 149 .end entMM
ian@0 150
ian@0 151 .align 4
ian@0 152 .globl entIF
ian@0 153 .ent entIF
ian@0 154 entIF:
ian@0 155 SAVE_ALL
ian@0 156 lda $8, 0x3fff
ian@0 157 lda $26, ret_from_sys_call
ian@0 158 bic $sp, $8, $8
ian@0 159 mov $sp, $17
ian@0 160 jsr $31, do_entIF
ian@0 161 .end entIF
ian@0 162
ian@0 163 .align 4
ian@0 164 .globl entUna
ian@0 165 .ent entUna
ian@0 166 entUna:
ian@0 167 lda $sp, -256($sp)
ian@0 168 stq $0, 0($sp)
ian@0 169 ldq $0, 256($sp) /* get PS */
ian@0 170 stq $1, 8($sp)
ian@0 171 stq $2, 16($sp)
ian@0 172 stq $3, 24($sp)
ian@0 173 and $0, 8, $0 /* user mode? */
ian@0 174 stq $4, 32($sp)
ian@0 175 bne $0, entUnaUser /* yup -> do user-level unaligned fault */
ian@0 176 stq $5, 40($sp)
ian@0 177 stq $6, 48($sp)
ian@0 178 stq $7, 56($sp)
ian@0 179 stq $8, 64($sp)
ian@0 180 stq $9, 72($sp)
ian@0 181 stq $10, 80($sp)
ian@0 182 stq $11, 88($sp)
ian@0 183 stq $12, 96($sp)
ian@0 184 stq $13, 104($sp)
ian@0 185 stq $14, 112($sp)
ian@0 186 stq $15, 120($sp)
ian@0 187 /* 16-18 PAL-saved */
ian@0 188 stq $19, 152($sp)
ian@0 189 stq $20, 160($sp)
ian@0 190 stq $21, 168($sp)
ian@0 191 stq $22, 176($sp)
ian@0 192 stq $23, 184($sp)
ian@0 193 stq $24, 192($sp)
ian@0 194 stq $25, 200($sp)
ian@0 195 stq $26, 208($sp)
ian@0 196 stq $27, 216($sp)
ian@0 197 stq $28, 224($sp)
ian@0 198 mov $sp, $19
ian@0 199 stq $gp, 232($sp)
ian@0 200 lda $8, 0x3fff
ian@0 201 stq $31, 248($sp)
ian@0 202 bic $sp, $8, $8
ian@0 203 jsr $26, do_entUna
ian@0 204 ldq $0, 0($sp)
ian@0 205 ldq $1, 8($sp)
ian@0 206 ldq $2, 16($sp)
ian@0 207 ldq $3, 24($sp)
ian@0 208 ldq $4, 32($sp)
ian@0 209 ldq $5, 40($sp)
ian@0 210 ldq $6, 48($sp)
ian@0 211 ldq $7, 56($sp)
ian@0 212 ldq $8, 64($sp)
ian@0 213 ldq $9, 72($sp)
ian@0 214 ldq $10, 80($sp)
ian@0 215 ldq $11, 88($sp)
ian@0 216 ldq $12, 96($sp)
ian@0 217 ldq $13, 104($sp)
ian@0 218 ldq $14, 112($sp)
ian@0 219 ldq $15, 120($sp)
ian@0 220 /* 16-18 PAL-saved */
ian@0 221 ldq $19, 152($sp)
ian@0 222 ldq $20, 160($sp)
ian@0 223 ldq $21, 168($sp)
ian@0 224 ldq $22, 176($sp)
ian@0 225 ldq $23, 184($sp)
ian@0 226 ldq $24, 192($sp)
ian@0 227 ldq $25, 200($sp)
ian@0 228 ldq $26, 208($sp)
ian@0 229 ldq $27, 216($sp)
ian@0 230 ldq $28, 224($sp)
ian@0 231 ldq $gp, 232($sp)
ian@0 232 lda $sp, 256($sp)
ian@0 233 call_pal PAL_rti
ian@0 234 .end entUna
ian@0 235
ian@0 236 .align 4
ian@0 237 .ent entUnaUser
ian@0 238 entUnaUser:
ian@0 239 ldq $0, 0($sp) /* restore original $0 */
ian@0 240 lda $sp, 256($sp) /* pop entUna's stack frame */
ian@0 241 SAVE_ALL /* setup normal kernel stack */
ian@0 242 lda $sp, -56($sp)
ian@0 243 stq $9, 0($sp)
ian@0 244 stq $10, 8($sp)
ian@0 245 stq $11, 16($sp)
ian@0 246 stq $12, 24($sp)
ian@0 247 stq $13, 32($sp)
ian@0 248 stq $14, 40($sp)
ian@0 249 stq $15, 48($sp)
ian@0 250 lda $8, 0x3fff
ian@0 251 addq $sp, 56, $19
ian@0 252 bic $sp, $8, $8
ian@0 253 jsr $26, do_entUnaUser
ian@0 254 ldq $9, 0($sp)
ian@0 255 ldq $10, 8($sp)
ian@0 256 ldq $11, 16($sp)
ian@0 257 ldq $12, 24($sp)
ian@0 258 ldq $13, 32($sp)
ian@0 259 ldq $14, 40($sp)
ian@0 260 ldq $15, 48($sp)
ian@0 261 lda $sp, 56($sp)
ian@0 262 br ret_from_sys_call
ian@0 263 .end entUnaUser
ian@0 264
ian@0 265 .align 4
ian@0 266 .globl entDbg
ian@0 267 .ent entDbg
ian@0 268 entDbg:
ian@0 269 SAVE_ALL
ian@0 270 lda $8, 0x3fff
ian@0 271 lda $26, ret_from_sys_call
ian@0 272 bic $sp, $8, $8
ian@0 273 mov $sp, $16
ian@0 274 jsr $31, do_entDbg
ian@0 275 .end entDbg
ian@0 276
ian@0 277 /*
ian@0 278 * The system call entry point is special. Most importantly, it looks
ian@0 279 * like a function call to userspace as far as clobbered registers. We
ian@0 280 * do preserve the argument registers (for syscall restarts) and $26
ian@0 281 * (for leaf syscall functions).
ian@0 282 *
ian@0 283 * So much for theory. We don't take advantage of this yet.
ian@0 284 *
ian@0 285 * Note that a0-a2 are not saved by PALcode as with the other entry points.
ian@0 286 */
ian@0 287
ian@0 288 .align 4
ian@0 289 .globl entSys
ian@0 290 .globl ret_from_sys_call
ian@0 291 .ent entSys
ian@0 292 entSys:
ian@0 293 SAVE_ALL
ian@0 294 lda $8, 0x3fff
ian@0 295 bic $sp, $8, $8
ian@0 296 lda $4, NR_SYSCALLS($31)
ian@0 297 stq $16, SP_OFF+24($sp)
ian@0 298 lda $5, sys_call_table
ian@0 299 lda $27, sys_ni_syscall
ian@0 300 cmpult $0, $4, $4
ian@0 301 ldl $3, TI_FLAGS($8)
ian@0 302 stq $17, SP_OFF+32($sp)
ian@0 303 s8addq $0, $5, $5
ian@0 304 stq $18, SP_OFF+40($sp)
ian@0 305 blbs $3, strace
ian@0 306 beq $4, 1f
ian@0 307 ldq $27, 0($5)
ian@0 308 1: jsr $26, ($27), alpha_ni_syscall
ian@0 309 ldgp $gp, 0($26)
ian@0 310 blt $0, $syscall_error /* the call failed */
ian@0 311 stq $0, 0($sp)
ian@0 312 stq $31, 72($sp) /* a3=0 => no error */
ian@0 313
ian@0 314 .align 4
ian@0 315 ret_from_sys_call:
ian@0 316 cmovne $26, 0, $19 /* $19 = 0 => non-restartable */
ian@0 317 ldq $0, SP_OFF($sp)
ian@0 318 and $0, 8, $0
ian@0 319 beq $0, restore_all
ian@0 320 ret_from_reschedule:
ian@0 321 /* Make sure need_resched and sigpending don't change between
ian@0 322 sampling and the rti. */
ian@0 323 lda $16, 7
ian@0 324 call_pal PAL_swpipl
ian@0 325 ldl $5, TI_FLAGS($8)
ian@0 326 and $5, _TIF_WORK_MASK, $2
ian@0 327 bne $5, work_pending
ian@0 328 restore_all:
ian@0 329 RESTORE_ALL
ian@0 330 call_pal PAL_rti
ian@0 331
ian@0 332 .align 3
ian@0 333 $syscall_error:
ian@0 334 /*
ian@0 335 * Some system calls (e.g., ptrace) can return arbitrary
ian@0 336 * values which might normally be mistaken as error numbers.
ian@0 337 * Those functions must zero $0 (v0) directly in the stack
ian@0 338 * frame to indicate that a negative return value wasn't an
ian@0 339 * error number..
ian@0 340 */
ian@0 341 ldq $19, 0($sp) /* old syscall nr (zero if success) */
ian@0 342 beq $19, $ret_success
ian@0 343
ian@0 344 ldq $20, 72($sp) /* .. and this a3 */
ian@0 345 subq $31, $0, $0 /* with error in v0 */
ian@0 346 addq $31, 1, $1 /* set a3 for errno return */
ian@0 347 stq $0, 0($sp)
ian@0 348 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
ian@0 349 stq $1, 72($sp) /* a3 for return */
ian@0 350 br ret_from_sys_call
ian@0 351
ian@0 352 $ret_success:
ian@0 353 stq $0, 0($sp)
ian@0 354 stq $31, 72($sp) /* a3=0 => no error */
ian@0 355 br ret_from_sys_call
ian@0 356 .end entSys
ian@0 357
ian@0 358 /*
ian@0 359 * Do all cleanup when returning from all interrupts and system calls.
ian@0 360 *
ian@0 361 * Arguments:
ian@0 362 * $5: TI_FLAGS.
ian@0 363 * $8: current.
ian@0 364 * $19: The old syscall number, or zero if this is not a return
ian@0 365 * from a syscall that errored and is possibly restartable.
ian@0 366 * $20: Error indication.
ian@0 367 */
ian@0 368
ian@0 369 .align 4
ian@0 370 .ent work_pending
ian@0 371 work_pending:
ian@0 372 and $5, _TIF_NEED_RESCHED, $2
ian@0 373 beq $2, $work_notifysig
ian@0 374
ian@0 375 $work_resched:
ian@0 376 subq $sp, 16, $sp
ian@0 377 stq $19, 0($sp) /* save syscall nr */
ian@0 378 stq $20, 8($sp) /* and error indication (a3) */
ian@0 379 jsr $26, schedule
ian@0 380 ldq $19, 0($sp)
ian@0 381 ldq $20, 8($sp)
ian@0 382 addq $sp, 16, $sp
ian@0 383 /* Make sure need_resched and sigpending don't change between
ian@0 384 sampling and the rti. */
ian@0 385 lda $16, 7
ian@0 386 call_pal PAL_swpipl
ian@0 387 ldl $5, TI_FLAGS($8)
ian@0 388 and $5, _TIF_WORK_MASK, $2
ian@0 389 beq $2, restore_all
ian@0 390 and $5, _TIF_NEED_RESCHED, $2
ian@0 391 bne $2, $work_resched
ian@0 392
ian@0 393 $work_notifysig:
ian@0 394 mov $sp, $17
ian@0 395 br $1, do_switch_stack
ian@0 396 mov $5, $21
ian@0 397 mov $sp, $18
ian@0 398 mov $31, $16
ian@0 399 jsr $26, do_notify_resume
ian@0 400 bsr $1, undo_switch_stack
ian@0 401 br restore_all
ian@0 402 .end work_pending
ian@0 403
ian@0 404 /*
ian@0 405 * PTRACE syscall handler
ian@0 406 */
ian@0 407
ian@0 408 .align 4
ian@0 409 .ent strace
ian@0 410 strace:
ian@0 411 /* set up signal stack, call syscall_trace */
ian@0 412 bsr $1, do_switch_stack
ian@0 413 jsr $26, syscall_trace
ian@0 414 bsr $1, undo_switch_stack
ian@0 415
ian@0 416 /* get the system call number and the arguments back.. */
ian@0 417 ldq $0, 0($sp)
ian@0 418 ldq $16, SP_OFF+24($sp)
ian@0 419 ldq $17, SP_OFF+32($sp)
ian@0 420 ldq $18, SP_OFF+40($sp)
ian@0 421 ldq $19, 72($sp)
ian@0 422 ldq $20, 80($sp)
ian@0 423 ldq $21, 88($sp)
ian@0 424
ian@0 425 /* get the system call pointer.. */
ian@0 426 lda $1, NR_SYSCALLS($31)
ian@0 427 lda $2, sys_call_table
ian@0 428 lda $27, alpha_ni_syscall
ian@0 429 cmpult $0, $1, $1
ian@0 430 s8addq $0, $2, $2
ian@0 431 beq $1, 1f
ian@0 432 ldq $27, 0($2)
ian@0 433 1: jsr $26, ($27), sys_gettimeofday
ian@0 434 ldgp $gp, 0($26)
ian@0 435
ian@0 436 /* check return.. */
ian@0 437 blt $0, $strace_error /* the call failed */
ian@0 438 stq $31, 72($sp) /* a3=0 => no error */
ian@0 439 $strace_success:
ian@0 440 stq $0, 0($sp) /* save return value */
ian@0 441
ian@0 442 bsr $1, do_switch_stack
ian@0 443 jsr $26, syscall_trace
ian@0 444 bsr $1, undo_switch_stack
ian@0 445 br $31, ret_from_sys_call
ian@0 446
ian@0 447 .align 3
ian@0 448 $strace_error:
ian@0 449 ldq $19, 0($sp) /* old syscall nr (zero if success) */
ian@0 450 beq $19, $strace_success
ian@0 451 ldq $20, 72($sp) /* .. and this a3 */
ian@0 452
ian@0 453 subq $31, $0, $0 /* with error in v0 */
ian@0 454 addq $31, 1, $1 /* set a3 for errno return */
ian@0 455 stq $0, 0($sp)
ian@0 456 stq $1, 72($sp) /* a3 for return */
ian@0 457
ian@0 458 bsr $1, do_switch_stack
ian@0 459 mov $19, $9 /* save old syscall number */
ian@0 460 mov $20, $10 /* save old a3 */
ian@0 461 jsr $26, syscall_trace
ian@0 462 mov $9, $19
ian@0 463 mov $10, $20
ian@0 464 bsr $1, undo_switch_stack
ian@0 465
ian@0 466 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
ian@0 467 br ret_from_sys_call
ian@0 468 .end strace
ian@0 469
ian@0 470 /*
ian@0 471 * Save and restore the switch stack -- aka the balance of the user context.
ian@0 472 */
ian@0 473
ian@0 474 .align 4
ian@0 475 .ent do_switch_stack
ian@0 476 do_switch_stack:
ian@0 477 lda $sp, -SWITCH_STACK_SIZE($sp)
ian@0 478 stq $9, 0($sp)
ian@0 479 stq $10, 8($sp)
ian@0 480 stq $11, 16($sp)
ian@0 481 stq $12, 24($sp)
ian@0 482 stq $13, 32($sp)
ian@0 483 stq $14, 40($sp)
ian@0 484 stq $15, 48($sp)
ian@0 485 stq $26, 56($sp)
ian@0 486 stt $f0, 64($sp)
ian@0 487 stt $f1, 72($sp)
ian@0 488 stt $f2, 80($sp)
ian@0 489 stt $f3, 88($sp)
ian@0 490 stt $f4, 96($sp)
ian@0 491 stt $f5, 104($sp)
ian@0 492 stt $f6, 112($sp)
ian@0 493 stt $f7, 120($sp)
ian@0 494 stt $f8, 128($sp)
ian@0 495 stt $f9, 136($sp)
ian@0 496 stt $f10, 144($sp)
ian@0 497 stt $f11, 152($sp)
ian@0 498 stt $f12, 160($sp)
ian@0 499 stt $f13, 168($sp)
ian@0 500 stt $f14, 176($sp)
ian@0 501 stt $f15, 184($sp)
ian@0 502 stt $f16, 192($sp)
ian@0 503 stt $f17, 200($sp)
ian@0 504 stt $f18, 208($sp)
ian@0 505 stt $f19, 216($sp)
ian@0 506 stt $f20, 224($sp)
ian@0 507 stt $f21, 232($sp)
ian@0 508 stt $f22, 240($sp)
ian@0 509 stt $f23, 248($sp)
ian@0 510 stt $f24, 256($sp)
ian@0 511 stt $f25, 264($sp)
ian@0 512 stt $f26, 272($sp)
ian@0 513 stt $f27, 280($sp)
ian@0 514 mf_fpcr $f0 # get fpcr
ian@0 515 stt $f28, 288($sp)
ian@0 516 stt $f29, 296($sp)
ian@0 517 stt $f30, 304($sp)
ian@0 518 stt $f0, 312($sp) # save fpcr in slot of $f31
ian@0 519 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
ian@0 520 ret $31, ($1), 1
ian@0 521 .end do_switch_stack
ian@0 522
ian@0 523 .align 4
ian@0 524 .ent undo_switch_stack
ian@0 525 undo_switch_stack:
ian@0 526 ldq $9, 0($sp)
ian@0 527 ldq $10, 8($sp)
ian@0 528 ldq $11, 16($sp)
ian@0 529 ldq $12, 24($sp)
ian@0 530 ldq $13, 32($sp)
ian@0 531 ldq $14, 40($sp)
ian@0 532 ldq $15, 48($sp)
ian@0 533 ldq $26, 56($sp)
ian@0 534 ldt $f30, 312($sp) # get saved fpcr
ian@0 535 ldt $f0, 64($sp)
ian@0 536 ldt $f1, 72($sp)
ian@0 537 ldt $f2, 80($sp)
ian@0 538 ldt $f3, 88($sp)
ian@0 539 mt_fpcr $f30 # install saved fpcr
ian@0 540 ldt $f4, 96($sp)
ian@0 541 ldt $f5, 104($sp)
ian@0 542 ldt $f6, 112($sp)
ian@0 543 ldt $f7, 120($sp)
ian@0 544 ldt $f8, 128($sp)
ian@0 545 ldt $f9, 136($sp)
ian@0 546 ldt $f10, 144($sp)
ian@0 547 ldt $f11, 152($sp)
ian@0 548 ldt $f12, 160($sp)
ian@0 549 ldt $f13, 168($sp)
ian@0 550 ldt $f14, 176($sp)
ian@0 551 ldt $f15, 184($sp)
ian@0 552 ldt $f16, 192($sp)
ian@0 553 ldt $f17, 200($sp)
ian@0 554 ldt $f18, 208($sp)
ian@0 555 ldt $f19, 216($sp)
ian@0 556 ldt $f20, 224($sp)
ian@0 557 ldt $f21, 232($sp)
ian@0 558 ldt $f22, 240($sp)
ian@0 559 ldt $f23, 248($sp)
ian@0 560 ldt $f24, 256($sp)
ian@0 561 ldt $f25, 264($sp)
ian@0 562 ldt $f26, 272($sp)
ian@0 563 ldt $f27, 280($sp)
ian@0 564 ldt $f28, 288($sp)
ian@0 565 ldt $f29, 296($sp)
ian@0 566 ldt $f30, 304($sp)
ian@0 567 lda $sp, SWITCH_STACK_SIZE($sp)
ian@0 568 ret $31, ($1), 1
ian@0 569 .end undo_switch_stack
ian@0 570
ian@0 571 /*
ian@0 572 * The meat of the context switch code.
ian@0 573 */
ian@0 574
ian@0 575 .align 4
ian@0 576 .globl alpha_switch_to
ian@0 577 .ent alpha_switch_to
ian@0 578 alpha_switch_to:
ian@0 579 .prologue 0
ian@0 580 bsr $1, do_switch_stack
ian@0 581 call_pal PAL_swpctx
ian@0 582 lda $8, 0x3fff
ian@0 583 bsr $1, undo_switch_stack
ian@0 584 bic $sp, $8, $8
ian@0 585 mov $17, $0
ian@0 586 ret
ian@0 587 .end alpha_switch_to
ian@0 588
ian@0 589 /*
ian@0 590 * New processes begin life here.
ian@0 591 */
ian@0 592
ian@0 593 .globl ret_from_fork
ian@0 594 .align 4
ian@0 595 .ent ret_from_fork
ian@0 596 ret_from_fork:
ian@0 597 lda $26, ret_from_sys_call
ian@0 598 mov $17, $16
ian@0 599 jmp $31, schedule_tail
ian@0 600 .end ret_from_fork
ian@0 601
ian@0 602 /*
ian@0 603 * kernel_thread(fn, arg, clone_flags)
ian@0 604 */
ian@0 605 .align 4
ian@0 606 .globl kernel_thread
ian@0 607 .ent kernel_thread
ian@0 608 kernel_thread:
ian@0 609 /* We can be called from a module. */
ian@0 610 ldgp $gp, 0($27)
ian@0 611 .prologue 1
ian@0 612 subq $sp, SP_OFF+6*8, $sp
ian@0 613 br $1, 2f /* load start address */
ian@0 614
ian@0 615 /* We've now "returned" from a fake system call. */
ian@0 616 unop
ian@0 617 blt $0, 1f /* error? */
ian@0 618 ldi $1, 0x3fff
ian@0 619 beq $20, 1f /* parent or child? */
ian@0 620
ian@0 621 bic $sp, $1, $8 /* in child. */
ian@0 622 jsr $26, ($27)
ian@0 623 ldgp $gp, 0($26)
ian@0 624 mov $0, $16
ian@0 625 mov $31, $26
ian@0 626 jmp $31, sys_exit
ian@0 627
ian@0 628 1: ret /* in parent. */
ian@0 629
ian@0 630 .align 4
ian@0 631 2: /* Fake a system call stack frame, as we can't do system calls
ian@0 632 from kernel space. Note that we store FN and ARG as they
ian@0 633 need to be set up in the child for the call. Also store $8
ian@0 634 and $26 for use in the parent. */
ian@0 635 stq $31, SP_OFF($sp) /* ps */
ian@0 636 stq $1, SP_OFF+8($sp) /* pc */
ian@0 637 stq $gp, SP_OFF+16($sp) /* gp */
ian@0 638 stq $16, 136($sp) /* $27; FN for child */
ian@0 639 stq $17, SP_OFF+24($sp) /* $16; ARG for child */
ian@0 640 stq $8, 64($sp) /* $8 */
ian@0 641 stq $26, 128($sp) /* $26 */
ian@0 642 /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
ian@0 643 ldq $2, alpha_mv+HAE_CACHE
ian@0 644 stq $2, 152($sp) /* HAE */
ian@0 645
ian@0 646 /* Shuffle FLAGS to the front; add CLONE_VM. */
ian@0 647 ldi $1, CLONE_VM|CLONE_UNTRACED
ian@0 648 or $18, $1, $16
ian@0 649 bsr $26, sys_clone
ian@0 650
ian@0 651 /* We don't actually care for a3 success widgetry in the kernel.
ian@0 652 Not for positive errno values. */
ian@0 653 stq $0, 0($sp) /* $0 */
ian@0 654 br restore_all
ian@0 655 .end kernel_thread
ian@0 656
ian@0 657 /*
ian@0 658 * execve(path, argv, envp)
ian@0 659 */
ian@0 660 .align 4
ian@0 661 .globl execve
ian@0 662 .ent execve
ian@0 663 execve:
ian@0 664 /* We can be called from a module. */
ian@0 665 ldgp $gp, 0($27)
ian@0 666 lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
ian@0 667 .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0
ian@0 668 stq $26, 0($sp)
ian@0 669 stq $16, 8($sp)
ian@0 670 stq $17, 16($sp)
ian@0 671 stq $18, 24($sp)
ian@0 672 .prologue 1
ian@0 673
ian@0 674 lda $16, 32($sp)
ian@0 675 lda $17, 0
ian@0 676 lda $18, SIZEOF_PT_REGS
ian@0 677 bsr $26, memset !samegp
ian@0 678
ian@0 679 /* Avoid the HAE being gratuitously wrong, which would cause us
ian@0 680 to do the whole turn off interrupts thing and restore it. */
ian@0 681 ldq $2, alpha_mv+HAE_CACHE
ian@0 682 stq $2, 152+32($sp)
ian@0 683
ian@0 684 ldq $16, 8($sp)
ian@0 685 ldq $17, 16($sp)
ian@0 686 ldq $18, 24($sp)
ian@0 687 lda $19, 32($sp)
ian@0 688 bsr $26, do_execve !samegp
ian@0 689
ian@0 690 ldq $26, 0($sp)
ian@0 691 bne $0, 1f /* error! */
ian@0 692
ian@0 693 /* Move the temporary pt_regs struct from its current location
ian@0 694 to the top of the kernel stack frame. See copy_thread for
ian@0 695 details for a normal process. */
ian@0 696 lda $16, 0x4000 - SIZEOF_PT_REGS($8)
ian@0 697 lda $17, 32($sp)
ian@0 698 lda $18, SIZEOF_PT_REGS
ian@0 699 bsr $26, memmove !samegp
ian@0 700
ian@0 701 /* Take that over as our new stack frame and visit userland! */
ian@0 702 lda $sp, 0x4000 - SIZEOF_PT_REGS($8)
ian@0 703 br $31, ret_from_sys_call
ian@0 704
ian@0 705 1: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
ian@0 706 ret
ian@0 707 .end execve
ian@0 708
ian@0 709
ian@0 710 /*
ian@0 711 * Special system calls. Most of these are special in that they either
ian@0 712 * have to play switch_stack games or in some way use the pt_regs struct.
ian@0 713 */
ian@0 714 .align 4
ian@0 715 .globl sys_fork
ian@0 716 .ent sys_fork
ian@0 717 sys_fork:
ian@0 718 .prologue 0
ian@0 719 mov $sp, $21
ian@0 720 bsr $1, do_switch_stack
ian@0 721 bis $31, SIGCHLD, $16
ian@0 722 mov $31, $17
ian@0 723 mov $31, $18
ian@0 724 mov $31, $19
ian@0 725 mov $31, $20
ian@0 726 jsr $26, alpha_clone
ian@0 727 bsr $1, undo_switch_stack
ian@0 728 ret
ian@0 729 .end sys_fork
ian@0 730
ian@0 731 .align 4
ian@0 732 .globl sys_clone
ian@0 733 .ent sys_clone
ian@0 734 sys_clone:
ian@0 735 .prologue 0
ian@0 736 mov $sp, $21
ian@0 737 bsr $1, do_switch_stack
ian@0 738 /* $16, $17, $18, $19, $20 come from the user. */
ian@0 739 jsr $26, alpha_clone
ian@0 740 bsr $1, undo_switch_stack
ian@0 741 ret
ian@0 742 .end sys_clone
ian@0 743
ian@0 744 .align 4
ian@0 745 .globl sys_vfork
ian@0 746 .ent sys_vfork
ian@0 747 sys_vfork:
ian@0 748 .prologue 0
ian@0 749 mov $sp, $16
ian@0 750 bsr $1, do_switch_stack
ian@0 751 jsr $26, alpha_vfork
ian@0 752 bsr $1, undo_switch_stack
ian@0 753 ret
ian@0 754 .end sys_vfork
ian@0 755
ian@0 756 .align 4
ian@0 757 .globl sys_sigreturn
ian@0 758 .ent sys_sigreturn
ian@0 759 sys_sigreturn:
ian@0 760 .prologue 0
ian@0 761 mov $sp, $17
ian@0 762 lda $18, -SWITCH_STACK_SIZE($sp)
ian@0 763 lda $sp, -SWITCH_STACK_SIZE($sp)
ian@0 764 jsr $26, do_sigreturn
ian@0 765 br $1, undo_switch_stack
ian@0 766 br ret_from_sys_call
ian@0 767 .end sys_sigreturn
ian@0 768
ian@0 769 .align 4
ian@0 770 .globl sys_rt_sigreturn
ian@0 771 .ent sys_rt_sigreturn
ian@0 772 sys_rt_sigreturn:
ian@0 773 .prologue 0
ian@0 774 mov $sp, $17
ian@0 775 lda $18, -SWITCH_STACK_SIZE($sp)
ian@0 776 lda $sp, -SWITCH_STACK_SIZE($sp)
ian@0 777 jsr $26, do_rt_sigreturn
ian@0 778 br $1, undo_switch_stack
ian@0 779 br ret_from_sys_call
ian@0 780 .end sys_rt_sigreturn
ian@0 781
ian@0 782 .align 4
ian@0 783 .globl sys_sigsuspend
ian@0 784 .ent sys_sigsuspend
ian@0 785 sys_sigsuspend:
ian@0 786 .prologue 0
ian@0 787 mov $sp, $17
ian@0 788 br $1, do_switch_stack
ian@0 789 mov $sp, $18
ian@0 790 subq $sp, 16, $sp
ian@0 791 stq $26, 0($sp)
ian@0 792 jsr $26, do_sigsuspend
ian@0 793 ldq $26, 0($sp)
ian@0 794 lda $sp, SWITCH_STACK_SIZE+16($sp)
ian@0 795 ret
ian@0 796 .end sys_sigsuspend
ian@0 797
ian@0 798 .align 4
ian@0 799 .globl sys_rt_sigsuspend
ian@0 800 .ent sys_rt_sigsuspend
ian@0 801 sys_rt_sigsuspend:
ian@0 802 .prologue 0
ian@0 803 mov $sp, $18
ian@0 804 br $1, do_switch_stack
ian@0 805 mov $sp, $19
ian@0 806 subq $sp, 16, $sp
ian@0 807 stq $26, 0($sp)
ian@0 808 jsr $26, do_rt_sigsuspend
ian@0 809 ldq $26, 0($sp)
ian@0 810 lda $sp, SWITCH_STACK_SIZE+16($sp)
ian@0 811 ret
ian@0 812 .end sys_rt_sigsuspend
ian@0 813
ian@0 814 .align 4
ian@0 815 .globl sys_sethae
ian@0 816 .ent sys_sethae
ian@0 817 sys_sethae:
ian@0 818 .prologue 0
ian@0 819 stq $16, 152($sp)
ian@0 820 ret
ian@0 821 .end sys_sethae
ian@0 822
ian@0 823 .align 4
ian@0 824 .globl osf_getpriority
ian@0 825 .ent osf_getpriority
ian@0 826 osf_getpriority:
ian@0 827 lda $sp, -16($sp)
ian@0 828 stq $26, 0($sp)
ian@0 829 .prologue 0
ian@0 830
ian@0 831 jsr $26, sys_getpriority
ian@0 832
ian@0 833 ldq $26, 0($sp)
ian@0 834 blt $0, 1f
ian@0 835
ian@0 836 /* Return value is the unbiased priority, i.e. 20 - prio.
ian@0 837 This does result in negative return values, so signal
ian@0 838 no error by writing into the R0 slot. */
ian@0 839 lda $1, 20
ian@0 840 stq $31, 16($sp)
ian@0 841 subl $1, $0, $0
ian@0 842 unop
ian@0 843
ian@0 844 1: lda $sp, 16($sp)
ian@0 845 ret
ian@0 846 .end osf_getpriority
ian@0 847
ian@0 848 .align 4
ian@0 849 .globl sys_getxuid
ian@0 850 .ent sys_getxuid
ian@0 851 sys_getxuid:
ian@0 852 .prologue 0
ian@0 853 ldq $2, TI_TASK($8)
ian@0 854 ldl $0, TASK_UID($2)
ian@0 855 ldl $1, TASK_EUID($2)
ian@0 856 stq $1, 80($sp)
ian@0 857 ret
ian@0 858 .end sys_getxuid
ian@0 859
ian@0 860 .align 4
ian@0 861 .globl sys_getxgid
ian@0 862 .ent sys_getxgid
ian@0 863 sys_getxgid:
ian@0 864 .prologue 0
ian@0 865 ldq $2, TI_TASK($8)
ian@0 866 ldl $0, TASK_GID($2)
ian@0 867 ldl $1, TASK_EGID($2)
ian@0 868 stq $1, 80($sp)
ian@0 869 ret
ian@0 870 .end sys_getxgid
ian@0 871
ian@0 872 .align 4
ian@0 873 .globl sys_getxpid
ian@0 874 .ent sys_getxpid
ian@0 875 sys_getxpid:
ian@0 876 .prologue 0
ian@0 877 ldq $2, TI_TASK($8)
ian@0 878
ian@0 879 /* See linux/kernel/timer.c sys_getppid for discussion
ian@0 880 about this loop. */
ian@0 881 ldq $3, TASK_GROUP_LEADER($2)
ian@0 882 ldq $4, TASK_REAL_PARENT($3)
ian@0 883 ldl $0, TASK_TGID($2)
ian@0 884 1: ldl $1, TASK_TGID($4)
ian@0 885 #ifdef CONFIG_SMP
ian@0 886 mov $4, $5
ian@0 887 mb
ian@0 888 ldq $3, TASK_GROUP_LEADER($2)
ian@0 889 ldq $4, TASK_REAL_PARENT($3)
ian@0 890 cmpeq $4, $5, $5
ian@0 891 beq $5, 1b
ian@0 892 #endif
ian@0 893 stq $1, 80($sp)
ian@0 894 ret
ian@0 895 .end sys_getxpid
ian@0 896
ian@0 897 .align 4
ian@0 898 .globl sys_pipe
ian@0 899 .ent sys_pipe
ian@0 900 sys_pipe:
ian@0 901 lda $sp, -16($sp)
ian@0 902 stq $26, 0($sp)
ian@0 903 .prologue 0
ian@0 904
ian@0 905 lda $16, 8($sp)
ian@0 906 jsr $26, do_pipe
ian@0 907
ian@0 908 ldq $26, 0($sp)
ian@0 909 bne $0, 1f
ian@0 910
ian@0 911 /* The return values are in $0 and $20. */
ian@0 912 ldl $1, 12($sp)
ian@0 913 ldl $0, 8($sp)
ian@0 914
ian@0 915 stq $1, 80+16($sp)
ian@0 916 1: lda $sp, 16($sp)
ian@0 917 ret
ian@0 918 .end sys_pipe
ian@0 919
ian@0 920 .align 4
ian@0 921 .globl sys_ptrace
ian@0 922 .ent sys_ptrace
ian@0 923 sys_ptrace:
ian@0 924 .prologue 0
ian@0 925 mov $sp, $20
ian@0 926 jmp $31, do_sys_ptrace
ian@0 927 .end sys_ptrace
ian@0 928
ian@0 929 .align 4
ian@0 930 .globl sys_execve
ian@0 931 .ent sys_execve
ian@0 932 sys_execve:
ian@0 933 .prologue 0
ian@0 934 mov $sp, $19
ian@0 935 jmp $31, do_sys_execve
ian@0 936 .end sys_execve
ian@0 937
ian@0 938 .align 4
ian@0 939 .globl osf_sigprocmask
ian@0 940 .ent osf_sigprocmask
ian@0 941 osf_sigprocmask:
ian@0 942 .prologue 0
ian@0 943 mov $sp, $18
ian@0 944 jmp $31, do_osf_sigprocmask
ian@0 945 .end osf_sigprocmask
ian@0 946
ian@0 947 .align 4
ian@0 948 .globl alpha_ni_syscall
ian@0 949 .ent alpha_ni_syscall
ian@0 950 alpha_ni_syscall:
ian@0 951 .prologue 0
ian@0 952 /* Special because it also implements overflow handling via
ian@0 953 syscall number 0. And if you recall, zero is a special
ian@0 954 trigger for "not an error". Store large non-zero there. */
ian@0 955 lda $0, -ENOSYS
ian@0 956 unop
ian@0 957 stq $0, 0($sp)
ian@0 958 ret
ian@0 959 .end alpha_ni_syscall