1// Copyright 2014 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// +build linux 6// +build ppc64 ppc64le 7 8// 9// System calls and other sys.stuff for ppc64, Linux 10// 11 12#include "go_asm.h" 13#include "go_tls.h" 14#include "textflag.h" 15#include "asm_ppc64x.h" 16 17#define SYS_exit 1 18#define SYS_read 3 19#define SYS_write 4 20#define SYS_open 5 21#define SYS_close 6 22#define SYS_getpid 20 23#define SYS_kill 37 24#define SYS_brk 45 25#define SYS_fcntl 55 26#define SYS_gettimeofday 78 27#define SYS_select 82 // always return -ENOSYS 28#define SYS_mmap 90 29#define SYS_munmap 91 30#define SYS_setitimer 104 31#define SYS_clone 120 32#define SYS_newselect 142 33#define SYS_sched_yield 158 34#define SYS_rt_sigreturn 172 35#define SYS_rt_sigaction 173 36#define SYS_rt_sigprocmask 174 37#define SYS_sigaltstack 185 38#define SYS_ugetrlimit 190 39#define SYS_madvise 205 40#define SYS_mincore 206 41#define SYS_gettid 207 42#define SYS_tkill 208 43#define SYS_futex 221 44#define SYS_sched_getaffinity 223 45#define SYS_exit_group 234 46#define SYS_epoll_create 236 47#define SYS_epoll_ctl 237 48#define SYS_epoll_wait 238 49#define SYS_clock_gettime 246 50#define SYS_epoll_create1 315 51 52TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 53 MOVW code+0(FP), R3 54 SYSCALL $SYS_exit_group 55 RET 56 57// func exitThread(wait *uint32) 58TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 59 MOVD wait+0(FP), R1 60 // We're done using the stack. 61 MOVW $0, R2 62 SYNC 63 MOVW R2, (R1) 64 MOVW $0, R3 // exit code 65 SYSCALL $SYS_exit 66 JMP 0(PC) 67 68TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20 69 MOVD name+0(FP), R3 70 MOVW mode+8(FP), R4 71 MOVW perm+12(FP), R5 72 SYSCALL $SYS_open 73 BVC 2(PC) 74 MOVW $-1, R3 75 MOVW R3, ret+16(FP) 76 RET 77 78TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12 79 MOVW fd+0(FP), R3 80 SYSCALL $SYS_close 81 BVC 2(PC) 82 MOVW $-1, R3 83 MOVW R3, ret+8(FP) 84 RET 85 86TEXT runtime·write(SB),NOSPLIT|NOFRAME,$0-28 87 MOVD fd+0(FP), R3 88 MOVD p+8(FP), R4 89 MOVW n+16(FP), R5 90 SYSCALL $SYS_write 91 BVC 2(PC) 92 MOVW $-1, R3 93 MOVW R3, ret+24(FP) 94 RET 95 96TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28 97 MOVW fd+0(FP), R3 98 MOVD p+8(FP), R4 99 MOVW n+16(FP), R5 100 SYSCALL $SYS_read 101 BVC 2(PC) 102 MOVW $-1, R3 103 MOVW R3, ret+24(FP) 104 RET 105 106TEXT runtime·getrlimit(SB),NOSPLIT|NOFRAME,$0-20 107 MOVW kind+0(FP), R3 108 MOVD limit+8(FP), R4 109 SYSCALL $SYS_ugetrlimit 110 MOVW R3, ret+16(FP) 111 RET 112 113TEXT runtime·usleep(SB),NOSPLIT,$16-4 114 MOVW usec+0(FP), R3 115 MOVD R3, R5 116 MOVW $1000000, R4 117 DIVD R4, R3 118 MOVD R3, 8(R1) 119 MULLD R3, R4 120 SUB R4, R5 121 MOVD R5, 16(R1) 122 123 // select(0, 0, 0, 0, &tv) 124 MOVW $0, R3 125 MOVW $0, R4 126 MOVW $0, R5 127 MOVW $0, R6 128 ADD $8, R1, R7 129 SYSCALL $SYS_newselect 130 RET 131 132TEXT runtime·gettid(SB),NOSPLIT,$0-4 133 SYSCALL $SYS_gettid 134 MOVW R3, ret+0(FP) 135 RET 136 137TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0 138 SYSCALL $SYS_gettid 139 MOVW R3, R3 // arg 1 tid 140 MOVW sig+0(FP), R4 // arg 2 141 SYSCALL $SYS_tkill 142 RET 143 144TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0 145 SYSCALL $SYS_getpid 146 MOVW R3, R3 // arg 1 pid 147 MOVW sig+0(FP), R4 // arg 2 148 SYSCALL $SYS_kill 149 RET 150 151TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 152 MOVW mode+0(FP), R3 153 MOVD new+8(FP), R4 154 MOVD old+16(FP), R5 155 SYSCALL $SYS_setitimer 156 RET 157 158TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 159 MOVD addr+0(FP), R3 160 MOVD n+8(FP), R4 161 MOVD dst+16(FP), R5 162 SYSCALL $SYS_mincore 163 NEG R3 // caller expects negative errno 164 MOVW R3, ret+24(FP) 165 RET 166 167// func walltime() (sec int64, nsec int32) 168TEXT runtime·walltime(SB),NOSPLIT,$16 169 MOVD $0, R3 // CLOCK_REALTIME 170 MOVD $0(R1), R4 171 SYSCALL $SYS_clock_gettime 172 MOVD 0(R1), R3 // sec 173 MOVD 8(R1), R5 // nsec 174 MOVD R3, sec+0(FP) 175 MOVW R5, nsec+8(FP) 176 RET 177 178TEXT runtime·nanotime(SB),NOSPLIT,$16 179 MOVW $1, R3 // CLOCK_MONOTONIC 180 MOVD $0(R1), R4 181 SYSCALL $SYS_clock_gettime 182 MOVD 0(R1), R3 // sec 183 MOVD 8(R1), R5 // nsec 184 // sec is in R3, nsec in R5 185 // return nsec in R3 186 MOVD $1000000000, R4 187 MULLD R4, R3 188 ADD R5, R3 189 MOVD R3, ret+0(FP) 190 RET 191 192TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 193 MOVW how+0(FP), R3 194 MOVD new+8(FP), R4 195 MOVD old+16(FP), R5 196 MOVW size+24(FP), R6 197 SYSCALL $SYS_rt_sigprocmask 198 BVC 2(PC) 199 MOVD R0, 0xf0(R0) // crash 200 RET 201 202TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36 203 MOVD sig+0(FP), R3 204 MOVD new+8(FP), R4 205 MOVD old+16(FP), R5 206 MOVD size+24(FP), R6 207 SYSCALL $SYS_rt_sigaction 208 MOVW R3, ret+32(FP) 209 RET 210 211TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 212 MOVW sig+8(FP), R3 213 MOVD info+16(FP), R4 214 MOVD ctx+24(FP), R5 215 MOVD fn+0(FP), R12 216 MOVD R12, CTR 217 BL (CTR) 218 MOVD 24(R1), R2 219 RET 220 221#ifdef GOARCH_ppc64le 222// ppc64le doesn't need function descriptors 223TEXT runtime·sigtramp(SB),NOSPLIT,$64 224#else 225// function descriptor for the real sigtramp 226TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0 227 DWORD $runtime·_sigtramp(SB) 228 DWORD $0 229 DWORD $0 230TEXT runtime·_sigtramp(SB),NOSPLIT,$64 231#endif 232 // initialize essential registers (just in case) 233 BL runtime·reginit(SB) 234 235 // this might be called in external code context, 236 // where g is not set. 237 MOVB runtime·iscgo(SB), R6 238 CMP R6, $0 239 BEQ 2(PC) 240 BL runtime·load_g(SB) 241 242 MOVW R3, FIXED_FRAME+0(R1) 243 MOVD R4, FIXED_FRAME+8(R1) 244 MOVD R5, FIXED_FRAME+16(R1) 245 MOVD $runtime·sigtrampgo(SB), R12 246 MOVD R12, CTR 247 BL (CTR) 248 MOVD 24(R1), R2 249 RET 250 251#ifdef GOARCH_ppc64le 252// ppc64le doesn't need function descriptors 253TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 254 // The stack unwinder, presumably written in C, may not be able to 255 // handle Go frame correctly. So, this function is NOFRAME, and we 256 // we save/restore LR manually. 257 MOVD LR, R10 258 259 // We're coming from C code, initialize essential registers. 260 CALL runtime·reginit(SB) 261 262 // If no traceback function, do usual sigtramp. 263 MOVD runtime·cgoTraceback(SB), R6 264 CMP $0, R6 265 BEQ sigtramp 266 267 // If no traceback support function, which means that 268 // runtime/cgo was not linked in, do usual sigtramp. 269 MOVD _cgo_callers(SB), R6 270 CMP $0, R6 271 BEQ sigtramp 272 273 // Set up g register. 274 CALL runtime·load_g(SB) 275 276 // Figure out if we are currently in a cgo call. 277 // If not, just do usual sigtramp. 278 CMP $0, g 279 BEQ sigtrampnog // g == nil 280 MOVD g_m(g), R6 281 CMP $0, R6 282 BEQ sigtramp // g.m == nil 283 MOVW m_ncgo(R6), R7 284 CMPW $0, R7 285 BEQ sigtramp // g.m.ncgo = 0 286 MOVD m_curg(R6), R7 287 CMP $0, R7 288 BEQ sigtramp // g.m.curg == nil 289 MOVD g_syscallsp(R7), R7 290 CMP $0, R7 291 BEQ sigtramp // g.m.curg.syscallsp == 0 292 MOVD m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention. 293 CMP $0, R7 294 BEQ sigtramp // g.m.cgoCallers == nil 295 MOVW m_cgoCallersUse(R6), R8 296 CMPW $0, R8 297 BNE sigtramp // g.m.cgoCallersUse != 0 298 299 // Jump to a function in runtime/cgo. 300 // That function, written in C, will call the user's traceback 301 // function with proper unwind info, and will then call back here. 302 // The first three arguments, and the fifth, are already in registers. 303 // Set the two remaining arguments now. 304 MOVD runtime·cgoTraceback(SB), R6 305 MOVD $runtime·sigtramp(SB), R8 306 MOVD _cgo_callers(SB), R12 307 MOVD R12, CTR 308 MOVD R10, LR // restore LR 309 JMP (CTR) 310 311sigtramp: 312 MOVD R10, LR // restore LR 313 JMP runtime·sigtramp(SB) 314 315sigtrampnog: 316 // Signal arrived on a non-Go thread. If this is SIGPROF, get a 317 // stack trace. 318 CMPW R3, $27 // 27 == SIGPROF 319 BNE sigtramp 320 321 // Lock sigprofCallersUse (cas from 0 to 1). 322 MOVW $1, R7 323 MOVD $runtime·sigprofCallersUse(SB), R8 324 SYNC 325 LWAR (R8), R6 326 CMPW $0, R6 327 BNE sigtramp 328 STWCCC R7, (R8) 329 BNE -4(PC) 330 ISYNC 331 332 // Jump to the traceback function in runtime/cgo. 333 // It will call back to sigprofNonGo, which will ignore the 334 // arguments passed in registers. 335 // First three arguments to traceback function are in registers already. 336 MOVD runtime·cgoTraceback(SB), R6 337 MOVD $runtime·sigprofCallers(SB), R7 338 MOVD $runtime·sigprofNonGoWrapper<>(SB), R8 339 MOVD _cgo_callers(SB), R12 340 MOVD R12, CTR 341 MOVD R10, LR // restore LR 342 JMP (CTR) 343#else 344// function descriptor for the real sigtramp 345TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 346 DWORD $runtime·_cgoSigtramp(SB) 347 DWORD $0 348 DWORD $0 349TEXT runtime·_cgoSigtramp(SB),NOSPLIT,$0 350 JMP runtime·sigtramp(SB) 351#endif 352 353TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 354 // We're coming from C code, set up essential register, then call sigprofNonGo. 355 CALL runtime·reginit(SB) 356 CALL runtime·sigprofNonGo(SB) 357 RET 358 359TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0 360 MOVD addr+0(FP), R3 361 MOVD n+8(FP), R4 362 MOVW prot+16(FP), R5 363 MOVW flags+20(FP), R6 364 MOVW fd+24(FP), R7 365 MOVW off+28(FP), R8 366 367 SYSCALL $SYS_mmap 368 BVC ok 369 MOVD $0, p+32(FP) 370 MOVD R3, err+40(FP) 371 RET 372ok: 373 MOVD R3, p+32(FP) 374 MOVD $0, err+40(FP) 375 RET 376 377TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0 378 MOVD addr+0(FP), R3 379 MOVD n+8(FP), R4 380 SYSCALL $SYS_munmap 381 BVC 2(PC) 382 MOVD R0, 0xf0(R0) 383 RET 384 385TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0 386 MOVD addr+0(FP), R3 387 MOVD n+8(FP), R4 388 MOVW flags+16(FP), R5 389 SYSCALL $SYS_madvise 390 // ignore failure - maybe pages are locked 391 RET 392 393// int64 futex(int32 *uaddr, int32 op, int32 val, 394// struct timespec *timeout, int32 *uaddr2, int32 val2); 395TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0 396 MOVD addr+0(FP), R3 397 MOVW op+8(FP), R4 398 MOVW val+12(FP), R5 399 MOVD ts+16(FP), R6 400 MOVD addr2+24(FP), R7 401 MOVW val3+32(FP), R8 402 SYSCALL $SYS_futex 403 MOVW R3, ret+40(FP) 404 RET 405 406// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); 407TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0 408 MOVW flags+0(FP), R3 409 MOVD stk+8(FP), R4 410 411 // Copy mp, gp, fn off parent stack for use by child. 412 // Careful: Linux system call clobbers ???. 413 MOVD mp+16(FP), R7 414 MOVD gp+24(FP), R8 415 MOVD fn+32(FP), R12 416 417 MOVD R7, -8(R4) 418 MOVD R8, -16(R4) 419 MOVD R12, -24(R4) 420 MOVD $1234, R7 421 MOVD R7, -32(R4) 422 423 SYSCALL $SYS_clone 424 425 // In parent, return. 426 CMP R3, $0 427 BEQ 3(PC) 428 MOVW R3, ret+40(FP) 429 RET 430 431 // In child, on new stack. 432 // initialize essential registers 433 BL runtime·reginit(SB) 434 MOVD -32(R1), R7 435 CMP R7, $1234 436 BEQ 2(PC) 437 MOVD R0, 0(R0) 438 439 // Initialize m->procid to Linux tid 440 SYSCALL $SYS_gettid 441 442 MOVD -24(R1), R12 // fn 443 MOVD -16(R1), R8 // g 444 MOVD -8(R1), R7 // m 445 446 CMP R7, $0 447 BEQ nog 448 CMP R8, $0 449 BEQ nog 450 451 MOVD R3, m_procid(R7) 452 453 // TODO: setup TLS. 454 455 // In child, set up new stack 456 MOVD R7, g_m(R8) 457 MOVD R8, g 458 //CALL runtime·stackcheck(SB) 459 460nog: 461 // Call fn 462 MOVD R12, CTR 463 BL (CTR) 464 465 // It shouldn't return. If it does, exit that thread. 466 MOVW $111, R3 467 SYSCALL $SYS_exit 468 BR -2(PC) // keep exiting 469 470TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0 471 MOVD new+0(FP), R3 472 MOVD old+8(FP), R4 473 SYSCALL $SYS_sigaltstack 474 BVC 2(PC) 475 MOVD R0, 0xf0(R0) // crash 476 RET 477 478TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0 479 SYSCALL $SYS_sched_yield 480 RET 481 482TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0 483 MOVD pid+0(FP), R3 484 MOVD len+8(FP), R4 485 MOVD buf+16(FP), R5 486 SYSCALL $SYS_sched_getaffinity 487 MOVW R3, ret+24(FP) 488 RET 489 490// int32 runtime·epollcreate(int32 size); 491TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0 492 MOVW size+0(FP), R3 493 SYSCALL $SYS_epoll_create 494 MOVW R3, ret+8(FP) 495 RET 496 497// int32 runtime·epollcreate1(int32 flags); 498TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0 499 MOVW flags+0(FP), R3 500 SYSCALL $SYS_epoll_create1 501 MOVW R3, ret+8(FP) 502 RET 503 504// func epollctl(epfd, op, fd int32, ev *epollEvent) int 505TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0 506 MOVW epfd+0(FP), R3 507 MOVW op+4(FP), R4 508 MOVW fd+8(FP), R5 509 MOVD ev+16(FP), R6 510 SYSCALL $SYS_epoll_ctl 511 MOVW R3, ret+24(FP) 512 RET 513 514// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 515TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0 516 MOVW epfd+0(FP), R3 517 MOVD ev+8(FP), R4 518 MOVW nev+16(FP), R5 519 MOVW timeout+20(FP), R6 520 SYSCALL $SYS_epoll_wait 521 MOVW R3, ret+24(FP) 522 RET 523 524// void runtime·closeonexec(int32 fd); 525TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0 526 MOVW fd+0(FP), R3 // fd 527 MOVD $2, R4 // F_SETFD 528 MOVD $1, R5 // FD_CLOEXEC 529 SYSCALL $SYS_fcntl 530 RET 531 532// func sbrk0() uintptr 533TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0 534 // Implemented as brk(NULL). 535 MOVD $0, R3 536 SYSCALL $SYS_brk 537 MOVD R3, ret+0(FP) 538 RET 539