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