ia64/linux-2.6.18-xen.hg

annotate arch/alpha/kernel/entry.S @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
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