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 84ia64_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} 102gw_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} 115gw_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 130ENTRY_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} 192END(break_sigtramp) 193 194ENTRY_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 231END(epc_sigtramp) 232 233 .align PAGE_SIZE 234 235 .text 236 237ENTRY_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} 3891: 390{ .mib 391 srlz.d 392 add out0=16,sp 393 br.call.sptk rp=syscall 394 ;; 395} 396 .global epc_syscall_return 397epc_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} 523epc_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 ;; 583END(epc_syscall) 584