1// Copyright 2023 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4// 5// System calls and other sys.stuff for ppc64, OpenBSD 6// System calls are implemented in libc/libpthread, this file 7// contains trampolines that convert from Go to C calling convention. 8// Some direct system call implementations currently remain. 9// 10 11#include "go_asm.h" 12#include "go_tls.h" 13#include "textflag.h" 14 15#define CLOCK_REALTIME $0 16#define CLOCK_MONOTONIC $3 17 18// mstart_stub is the first function executed on a new thread started by pthread_create. 19// It just does some low-level setup and then calls mstart. 20// Note: called with the C calling convention. 21TEXT runtime·mstart_stub(SB),NOSPLIT,$32 22 // R3 points to the m. 23 // We are already on m's g0 stack. 24 25 // Go relies on R0 being $0. 26 XOR R0, R0 27 28 // TODO(jsing): Save callee-save registers (R14-R31, F14-F31, V20-V31). 29 30 MOVD m_g0(R3), g 31 BL runtime·save_g(SB) 32 33 BL runtime·mstart(SB) 34 35 // TODO(jsing): Restore callee-save registers (R14-R31, F14-F31, V20-V31). 36 37 // Go is all done with this OS thread. 38 // Tell pthread everything is ok (we never join with this thread, so 39 // the value here doesn't really matter). 40 MOVD $0, R3 41 42 RET 43 44TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 45 MOVW sig+8(FP), R3 46 MOVD info+16(FP), R4 47 MOVD ctx+24(FP), R5 48 MOVD fn+0(FP), R12 49 MOVD R12, CTR 50 CALL (CTR) // Alignment for ELF ABI? 51 RET 52 53TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$16 54 // Go relies on R0 being $0 and we may have been executing non-Go code. 55 XOR R0, R0 56 57 // TODO(jsing): Save callee-save registers (R2, R14-R31, F14-F31). 58 // in the case of signal forwarding. 59 // Please refer to https://golang.org/issue/31827 . 60 61 // If called from an external code context, g will not be set. 62 BL runtime·load_g(SB) 63 64 BL runtime·sigtrampgo<ABIInternal>(SB) 65 66 // TODO(jsing): Restore callee-save registers. 67 68 RET 69 70// These trampolines help convert from Go calling convention to C calling convention. 71// They should be called with asmcgocall. 72// A pointer to the arguments is passed in R3. 73// A single int32 result is returned in R3. 74// (For more results, make an args/results structure.) 75TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$32 76 MOVD 0(R3), R3 // arg 1 - attr 77 CALL libc_pthread_attr_init(SB) 78 RET 79 80TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$32 81 MOVD 0(R3), R3 // arg 1 - attr 82 CALL libc_pthread_attr_destroy(SB) 83 RET 84 85TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$32 86 MOVD 8(R3), R4 // arg 2 - size 87 MOVD 0(R3), R3 // arg 1 - attr 88 CALL libc_pthread_attr_getstacksize(SB) 89 RET 90 91TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$32 92 MOVD 8(R3), R4 // arg 2 - state 93 MOVD 0(R3), R3 // arg 1 - attr 94 CALL libc_pthread_attr_setdetachstate(SB) 95 RET 96 97TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$32 98 MOVD 0(R3), R4 // arg 2 - attr 99 MOVD 8(R3), R5 // arg 3 - start 100 MOVD 16(R3), R6 // arg 4 - arg 101 102 MOVD R1, R15 103 SUB $64, R1 104 RLDCR $0, R1, $~15, R1 105 MOVD R1, R3 // arg 1 - &threadid (discard) 106 CALL libc_pthread_create(SB) 107 MOVD R15, R1 108 109 RET 110 111TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$32 112 MOVD 8(R3), R4 // arg 2 - signal (int64) 113 MOVD $0, R5 // arg 3 - tcb 114 MOVW 0(R3), R3 // arg 1 - tid 115 CALL libc_thrkill(SB) 116 RET 117 118TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$32 119 MOVW 8(R3), R4 // arg 2 - clock_id 120 MOVD 16(R3), R5 // arg 3 - abstime 121 MOVD 24(R3), R6 // arg 4 - lock 122 MOVD 32(R3), R7 // arg 5 - abort 123 MOVD 0(R3), R3 // arg 1 - id 124 CALL libc_thrsleep(SB) 125 RET 126 127TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$32 128 MOVW 8(R3), R4 // arg 2 - count 129 MOVD 0(R3), R3 // arg 1 - id 130 CALL libc_thrwakeup(SB) 131 RET 132 133TEXT runtime·exit_trampoline(SB),NOSPLIT,$32 134 MOVW 0(R3), R3 // arg 1 - status 135 CALL libc_exit(SB) 136 MOVD $0, R3 // crash on failure 137 MOVD R3, (R3) 138 RET 139 140TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$32 141 MOVD R3, R14 // pointer to args 142 CALL libc_getthrid(SB) 143 MOVW R3, 0(R14) // return value 144 RET 145 146TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$32 147 MOVD R3, R14 // pointer to args 148 CALL libc_getpid(SB) // arg 1 - pid 149 MOVW 0(R14), R4 // arg 2 - signal 150 CALL libc_kill(SB) 151 RET 152 153TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$32 154 CALL libc_sched_yield(SB) 155 RET 156 157TEXT runtime·mmap_trampoline(SB),NOSPLIT,$32 158 MOVD R3, R14 // pointer to args 159 MOVD 0(R14), R3 // arg 1 - addr 160 MOVD 8(R14), R4 // arg 2 - len 161 MOVW 16(R14), R5 // arg 3 - prot 162 MOVW 20(R14), R6 // arg 4 - flags 163 MOVW 24(R14), R7 // arg 5 - fid 164 MOVW 28(R14), R8 // arg 6 - offset 165 CALL libc_mmap(SB) 166 MOVD $0, R4 167 CMP R3, $-1 168 BNE noerr 169 CALL libc_errno(SB) 170 MOVW (R3), R4 // errno 171 MOVD $0, R3 172noerr: 173 MOVD R3, 32(R14) 174 MOVD R4, 40(R14) 175 RET 176 177TEXT runtime·munmap_trampoline(SB),NOSPLIT,$32 178 MOVD 8(R3), R4 // arg 2 - len 179 MOVD 0(R3), R3 // arg 1 - addr 180 CALL libc_munmap(SB) 181 CMP R3, $-1 182 BNE 3(PC) 183 MOVD $0, R3 // crash on failure 184 MOVD R3, (R3) 185 RET 186 187TEXT runtime·madvise_trampoline(SB),NOSPLIT,$32 188 MOVD 8(R3), R4 // arg 2 - len 189 MOVW 16(R3), R5 // arg 3 - advice 190 MOVD 0(R3), R3 // arg 1 - addr 191 CALL libc_madvise(SB) 192 // ignore failure - maybe pages are locked 193 RET 194 195TEXT runtime·open_trampoline(SB),NOSPLIT,$32 196 MOVW 8(R3), R4 // arg 2 - flags 197 MOVW 12(R3), R5 // arg 3 - mode 198 MOVD 0(R3), R3 // arg 1 - path 199 MOVD $0, R6 // varargs 200 CALL libc_open(SB) 201 RET 202 203TEXT runtime·close_trampoline(SB),NOSPLIT,$32 204 MOVW 0(R3), R3 // arg 1 - fd 205 CALL libc_close(SB) 206 RET 207 208TEXT runtime·read_trampoline(SB),NOSPLIT,$32 209 MOVD 8(R3), R4 // arg 2 - buf 210 MOVW 16(R3), R5 // arg 3 - count 211 MOVW 0(R3), R3 // arg 1 - fd (int32) 212 CALL libc_read(SB) 213 CMP R3, $-1 214 BNE noerr 215 CALL libc_errno(SB) 216 MOVW (R3), R3 // errno 217 NEG R3, R3 // caller expects negative errno value 218noerr: 219 RET 220 221TEXT runtime·write_trampoline(SB),NOSPLIT,$32 222 MOVD 8(R3), R4 // arg 2 - buf 223 MOVW 16(R3), R5 // arg 3 - count 224 MOVD 0(R3), R3 // arg 1 - fd (uintptr) 225 CALL libc_write(SB) 226 CMP R3, $-1 227 BNE noerr 228 CALL libc_errno(SB) 229 MOVW (R3), R3 // errno 230 NEG R3, R3 // caller expects negative errno value 231noerr: 232 RET 233 234TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$32 235 MOVW 8(R3), R4 // arg 2 - flags 236 MOVD 0(R3), R3 // arg 1 - filedes 237 CALL libc_pipe2(SB) 238 CMP R3, $-1 239 BNE noerr 240 CALL libc_errno(SB) 241 MOVW (R3), R3 // errno 242 NEG R3, R3 // caller expects negative errno value 243noerr: 244 RET 245 246TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$32 247 MOVD 8(R3), R4 // arg 2 - new 248 MOVD 16(R3), R5 // arg 3 - old 249 MOVW 0(R3), R3 // arg 1 - which 250 CALL libc_setitimer(SB) 251 RET 252 253TEXT runtime·usleep_trampoline(SB),NOSPLIT,$32 254 MOVW 0(R3), R3 // arg 1 - usec 255 CALL libc_usleep(SB) 256 RET 257 258TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$32 259 MOVW 8(R3), R4 // arg 2 - miblen 260 MOVD 16(R3), R5 // arg 3 - out 261 MOVD 24(R3), R6 // arg 4 - size 262 MOVD 32(R3), R7 // arg 5 - dst 263 MOVD 40(R3), R8 // arg 6 - ndst 264 MOVD 0(R3), R3 // arg 1 - mib 265 CALL libc_sysctl(SB) 266 RET 267 268TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$32 269 CALL libc_kqueue(SB) 270 RET 271 272TEXT runtime·kevent_trampoline(SB),NOSPLIT,$32 273 MOVD 8(R3), R4 // arg 2 - keventt 274 MOVW 16(R3), R5 // arg 3 - nch 275 MOVD 24(R3), R6 // arg 4 - ev 276 MOVW 32(R3), R7 // arg 5 - nev 277 MOVD 40(R3), R8 // arg 6 - ts 278 MOVW 0(R3), R3 // arg 1 - kq 279 CALL libc_kevent(SB) 280 CMP R3, $-1 281 BNE noerr 282 CALL libc_errno(SB) 283 MOVW (R3), R3 // errno 284 NEG R3, R3 // caller expects negative errno value 285noerr: 286 RET 287 288TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$32 289 MOVD 8(R3), R4 // arg 2 - tp 290 MOVW 0(R3), R3 // arg 1 - clock_id 291 CALL libc_clock_gettime(SB) 292 CMP R3, $-1 293 BNE noerr 294 CALL libc_errno(SB) 295 MOVW (R3), R3 // errno 296 NEG R3, R3 // caller expects negative errno value 297noerr: 298 RET 299 300TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$32 301 MOVD R3, R14 // pointer to args 302 MOVW 0(R14), R3 // arg 1 - fd 303 MOVW 4(R14), R4 // arg 2 - cmd 304 MOVW 8(R14), R5 // arg 3 - arg 305 MOVD $0, R6 // vararg 306 CALL libc_fcntl(SB) 307 MOVD $0, R4 308 CMP R3, $-1 309 BNE noerr 310 CALL libc_errno(SB) 311 MOVW (R3), R4 // errno 312 MOVW $-1, R3 313noerr: 314 MOVW R3, 12(R14) 315 MOVW R4, 16(R14) 316 RET 317 318TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$32 319 MOVD 8(R3), R4 // arg 2 - new 320 MOVD 16(R3), R5 // arg 3 - old 321 MOVW 0(R3), R3 // arg 1 - sig 322 CALL libc_sigaction(SB) 323 CMP R3, $-1 324 BNE 3(PC) 325 MOVD $0, R3 // crash on syscall failure 326 MOVD R3, (R3) 327 RET 328 329TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$32 330 MOVD 8(R3), R4 // arg 2 - new 331 MOVD 16(R3), R5 // arg 3 - old 332 MOVW 0(R3), R3 // arg 1 - how 333 CALL libc_pthread_sigmask(SB) 334 CMP R3, $-1 335 BNE 3(PC) 336 MOVD $0, R3 // crash on syscall failure 337 MOVD R3, (R3) 338 RET 339 340TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$32 341 MOVD 8(R3), R4 // arg 2 - old 342 MOVD 0(R3), R3 // arg 1 - new 343 CALL libc_sigaltstack(SB) 344 CMP R3, $-1 345 BNE 3(PC) 346 MOVD $0, R3 // crash on syscall failure 347 MOVD R3, (R3) 348 RET 349 350TEXT runtime·issetugid_trampoline(SB),NOSPLIT,$32 351 MOVD R3, R14 // pointer to args 352 CALL libc_getthrid(SB) 353 MOVW R3, 0(R14) // return value 354 RET 355 356// syscall calls a function in libc on behalf of the syscall package. 357// syscall takes a pointer to a struct like: 358// struct { 359// fn uintptr 360// a1 uintptr 361// a2 uintptr 362// a3 uintptr 363// r1 uintptr 364// r2 uintptr 365// err uintptr 366// } 367// syscall must be called on the g0 stack with the 368// C calling convention (use libcCall). 369// 370// syscall expects a 32-bit result and tests for 32-bit -1 371// to decide there was an error. 372TEXT runtime·syscall(SB),NOSPLIT,$32 373 MOVD R3, R14 // pointer to args 374 375 MOVD (0*8)(R14), R12 // fn 376 MOVD (1*8)(R14), R3 // a1 377 MOVD (2*8)(R14), R4 // a2 378 MOVD (3*8)(R14), R5 // a3 379 MOVD $0, R6 // vararg 380 381 MOVD R12, CTR 382 CALL (CTR) 383 384 MOVD R3, (4*8)(R14) // r1 385 MOVD R4, (5*8)(R14) // r2 386 387 // Standard libc functions return -1 on error 388 // and set errno. 389 CMPW R3, $-1 390 BNE ok 391 392 // Get error code from libc. 393 CALL libc_errno(SB) 394 MOVW (R3), R3 395 MOVD R3, (6*8)(R14) // err 396 397ok: 398 RET 399 400// syscallX calls a function in libc on behalf of the syscall package. 401// syscallX takes a pointer to a struct like: 402// struct { 403// fn uintptr 404// a1 uintptr 405// a2 uintptr 406// a3 uintptr 407// r1 uintptr 408// r2 uintptr 409// err uintptr 410// } 411// syscallX must be called on the g0 stack with the 412// C calling convention (use libcCall). 413// 414// syscallX is like syscall but expects a 64-bit result 415// and tests for 64-bit -1 to decide there was an error. 416TEXT runtime·syscallX(SB),NOSPLIT,$32 417 MOVD R3, R14 // pointer to args 418 419 MOVD (0*8)(R14), R12 // fn 420 MOVD (1*8)(R14), R3 // a1 421 MOVD (2*8)(R14), R4 // a2 422 MOVD (3*8)(R14), R5 // a3 423 MOVD $0, R6 // vararg 424 425 MOVD R12, CTR 426 CALL (CTR) 427 428 MOVD R3, (4*8)(R14) // r1 429 MOVD R4, (5*8)(R14) // r2 430 431 // Standard libc functions return -1 on error 432 // and set errno. 433 CMP R3, $-1 434 BNE ok 435 436 // Get error code from libc. 437 CALL libc_errno(SB) 438 MOVW (R3), R3 439 MOVD R3, (6*8)(R14) // err 440 441ok: 442 RET 443 444// syscall6 calls a function in libc on behalf of the syscall package. 445// syscall6 takes a pointer to a struct like: 446// struct { 447// fn uintptr 448// a1 uintptr 449// a2 uintptr 450// a3 uintptr 451// a4 uintptr 452// a5 uintptr 453// a6 uintptr 454// r1 uintptr 455// r2 uintptr 456// err uintptr 457// } 458// syscall6 must be called on the g0 stack with the 459// C calling convention (use libcCall). 460// 461// syscall6 expects a 32-bit result and tests for 32-bit -1 462// to decide there was an error. 463TEXT runtime·syscall6(SB),NOSPLIT,$32 464 MOVD R3, R14 // pointer to args 465 466 MOVD (0*8)(R14), R12 // fn 467 MOVD (1*8)(R14), R3 // a1 468 MOVD (2*8)(R14), R4 // a2 469 MOVD (3*8)(R14), R5 // a3 470 MOVD (4*8)(R14), R6 // a4 471 MOVD (5*8)(R14), R7 // a5 472 MOVD (6*8)(R14), R8 // a6 473 MOVD $0, R9 // vararg 474 475 MOVD R12, CTR 476 CALL (CTR) 477 478 MOVD R3, (7*8)(R14) // r1 479 MOVD R4, (8*8)(R14) // r2 480 481 // Standard libc functions return -1 on error 482 // and set errno. 483 CMPW R3, $-1 484 BNE ok 485 486 // Get error code from libc. 487 CALL libc_errno(SB) 488 MOVW (R3), R3 489 MOVD R3, (9*8)(R14) // err 490 491ok: 492 RET 493 494// syscall6X calls a function in libc on behalf of the syscall package. 495// syscall6X takes a pointer to a struct like: 496// struct { 497// fn uintptr 498// a1 uintptr 499// a2 uintptr 500// a3 uintptr 501// a4 uintptr 502// a5 uintptr 503// a6 uintptr 504// r1 uintptr 505// r2 uintptr 506// err uintptr 507// } 508// syscall6X must be called on the g0 stack with the 509// C calling convention (use libcCall). 510// 511// syscall6X is like syscall6 but expects a 64-bit result 512// and tests for 64-bit -1 to decide there was an error. 513TEXT runtime·syscall6X(SB),NOSPLIT,$32 514 MOVD R3, R14 // pointer to args 515 516 MOVD (0*8)(R14), R12 // fn 517 MOVD (1*8)(R14), R3 // a1 518 MOVD (2*8)(R14), R4 // a2 519 MOVD (3*8)(R14), R5 // a3 520 MOVD (4*8)(R14), R6 // a4 521 MOVD (5*8)(R14), R7 // a5 522 MOVD (6*8)(R14), R8 // a6 523 MOVD $0, R9 // vararg 524 525 MOVD R12, CTR 526 CALL (CTR) 527 528 MOVD R3, (7*8)(R14) // r1 529 MOVD R4, (8*8)(R14) // r2 530 531 // Standard libc functions return -1 on error 532 // and set errno. 533 CMP R3, $-1 534 BNE ok 535 536 // Get error code from libc. 537 CALL libc_errno(SB) 538 MOVW (R3), R3 539 MOVD R3, (9*8)(R14) // err 540 541ok: 542 RET 543 544// syscall10 calls a function in libc on behalf of the syscall package. 545// syscall10 takes a pointer to a struct like: 546// struct { 547// fn uintptr 548// a1 uintptr 549// a2 uintptr 550// a3 uintptr 551// a4 uintptr 552// a5 uintptr 553// a6 uintptr 554// a7 uintptr 555// a8 uintptr 556// a9 uintptr 557// a10 uintptr 558// r1 uintptr 559// r2 uintptr 560// err uintptr 561// } 562// syscall10 must be called on the g0 stack with the 563// C calling convention (use libcCall). Note that this is 564// really syscall8 as a maximum of eight parameters can be 565// passed via registers (and current usage does not exceed 566// this). 567TEXT runtime·syscall10(SB),NOSPLIT,$32 568 MOVD R3, R14 // pointer to args 569 570 MOVD (0*8)(R14), R12 // fn 571 MOVD (1*8)(R14), R3 // a1 572 MOVD (2*8)(R14), R4 // a2 573 MOVD (3*8)(R14), R5 // a3 574 MOVD (4*8)(R14), R6 // a4 575 MOVD (5*8)(R14), R7 // a5 576 MOVD (6*8)(R14), R8 // a6 577 MOVD (7*8)(R14), R9 // a7 578 MOVD (8*8)(R14), R10 // a8 579 580 MOVD R12, CTR 581 CALL (CTR) 582 583 MOVD R3, (11*8)(R14) // r1 584 MOVD R4, (12*8)(R14) // r2 585 586 // Standard libc functions return -1 on error 587 // and set errno. 588 CMPW R3, $-1 589 BNE ok 590 591 // Get error code from libc. 592 CALL libc_errno(SB) 593 MOVW (R3), R3 594 MOVD R3, (13*8)(R14) // err 595 596ok: 597 RET 598 599// syscall10X calls a function in libc on behalf of the syscall package. 600// syscall10X takes a pointer to a struct like: 601// struct { 602// fn uintptr 603// a1 uintptr 604// a2 uintptr 605// a3 uintptr 606// a4 uintptr 607// a5 uintptr 608// a6 uintptr 609// a7 uintptr 610// a8 uintptr 611// a9 uintptr 612// a10 uintptr 613// r1 uintptr 614// r2 uintptr 615// err uintptr 616// } 617// syscall10X must be called on the g0 stack with the 618// C calling convention (use libcCall). Note that this is 619// really syscall8X as a maximum of eight parameters can be 620// passed via registers (and current usage does not exceed 621// this). 622// 623// syscall10X is like syscall10 but expects a 64-bit result 624// and tests for 64-bit -1 to decide there was an error. 625TEXT runtime·syscall10X(SB),NOSPLIT,$32 626 MOVD R3, R14 // pointer to args 627 628 MOVD (0*8)(R14), R12 // fn 629 MOVD (1*8)(R14), R3 // a1 630 MOVD (2*8)(R14), R4 // a2 631 MOVD (3*8)(R14), R5 // a3 632 MOVD (4*8)(R14), R6 // a4 633 MOVD (5*8)(R14), R7 // a5 634 MOVD (6*8)(R14), R8 // a6 635 MOVD (7*8)(R14), R9 // a7 636 MOVD (8*8)(R14), R10 // a8 637 638 MOVD R12, CTR 639 CALL (CTR) 640 641 MOVD R3, (11*8)(R14) // r1 642 MOVD R4, (12*8)(R14) // r2 643 644 // Standard libc functions return -1 on error 645 // and set errno. 646 CMP R3, $-1 647 BNE ok 648 649 // Get error code from libc. 650 CALL libc_errno(SB) 651 MOVW (R3), R3 652 MOVD R3, (13*8)(R14) // err 653 654ok: 655 RET 656