1 /* $NetBSD: syscall_stubs.S,v 1.7 2023/10/06 11:45:16 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 Marcel Moolenaar 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <sys/syscall.h> 32 #include <sys/errno.h> 33 34 35 #include <machine/asm.h> 36 #undef VM_MAX_ADDRESS 37 38 #include "assym.h" 39 40 /* 41 * A process performs a syscall by performing an indirect call to the 42 * address stored in ar.k5. The contents of ar.pfs and rp should be 43 * saved prior to the syscall in r9 and r10 respectively. The kernel 44 * will restore these values on return. The value of gp is preserved 45 * across the call. This allows for small enough syscall stubs without 46 * getting too weird. 47 * The address in ar.k5 is the start of the EPC gateway page and also 48 * the syscall entry point. The syscall code in the gateway page is 49 * primarily responsible for increasing the privilege level, but will 50 * also make sure we have a reliable psr. 51 * 52 * A process defines: 53 * r8 - syscall number 54 * r9 - copy of ar.pfs 55 * r10 - copy of rp 56 * in0-in7 - syscall arguments 57 * 58 * A syscall returns: 59 * r8+r9 - syscall return value(s) 60 * r10 - syscall error flag 61 * ar.pfs - restored from r9 62 * rp - restored from r10 63 * gp - preserved 64 * 65 * The EPC syscall code defines: 66 * r11 - copy of psr.l 67 * r14 - Kernel memory stack 68 * r15 - Kernel register stack 69 * 70 * Also in the gateway page are the signal trampolines. As such, stacks 71 * don't have to be made executable per se. Since debuggers have a need 72 * to know about trampolines, we probably need to define a table of 73 * vectors or something along those lines so that debuggers can get the 74 * information they need and we have the freedom to move code around. 75 */ 76 77 /* XXX fix */ 78 #define syscall 0 79 #define SYS_sigreturn 0 80 81 .section .text.gateway, "ax" 82 .align PAGE_SIZE 83 .global ia64_gateway_page 84 ia64_gateway_page: 85 { .mmb 86 mov r14=ar.k7 // Memory stack 87 mov r15=ar.k6 // Register stack 88 epc 89 ;; 90 } 91 { .mlx 92 mov r11=psr 93 movl r31=epc_syscall 94 ;; 95 } 96 { .mib 97 rum psr.be 98 mov b7=r31 99 br b7 100 ;; 101 } 102 gw_ret: 103 { .mmi 104 mov ar.rnat=r22 105 ;; 106 mov ar.rsc=r24 107 mov ar.pfs=r20 108 } 109 { .mib 110 mov ar.fpsr=r25 111 mov b0=r18 112 br.sptk b6 113 ;; 114 } 115 gw_ret_ia32: 116 { .mmi 117 flushrs 118 nop 0 119 nop 0 120 ;; 121 } 122 { .mib 123 nop 0 124 nop 0 125 br.ia.sptk b6 126 ;; 127 } 128 129 130 ENTRY_NOPROFILE(break_sigtramp, 0) 131 { .mib 132 mov ar.rsc=0 133 cmp.ne p15,p0=0,gp 134 cover 135 ;; 136 } 137 { .mmi 138 flushrs 139 (p15) invala 140 add r16=16+UC_MCONTEXT+MC_SPECIAL,sp 141 ;; 142 } 143 { .mmi 144 mov r17=ar.bsp 145 mov r18=ar.rnat 146 add r14=40,r16 147 ;; 148 } 149 { .mmi 150 st8 [r14]=r17,64 // bspstore 151 (p15) mov ar.bspstore=gp 152 add r15=48,r16 153 ;; 154 } 155 { .mmi 156 st8 [r15]=r18 // rnat 157 st8 [r14]=r0 // ndirty 158 nop 0 159 ;; 160 } 161 { .mmi 162 alloc r14=ar.pfs, 0, 0, 3, 0 163 mov ar.rsc=15 164 mov out0=r8 165 ;; 166 } 167 { .mmi 168 ld8 r16=[r10],8 // function address 169 ;; 170 ld8 gp=[r10] // function's gp value 171 mov b7=r16 172 ;; 173 } 174 { .mib 175 mov out1=r9 176 add out2=16,sp 177 br.call.sptk rp=b7 178 ;; 179 } 180 { .mmi 181 mov r15=SYS_sigreturn 182 add out0=16,sp 183 break 0x100000 184 ;; 185 } 186 { .mmi 187 mov r15=SYS_exit 188 mov out0=ret0 189 break 0x100000 190 ;; 191 } 192 END(break_sigtramp) 193 194 ENTRY_NOPROFILE(epc_sigtramp, 0) 195 { .mmi 196 ld8 r16=[r10],8 // function address 197 mov ar.rsc=0 198 cmp.ne p15,p0=0,gp 199 ;; 200 } 201 { .mmi 202 (p15) invala 203 (p15) mov ar.bspstore=gp 204 mov b7=r16 205 ;; 206 } 207 { .mmi 208 alloc r14=ar.pfs, 0, 0, 3, 0 209 mov ar.rsc=15 210 nop 0 211 ;; 212 } 213 { .mii 214 ld8 gp=[r10] // function's gp value 215 mov out0=r8 216 mov out1=r9 217 } 218 { .mib 219 add out2=16,sp 220 nop 0 221 br.call.sptk rp=b7 222 ;; 223 } 224 add out0=16,sp 225 /* XXX fix */ 226 #if 0 227 CALLSYS_NOERROR(sigreturn) 228 mov out0=ret0 229 CALLSYS_NOERROR(exit) 230 #endif 231 END(epc_sigtramp) 232 233 .align PAGE_SIZE 234 235 .text 236 237 ENTRY_NOPROFILE(epc_syscall, 8) 238 .prologue 239 .unwabi @svr4, 'E' 240 .save rp, r0 241 .body 242 { .mmi 243 mov r16=ar.rsc 244 mov ar.rsc=0 245 nop 0 246 ;; 247 } 248 { .mmi 249 mov r18=ar.bspstore 250 ;; 251 mov r19=ar.rnat 252 dep r15=r18,r15,0,9 253 ;; 254 } 255 { .mmi 256 mov r21=ar.unat 257 add r30=-SIZEOF_TRAPFRAME,r14 258 mov r20=sp 259 ;; 260 } 261 { .mii 262 mov r17=r13 263 dep r30=0,r30,0,10 264 ;; 265 add sp=-16,r30 266 ;; 267 } 268 { .mmi 269 mov ar.bspstore=r15 270 ;; 271 mov ar.rnat=r19 272 add r31=8,r30 273 ;; 274 } 275 { .mmi 276 mov r13=ar.k4 277 mov r22=ar.fpsr 278 sub r29=r14,r30 279 } 280 { .mmi 281 mov r23=ar.bsp 282 mov ar.rsc=3 283 add r28=FRAME_SYSCALL,r0 284 ;; 285 } 286 { .mmi 287 st8 [r30]=r29,16 // tf_length 288 st8 [r31]=r28,16 // tf_flags 289 mov r24=rp 290 ;; 291 } 292 { .mmi 293 st8 [r30]=r20,16 // sp 294 st8 [r31]=r21,16 // unat 295 mov r25=pr 296 ;; 297 } 298 { .mmi 299 st8 [r30]=r10,16 // rp (syscall caller) 300 st8 [r31]=r25,16 // pr 301 mov r26=ar.pfs 302 ;; 303 } 304 { .mmi 305 st8 [r30]=r9,16 // pfs (syscall caller) 306 st8 [r31]=r18,16 // bspstore 307 sub r27=r23,r15 308 ;; 309 } 310 { .mmi 311 st8 [r30]=r19,16 // rnat 312 st8 [r31]=r0,16 // __spare 313 dep r11=-1,r11,44,1 // Set psr.bn=1 314 ;; 315 } 316 { .mmi 317 st8 [r30]=r17,16 // tp 318 st8 [r31]=r16,16 // rsc 319 dep r11=-1,r11,32,2 // Set psr.cpl=3 320 ;; 321 } 322 { .mmi 323 st8 [r30]=r22,16 // fpsr 324 st8 [r31]=r11,16 // psr 325 nop 0 326 ;; 327 } 328 { .mmi 329 st8 [r30]=r1,16 // gp 330 st8 [r31]=r27,16 // ndirty 331 nop 0 332 ;; 333 } 334 { .mmi 335 st8 [r30]=r26,16 // pfs (syscall stub) 336 st8 [r31]=r24,16 // rp (syscall stub) 337 nop 0 338 ;; 339 } 340 { .mmi 341 st8 [r30]=r0,80 // ifa 342 st8 [r31]=r0,80 // isr 343 nop 0 344 ;; 345 } 346 { .mmi 347 alloc r14=ar.pfs,0,0,8,0 348 st8 [r30]=r8,16 // syscall number (=r15) 349 nop 0 350 ;; 351 } 352 { .mmi 353 .mem.offset 0,0 354 st8.spill [r31]=r32,16 // arg0 (=r16) 355 .mem.offset 8,0 356 st8.spill [r30]=r33,16 // arg1 (=r17) 357 nop 0 358 ;; 359 } 360 { .mmi 361 .mem.offset 16,0 362 st8.spill [r31]=r34,16 // arg2 (=r18) 363 .mem.offset 24,0 364 st8.spill [r30]=r35,16 // arg3 (=r19) 365 nop 0 366 ;; 367 } 368 { .mmi 369 .mem.offset 32,0 370 st8.spill [r31]=r36,16 // arg4 (=r20) 371 .mem.offset 40,0 372 st8.spill [r30]=r37,16 // arg5 (=r21) 373 nop 0 374 ;; 375 } 376 { .mmi 377 .mem.offset 48,0 378 st8.spill [r31]=r38 // arg6 (=r22) 379 .mem.offset 56,0 380 st8.spill [r30]=r39 // arg7 (=r23) 381 nop 0 382 ;; 383 } 384 { .mlx 385 ssm psr.dfh|psr.ac 386 movl gp=__gp 387 ;; 388 } 389 1: 390 { .mib 391 srlz.d 392 add out0=16,sp 393 br.call.sptk rp=syscall 394 ;; 395 } 396 .global epc_syscall_return 397 epc_syscall_return: 398 { .mib 399 add out0=16,sp 400 nop 0 401 br.call.sptk rp=do_ast 402 ;; 403 } 404 { .mib 405 cmp4.eq p15,p0=ERESTART,r8 406 add r14=24,sp 407 (p15) br.spnt 1b // restart syscall 408 ;; 409 } 410 { .mmi 411 ld8 r14=[r14] // tf_flags 412 nop 0 413 nop 0 414 ;; 415 } 416 { .mib 417 nop 0 418 tbit.z p15,p0=r14,0 419 (p15) br.spnt exception_restore 420 ;; 421 } 422 { .mmi 423 alloc r31=ar.pfs,0,0,0,0 424 add r14=32,sp 425 add r15=16,sp 426 ;; 427 } 428 { .mmi 429 ld8 r31=[r15],24 // tf_length 430 ld8 r16=[r14],16 // sp 431 add sp=16,sp 432 ;; 433 } 434 { .mmi 435 ld8 r17=[r15],16 // unat (before) 436 ld8 r18=[r14],16 // rp (syscall caller) 437 add r31=r31,sp 438 ;; 439 } 440 { .mmi 441 ld8 r19=[r15],16 // pr 442 ld8 r20=[r14],16 // pfs (syscall caller) 443 nop 0 444 ;; 445 } 446 { .mmi 447 ld8 r21=[r15],24 // bspstore 448 ld8 r22=[r14],24 // rnat 449 mov pr=r19,0x1fffe 450 ;; 451 } 452 { .mmi 453 ld8 r23=[r15],16 // tp 454 ld8 r24=[r14],16 // rsc 455 nop 0 456 ;; 457 } 458 { .mmi 459 ld8 r25=[r15],16 // fpsr 460 ld8 r26=[r14],16 // psr 461 nop 0 462 ;; 463 } 464 { .mmi 465 ld8 gp=[r15],16 // gp 466 ld8 r27=[r14],16 // ndirty 467 tbit.z p14,p15=r26,34 // p14=ia64, p15=ia32 468 ;; 469 } 470 { .mmi 471 ld8 r28=[r15],56 // pfs (syscall stub) 472 ld8 r29=[r14],56 // rp (syscall stub) 473 shl r27=r27,16 474 ;; 475 } 476 { .mmi 477 ld8 r8=[r15],16 // r8 478 mov ar.rsc=r27 479 mov b6=r29 480 ;; 481 } 482 { .mmb 483 ld8 r9=[r14],40 // r9 484 ld8 r10=[r15],40 // r10 485 (p15) br.spnt epc_syscall_setup_ia32 486 ;; 487 } 488 { .mmi 489 loadrs 490 mov ar.k7=r31 491 mov sp=r16 492 ;; 493 } 494 { .mmi 495 mov r30=ar.bspstore 496 mov r14=ar.k5 497 mov ar.pfs=r28 498 ;; 499 } 500 { .mmi 501 mov ar.bspstore=r21 502 add r14=gw_ret-ia64_gateway_page,r14 503 dep r30=0,r30,0,13 // 8KB aligned. 504 ;; 505 } 506 { .mii 507 mov ar.k6=r30 508 mov r13=r23 509 nop 0 510 } 511 { .mmi 512 mov psr.l=r26 513 mov ar.unat=r17 514 nop 0 515 ;; 516 } 517 { .mib 518 srlz.d 519 mov b7=r14 520 br.ret.sptk b7 521 ;; 522 } 523 epc_syscall_setup_ia32: 524 { .mmi 525 loadrs 526 mov ar.k7=r31 527 mov sp=r16 528 ;; 529 } 530 { .mmi 531 mov r30=ar.bspstore 532 ;; 533 mov ar.unat=r17 534 dep r30=0,r30,0,13 // 8KB aligned 535 ;; 536 } 537 { .mmi 538 mov ar.k6=r30 539 mov ar.bspstore=r21 540 mov r11=r0 541 ;; 542 } 543 { .mmi 544 ld8 r16=[r14],64 545 ld8 r17=[r15],80 546 mov r13=r0 547 ;; 548 } 549 550 ld8 r24=[r14],32 551 ld8 r27=[r15],16 552 ;; 553 ld8 r28=[r14],16 554 ld8 r29=[r15],16 555 ;; 556 ld8 r30=[r14],40 557 ld8 r31=[r15],40 558 ;; 559 560 { .mmi 561 ld8 r2=[r14] 562 ld8 r3=[r15] 563 mov r14=r0 564 ;; 565 } 566 { .mmi 567 mov ar.csd=r2 568 mov ar.ssd=r3 569 mov r15=r0 570 ;; 571 } 572 573 mov r2=ar.k5 574 mov psr.l=r26 575 ;; 576 srlz.d 577 add r2=gw_ret_ia32-ia64_gateway_page,r2 578 ;; 579 mov ar.rsc=0 580 mov b7=r2 581 br.ret.sptk b7 582 ;; 583 END(epc_syscall) 584