github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/runtime/sys_linux_386.s (about) 1 // Copyright 2009 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 // 6 // System calls and other sys.stuff for 386, Linux 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // Most linux systems use glibc's dynamic linker, which puts the 14 // __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position 15 // independent code and setldt in runtime does the same in the statically 16 // linked case. However, systems that use alternative libc such as Android's 17 // bionic and musl, do not save the helper anywhere, and so the only way to 18 // invoke a syscall from position independent code is boring old int $0x80 19 // (which is also what syscall wrappers in bionic/musl use). 20 // 21 // The benchmarks also showed that using int $0x80 is as fast as calling 22 // *%gs:0x10 except on AMD Opteron. See https://golang.org/cl/19833 23 // for the benchmark program and raw data. 24 //#define INVOKE_SYSCALL CALL 0x10(GS) // non-portable 25 #define INVOKE_SYSCALL INT $0x80 26 27 TEXT runtime·exit(SB),NOSPLIT,$0 28 MOVL $252, AX // syscall number 29 MOVL code+0(FP), BX 30 INVOKE_SYSCALL 31 INT $3 // not reached 32 RET 33 34 TEXT runtime·exit1(SB),NOSPLIT,$0 35 MOVL $1, AX // exit - exit the current os thread 36 MOVL code+0(FP), BX 37 INVOKE_SYSCALL 38 INT $3 // not reached 39 RET 40 41 TEXT runtime·open(SB),NOSPLIT,$0 42 MOVL $5, AX // syscall - open 43 MOVL name+0(FP), BX 44 MOVL mode+4(FP), CX 45 MOVL perm+8(FP), DX 46 INVOKE_SYSCALL 47 CMPL AX, $0xfffff001 48 JLS 2(PC) 49 MOVL $-1, AX 50 MOVL AX, ret+12(FP) 51 RET 52 53 TEXT runtime·closefd(SB),NOSPLIT,$0 54 MOVL $6, AX // syscall - close 55 MOVL fd+0(FP), BX 56 INVOKE_SYSCALL 57 CMPL AX, $0xfffff001 58 JLS 2(PC) 59 MOVL $-1, AX 60 MOVL AX, ret+4(FP) 61 RET 62 63 TEXT runtime·write(SB),NOSPLIT,$0 64 MOVL $4, AX // syscall - write 65 MOVL fd+0(FP), BX 66 MOVL p+4(FP), CX 67 MOVL n+8(FP), DX 68 INVOKE_SYSCALL 69 CMPL AX, $0xfffff001 70 JLS 2(PC) 71 MOVL $-1, AX 72 MOVL AX, ret+12(FP) 73 RET 74 75 TEXT runtime·read(SB),NOSPLIT,$0 76 MOVL $3, AX // syscall - read 77 MOVL fd+0(FP), BX 78 MOVL p+4(FP), CX 79 MOVL n+8(FP), DX 80 INVOKE_SYSCALL 81 CMPL AX, $0xfffff001 82 JLS 2(PC) 83 MOVL $-1, AX 84 MOVL AX, ret+12(FP) 85 RET 86 87 TEXT runtime·getrlimit(SB),NOSPLIT,$0 88 MOVL $191, AX // syscall - ugetrlimit 89 MOVL kind+0(FP), BX 90 MOVL limit+4(FP), CX 91 INVOKE_SYSCALL 92 MOVL AX, ret+8(FP) 93 RET 94 95 TEXT runtime·usleep(SB),NOSPLIT,$8 96 MOVL $0, DX 97 MOVL usec+0(FP), AX 98 MOVL $1000000, CX 99 DIVL CX 100 MOVL AX, 0(SP) 101 MOVL DX, 4(SP) 102 103 // select(0, 0, 0, 0, &tv) 104 MOVL $142, AX 105 MOVL $0, BX 106 MOVL $0, CX 107 MOVL $0, DX 108 MOVL $0, SI 109 LEAL 0(SP), DI 110 INVOKE_SYSCALL 111 RET 112 113 TEXT runtime·gettid(SB),NOSPLIT,$0-4 114 MOVL $224, AX // syscall - gettid 115 INVOKE_SYSCALL 116 MOVL AX, ret+0(FP) 117 RET 118 119 TEXT runtime·raise(SB),NOSPLIT,$12 120 MOVL $224, AX // syscall - gettid 121 INVOKE_SYSCALL 122 MOVL AX, BX // arg 1 tid 123 MOVL sig+0(FP), CX // arg 2 signal 124 MOVL $238, AX // syscall - tkill 125 INVOKE_SYSCALL 126 RET 127 128 TEXT runtime·raiseproc(SB),NOSPLIT,$12 129 MOVL $20, AX // syscall - getpid 130 INVOKE_SYSCALL 131 MOVL AX, BX // arg 1 pid 132 MOVL sig+0(FP), CX // arg 2 signal 133 MOVL $37, AX // syscall - kill 134 INVOKE_SYSCALL 135 RET 136 137 TEXT runtime·setitimer(SB),NOSPLIT,$0-12 138 MOVL $104, AX // syscall - setitimer 139 MOVL mode+0(FP), BX 140 MOVL new+4(FP), CX 141 MOVL old+8(FP), DX 142 INVOKE_SYSCALL 143 RET 144 145 TEXT runtime·mincore(SB),NOSPLIT,$0-16 146 MOVL $218, AX // syscall - mincore 147 MOVL addr+0(FP), BX 148 MOVL n+4(FP), CX 149 MOVL dst+8(FP), DX 150 INVOKE_SYSCALL 151 MOVL AX, ret+12(FP) 152 RET 153 154 // func walltime() (sec int64, nsec int32) 155 TEXT runtime·walltime(SB), NOSPLIT, $32 156 MOVL $265, AX // syscall - clock_gettime 157 MOVL $0, BX // CLOCK_REALTIME 158 LEAL 8(SP), CX 159 MOVL $0, DX 160 INVOKE_SYSCALL 161 MOVL 8(SP), AX // sec 162 MOVL 12(SP), BX // nsec 163 164 // sec is in AX, nsec in BX 165 MOVL AX, sec_lo+0(FP) 166 MOVL $0, sec_hi+4(FP) 167 MOVL BX, nsec+8(FP) 168 RET 169 170 // int64 nanotime(void) so really 171 // void nanotime(int64 *nsec) 172 TEXT runtime·nanotime(SB), NOSPLIT, $32 173 MOVL $265, AX // syscall - clock_gettime 174 MOVL $1, BX // CLOCK_MONOTONIC 175 LEAL 8(SP), CX 176 MOVL $0, DX 177 INVOKE_SYSCALL 178 MOVL 8(SP), AX // sec 179 MOVL 12(SP), BX // nsec 180 181 // sec is in AX, nsec in BX 182 // convert to DX:AX nsec 183 MOVL $1000000000, CX 184 MULL CX 185 ADDL BX, AX 186 ADCL $0, DX 187 188 MOVL AX, ret_lo+0(FP) 189 MOVL DX, ret_hi+4(FP) 190 RET 191 192 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 193 MOVL $175, AX // syscall entry 194 MOVL how+0(FP), BX 195 MOVL new+4(FP), CX 196 MOVL old+8(FP), DX 197 MOVL size+12(FP), SI 198 INVOKE_SYSCALL 199 CMPL AX, $0xfffff001 200 JLS 2(PC) 201 INT $3 202 RET 203 204 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 205 MOVL $174, AX // syscall - rt_sigaction 206 MOVL sig+0(FP), BX 207 MOVL new+4(FP), CX 208 MOVL old+8(FP), DX 209 MOVL size+12(FP), SI 210 INVOKE_SYSCALL 211 MOVL AX, ret+16(FP) 212 RET 213 214 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16 215 MOVL fn+0(FP), AX 216 MOVL sig+4(FP), BX 217 MOVL info+8(FP), CX 218 MOVL ctx+12(FP), DX 219 MOVL SP, SI 220 SUBL $32, SP 221 ANDL $-15, SP // align stack: handler might be a C function 222 MOVL BX, 0(SP) 223 MOVL CX, 4(SP) 224 MOVL DX, 8(SP) 225 MOVL SI, 12(SP) // save SI: handler might be a Go function 226 CALL AX 227 MOVL 12(SP), AX 228 MOVL AX, SP 229 RET 230 231 TEXT runtime·sigtramp(SB),NOSPLIT,$28 232 // Save callee-saved C registers, since the caller may be a C signal handler. 233 MOVL BX, bx-4(SP) 234 MOVL BP, bp-8(SP) 235 MOVL SI, si-12(SP) 236 MOVL DI, di-16(SP) 237 // We don't save mxcsr or the x87 control word because sigtrampgo doesn't 238 // modify them. 239 240 MOVL sig+0(FP), BX 241 MOVL BX, 0(SP) 242 MOVL info+4(FP), BX 243 MOVL BX, 4(SP) 244 MOVL ctx+8(FP), BX 245 MOVL BX, 8(SP) 246 CALL runtime·sigtrampgo(SB) 247 248 MOVL di-16(SP), DI 249 MOVL si-12(SP), SI 250 MOVL bp-8(SP), BP 251 MOVL bx-4(SP), BX 252 RET 253 254 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 255 JMP runtime·sigtramp(SB) 256 257 TEXT runtime·sigreturn(SB),NOSPLIT,$0 258 MOVL $173, AX // rt_sigreturn 259 // Sigreturn expects same SP as signal handler, 260 // so cannot CALL 0x10(GS) here. 261 INT $0x80 262 INT $3 // not reached 263 RET 264 265 TEXT runtime·mmap(SB),NOSPLIT,$0 266 MOVL $192, AX // mmap2 267 MOVL addr+0(FP), BX 268 MOVL n+4(FP), CX 269 MOVL prot+8(FP), DX 270 MOVL flags+12(FP), SI 271 MOVL fd+16(FP), DI 272 MOVL off+20(FP), BP 273 SHRL $12, BP 274 INVOKE_SYSCALL 275 CMPL AX, $0xfffff001 276 JLS 3(PC) 277 NOTL AX 278 INCL AX 279 MOVL AX, ret+24(FP) 280 RET 281 282 TEXT runtime·munmap(SB),NOSPLIT,$0 283 MOVL $91, AX // munmap 284 MOVL addr+0(FP), BX 285 MOVL n+4(FP), CX 286 INVOKE_SYSCALL 287 CMPL AX, $0xfffff001 288 JLS 2(PC) 289 INT $3 290 RET 291 292 TEXT runtime·madvise(SB),NOSPLIT,$0 293 MOVL $219, AX // madvise 294 MOVL addr+0(FP), BX 295 MOVL n+4(FP), CX 296 MOVL flags+8(FP), DX 297 INVOKE_SYSCALL 298 // ignore failure - maybe pages are locked 299 RET 300 301 // int32 futex(int32 *uaddr, int32 op, int32 val, 302 // struct timespec *timeout, int32 *uaddr2, int32 val2); 303 TEXT runtime·futex(SB),NOSPLIT,$0 304 MOVL $240, AX // futex 305 MOVL addr+0(FP), BX 306 MOVL op+4(FP), CX 307 MOVL val+8(FP), DX 308 MOVL ts+12(FP), SI 309 MOVL addr2+16(FP), DI 310 MOVL val3+20(FP), BP 311 INVOKE_SYSCALL 312 MOVL AX, ret+24(FP) 313 RET 314 315 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 316 TEXT runtime·clone(SB),NOSPLIT,$0 317 MOVL $120, AX // clone 318 MOVL flags+0(FP), BX 319 MOVL stk+4(FP), CX 320 MOVL $0, DX // parent tid ptr 321 MOVL $0, DI // child tid ptr 322 323 // Copy mp, gp, fn off parent stack for use by child. 324 SUBL $16, CX 325 MOVL mp+8(FP), SI 326 MOVL SI, 0(CX) 327 MOVL gp+12(FP), SI 328 MOVL SI, 4(CX) 329 MOVL fn+16(FP), SI 330 MOVL SI, 8(CX) 331 MOVL $1234, 12(CX) 332 333 // cannot use CALL 0x10(GS) here, because the stack changes during the 334 // system call (after CALL 0x10(GS), the child is still using the 335 // parent's stack when executing its RET instruction). 336 INT $0x80 337 338 // In parent, return. 339 CMPL AX, $0 340 JEQ 3(PC) 341 MOVL AX, ret+20(FP) 342 RET 343 344 // Paranoia: check that SP is as we expect. 345 MOVL 12(SP), BP 346 CMPL BP, $1234 347 JEQ 2(PC) 348 INT $3 349 350 // Initialize AX to Linux tid 351 MOVL $224, AX 352 INVOKE_SYSCALL 353 354 MOVL 0(SP), BX // m 355 MOVL 4(SP), DX // g 356 MOVL 8(SP), SI // fn 357 358 CMPL BX, $0 359 JEQ nog 360 CMPL DX, $0 361 JEQ nog 362 363 MOVL AX, m_procid(BX) // save tid as m->procid 364 365 // set up ldt 7+id to point at m->tls. 366 LEAL m_tls(BX), BP 367 MOVL m_id(BX), DI 368 ADDL $7, DI // m0 is LDT#7. count up. 369 // setldt(tls#, &tls, sizeof tls) 370 PUSHAL // save registers 371 PUSHL $32 // sizeof tls 372 PUSHL BP // &tls 373 PUSHL DI // tls # 374 CALL runtime·setldt(SB) 375 POPL AX 376 POPL AX 377 POPL AX 378 POPAL 379 380 // Now segment is established. Initialize m, g. 381 get_tls(AX) 382 MOVL DX, g(AX) 383 MOVL BX, g_m(DX) 384 385 CALL runtime·stackcheck(SB) // smashes AX, CX 386 MOVL 0(DX), DX // paranoia; check they are not nil 387 MOVL 0(BX), BX 388 389 // more paranoia; check that stack splitting code works 390 PUSHAL 391 CALL runtime·emptyfunc(SB) 392 POPAL 393 394 nog: 395 CALL SI // fn() 396 CALL runtime·exit1(SB) 397 MOVL $0x1234, 0x1005 398 399 TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 400 MOVL $186, AX // sigaltstack 401 MOVL new+0(FP), BX 402 MOVL old+4(FP), CX 403 INVOKE_SYSCALL 404 CMPL AX, $0xfffff001 405 JLS 2(PC) 406 INT $3 407 RET 408 409 // <asm-i386/ldt.h> 410 // struct user_desc { 411 // unsigned int entry_number; 412 // unsigned long base_addr; 413 // unsigned int limit; 414 // unsigned int seg_32bit:1; 415 // unsigned int contents:2; 416 // unsigned int read_exec_only:1; 417 // unsigned int limit_in_pages:1; 418 // unsigned int seg_not_present:1; 419 // unsigned int useable:1; 420 // }; 421 #define SEG_32BIT 0x01 422 // contents are the 2 bits 0x02 and 0x04. 423 #define CONTENTS_DATA 0x00 424 #define CONTENTS_STACK 0x02 425 #define CONTENTS_CODE 0x04 426 #define READ_EXEC_ONLY 0x08 427 #define LIMIT_IN_PAGES 0x10 428 #define SEG_NOT_PRESENT 0x20 429 #define USEABLE 0x40 430 431 // `-1` means the kernel will pick a TLS entry on the first setldt call, 432 // which happens during runtime init, and that we'll store back the saved 433 // entry and reuse that on subsequent calls when creating new threads. 434 DATA runtime·tls_entry_number+0(SB)/4, $-1 435 GLOBL runtime·tls_entry_number(SB), NOPTR, $4 436 437 // setldt(int entry, int address, int limit) 438 // We use set_thread_area, which mucks with the GDT, instead of modify_ldt, 439 // which would modify the LDT, but is disabled on some kernels. 440 // The name, setldt, is a misnomer, although we leave this name as it is for 441 // the compatibility with other platforms. 442 TEXT runtime·setldt(SB),NOSPLIT,$32 443 MOVL address+4(FP), DX // base address 444 445 #ifdef GOOS_android 446 /* 447 * Same as in sys_darwin_386.s:/ugliness, different constant. 448 * address currently holds m->tls, which must be %gs:0xf8. 449 * See cgo/gcc_android_386.c for the derivation of the constant. 450 */ 451 SUBL $0xf8, DX 452 MOVL DX, 0(DX) 453 #else 454 /* 455 * When linking against the system libraries, 456 * we use its pthread_create and let it set up %gs 457 * for us. When we do that, the private storage 458 * we get is not at 0(GS), but -4(GS). 459 * To insulate the rest of the tool chain from this 460 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us. 461 * To accommodate that rewrite, we translate 462 * the address here and bump the limit to 0xffffffff (no limit) 463 * so that -4(GS) maps to 0(address). 464 * Also, the final 0(GS) (current 4(DX)) has to point 465 * to itself, to mimic ELF. 466 */ 467 ADDL $0x4, DX // address 468 MOVL DX, 0(DX) 469 #endif 470 471 // get entry number 472 MOVL runtime·tls_entry_number(SB), CX 473 474 // set up user_desc 475 LEAL 16(SP), AX // struct user_desc 476 MOVL CX, 0(AX) // unsigned int entry_number 477 MOVL DX, 4(AX) // unsigned long base_addr 478 MOVL $0xfffff, 8(AX) // unsigned int limit 479 MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits 480 481 // call set_thread_area 482 MOVL AX, BX // user_desc 483 MOVL $243, AX // syscall - set_thread_area 484 // We can't call this via 0x10(GS) because this is called from setldt0 to set that up. 485 INT $0x80 486 487 // breakpoint on error 488 CMPL AX, $0xfffff001 489 JLS 2(PC) 490 INT $3 491 492 // read allocated entry number back out of user_desc 493 LEAL 16(SP), AX // get our user_desc back 494 MOVL 0(AX), AX 495 496 // store entry number if the kernel allocated it 497 CMPL CX, $-1 498 JNE 2(PC) 499 MOVL AX, runtime·tls_entry_number(SB) 500 501 // compute segment selector - (entry*8+3) 502 SHLL $3, AX 503 ADDL $3, AX 504 MOVW AX, GS 505 506 RET 507 508 TEXT runtime·osyield(SB),NOSPLIT,$0 509 MOVL $158, AX 510 INVOKE_SYSCALL 511 RET 512 513 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 514 MOVL $242, AX // syscall - sched_getaffinity 515 MOVL pid+0(FP), BX 516 MOVL len+4(FP), CX 517 MOVL buf+8(FP), DX 518 INVOKE_SYSCALL 519 MOVL AX, ret+12(FP) 520 RET 521 522 // int32 runtime·epollcreate(int32 size); 523 TEXT runtime·epollcreate(SB),NOSPLIT,$0 524 MOVL $254, AX 525 MOVL size+0(FP), BX 526 INVOKE_SYSCALL 527 MOVL AX, ret+4(FP) 528 RET 529 530 // int32 runtime·epollcreate1(int32 flags); 531 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 532 MOVL $329, AX 533 MOVL flags+0(FP), BX 534 INVOKE_SYSCALL 535 MOVL AX, ret+4(FP) 536 RET 537 538 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 539 TEXT runtime·epollctl(SB),NOSPLIT,$0 540 MOVL $255, AX 541 MOVL epfd+0(FP), BX 542 MOVL op+4(FP), CX 543 MOVL fd+8(FP), DX 544 MOVL ev+12(FP), SI 545 INVOKE_SYSCALL 546 MOVL AX, ret+16(FP) 547 RET 548 549 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 550 TEXT runtime·epollwait(SB),NOSPLIT,$0 551 MOVL $256, AX 552 MOVL epfd+0(FP), BX 553 MOVL ev+4(FP), CX 554 MOVL nev+8(FP), DX 555 MOVL timeout+12(FP), SI 556 INVOKE_SYSCALL 557 MOVL AX, ret+16(FP) 558 RET 559 560 // void runtime·closeonexec(int32 fd); 561 TEXT runtime·closeonexec(SB),NOSPLIT,$0 562 MOVL $55, AX // fcntl 563 MOVL fd+0(FP), BX // fd 564 MOVL $2, CX // F_SETFD 565 MOVL $1, DX // FD_CLOEXEC 566 INVOKE_SYSCALL 567 RET 568 569 // int access(const char *name, int mode) 570 TEXT runtime·access(SB),NOSPLIT,$0 571 MOVL $33, AX // syscall - access 572 MOVL name+0(FP), BX 573 MOVL mode+4(FP), CX 574 INVOKE_SYSCALL 575 MOVL AX, ret+8(FP) 576 RET 577 578 // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) 579 TEXT runtime·connect(SB),NOSPLIT,$0-16 580 // connect is implemented as socketcall(NR_socket, 3, *(rest of args)) 581 // stack already should have fd, addr, addrlen. 582 MOVL $102, AX // syscall - socketcall 583 MOVL $3, BX // connect 584 LEAL fd+0(FP), CX 585 INVOKE_SYSCALL 586 MOVL AX, ret+12(FP) 587 RET 588 589 // int socket(int domain, int type, int protocol) 590 TEXT runtime·socket(SB),NOSPLIT,$0-16 591 // socket is implemented as socketcall(NR_socket, 1, *(rest of args)) 592 // stack already should have domain, type, protocol. 593 MOVL $102, AX // syscall - socketcall 594 MOVL $1, BX // socket 595 LEAL domain+0(FP), CX 596 INVOKE_SYSCALL 597 MOVL AX, ret+12(FP) 598 RET 599 600 // func sbrk0() uintptr 601 TEXT runtime·sbrk0(SB),NOSPLIT,$0-4 602 // Implemented as brk(NULL). 603 MOVL $45, AX // syscall - brk 604 MOVL $0, BX // NULL 605 INVOKE_SYSCALL 606 MOVL AX, ret+0(FP) 607 RET