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