github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 now() (sec int64, nsec int32) 155 TEXT time·now(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+0(FP) 166 MOVL $0, sec+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 sig+4(FP), AX 216 MOVL AX, 0(SP) 217 MOVL info+8(FP), AX 218 MOVL AX, 4(SP) 219 MOVL ctx+12(FP), AX 220 MOVL AX, 8(SP) 221 MOVL fn+0(FP), AX 222 CALL AX 223 RET 224 225 TEXT runtime·sigtramp(SB),NOSPLIT,$12 226 MOVL sig+0(FP), BX 227 MOVL BX, 0(SP) 228 MOVL info+4(FP), BX 229 MOVL BX, 4(SP) 230 MOVL ctx+8(FP), BX 231 MOVL BX, 8(SP) 232 CALL runtime·sigtrampgo(SB) 233 RET 234 235 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 236 JMP runtime·sigtramp(SB) 237 238 TEXT runtime·sigreturn(SB),NOSPLIT,$0 239 MOVL $173, AX // rt_sigreturn 240 // Sigreturn expects same SP as signal handler, 241 // so cannot CALL 0x10(GS) here. 242 INT $0x80 243 INT $3 // not reached 244 RET 245 246 TEXT runtime·mmap(SB),NOSPLIT,$0 247 MOVL $192, AX // mmap2 248 MOVL addr+0(FP), BX 249 MOVL n+4(FP), CX 250 MOVL prot+8(FP), DX 251 MOVL flags+12(FP), SI 252 MOVL fd+16(FP), DI 253 MOVL off+20(FP), BP 254 SHRL $12, BP 255 INVOKE_SYSCALL 256 CMPL AX, $0xfffff001 257 JLS 3(PC) 258 NOTL AX 259 INCL AX 260 MOVL AX, ret+24(FP) 261 RET 262 263 TEXT runtime·munmap(SB),NOSPLIT,$0 264 MOVL $91, AX // munmap 265 MOVL addr+0(FP), BX 266 MOVL n+4(FP), CX 267 INVOKE_SYSCALL 268 CMPL AX, $0xfffff001 269 JLS 2(PC) 270 INT $3 271 RET 272 273 TEXT runtime·madvise(SB),NOSPLIT,$0 274 MOVL $219, AX // madvise 275 MOVL addr+0(FP), BX 276 MOVL n+4(FP), CX 277 MOVL flags+8(FP), DX 278 INVOKE_SYSCALL 279 // ignore failure - maybe pages are locked 280 RET 281 282 // int32 futex(int32 *uaddr, int32 op, int32 val, 283 // struct timespec *timeout, int32 *uaddr2, int32 val2); 284 TEXT runtime·futex(SB),NOSPLIT,$0 285 MOVL $240, AX // futex 286 MOVL addr+0(FP), BX 287 MOVL op+4(FP), CX 288 MOVL val+8(FP), DX 289 MOVL ts+12(FP), SI 290 MOVL addr2+16(FP), DI 291 MOVL val3+20(FP), BP 292 INVOKE_SYSCALL 293 MOVL AX, ret+24(FP) 294 RET 295 296 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 297 TEXT runtime·clone(SB),NOSPLIT,$0 298 MOVL $120, AX // clone 299 MOVL flags+0(FP), BX 300 MOVL stk+4(FP), CX 301 MOVL $0, DX // parent tid ptr 302 MOVL $0, DI // child tid ptr 303 304 // Copy mp, gp, fn off parent stack for use by child. 305 SUBL $16, CX 306 MOVL mp+8(FP), SI 307 MOVL SI, 0(CX) 308 MOVL gp+12(FP), SI 309 MOVL SI, 4(CX) 310 MOVL fn+16(FP), SI 311 MOVL SI, 8(CX) 312 MOVL $1234, 12(CX) 313 314 // cannot use CALL 0x10(GS) here, because the stack changes during the 315 // system call (after CALL 0x10(GS), the child is still using the 316 // parent's stack when executing its RET instruction). 317 INT $0x80 318 319 // In parent, return. 320 CMPL AX, $0 321 JEQ 3(PC) 322 MOVL AX, ret+20(FP) 323 RET 324 325 // Paranoia: check that SP is as we expect. 326 MOVL 12(SP), BP 327 CMPL BP, $1234 328 JEQ 2(PC) 329 INT $3 330 331 // Initialize AX to Linux tid 332 MOVL $224, AX 333 INVOKE_SYSCALL 334 335 MOVL 0(SP), BX // m 336 MOVL 4(SP), DX // g 337 MOVL 8(SP), SI // fn 338 339 CMPL BX, $0 340 JEQ nog 341 CMPL DX, $0 342 JEQ nog 343 344 MOVL AX, m_procid(BX) // save tid as m->procid 345 346 // set up ldt 7+id to point at m->tls. 347 LEAL m_tls(BX), BP 348 MOVL m_id(BX), DI 349 ADDL $7, DI // m0 is LDT#7. count up. 350 // setldt(tls#, &tls, sizeof tls) 351 PUSHAL // save registers 352 PUSHL $32 // sizeof tls 353 PUSHL BP // &tls 354 PUSHL DI // tls # 355 CALL runtime·setldt(SB) 356 POPL AX 357 POPL AX 358 POPL AX 359 POPAL 360 361 // Now segment is established. Initialize m, g. 362 get_tls(AX) 363 MOVL DX, g(AX) 364 MOVL BX, g_m(DX) 365 366 CALL runtime·stackcheck(SB) // smashes AX, CX 367 MOVL 0(DX), DX // paranoia; check they are not nil 368 MOVL 0(BX), BX 369 370 // more paranoia; check that stack splitting code works 371 PUSHAL 372 CALL runtime·emptyfunc(SB) 373 POPAL 374 375 nog: 376 CALL SI // fn() 377 CALL runtime·exit1(SB) 378 MOVL $0x1234, 0x1005 379 380 TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 381 MOVL $186, AX // sigaltstack 382 MOVL new+0(FP), BX 383 MOVL old+4(FP), CX 384 INVOKE_SYSCALL 385 CMPL AX, $0xfffff001 386 JLS 2(PC) 387 INT $3 388 RET 389 390 // <asm-i386/ldt.h> 391 // struct user_desc { 392 // unsigned int entry_number; 393 // unsigned long base_addr; 394 // unsigned int limit; 395 // unsigned int seg_32bit:1; 396 // unsigned int contents:2; 397 // unsigned int read_exec_only:1; 398 // unsigned int limit_in_pages:1; 399 // unsigned int seg_not_present:1; 400 // unsigned int useable:1; 401 // }; 402 #define SEG_32BIT 0x01 403 // contents are the 2 bits 0x02 and 0x04. 404 #define CONTENTS_DATA 0x00 405 #define CONTENTS_STACK 0x02 406 #define CONTENTS_CODE 0x04 407 #define READ_EXEC_ONLY 0x08 408 #define LIMIT_IN_PAGES 0x10 409 #define SEG_NOT_PRESENT 0x20 410 #define USEABLE 0x40 411 412 // `-1` means the kernel will pick a TLS entry on the first setldt call, 413 // which happens during runtime init, and that we'll store back the saved 414 // entry and reuse that on subsequent calls when creating new threads. 415 DATA runtime·tls_entry_number+0(SB)/4, $-1 416 GLOBL runtime·tls_entry_number(SB), NOPTR, $4 417 418 // setldt(int entry, int address, int limit) 419 // We use set_thread_area, which mucks with the GDT, instead of modify_ldt, 420 // which would modify the LDT, but is disabled on some kernels. 421 // The name, setldt, is a misnomer, although we leave this name as it is for 422 // the compatibility with other platforms. 423 TEXT runtime·setldt(SB),NOSPLIT,$32 424 MOVL address+4(FP), DX // base address 425 426 #ifdef GOOS_android 427 /* 428 * Same as in sys_darwin_386.s:/ugliness, different constant. 429 * address currently holds m->tls, which must be %gs:0xf8. 430 * See cgo/gcc_android_386.c for the derivation of the constant. 431 */ 432 SUBL $0xf8, DX 433 MOVL DX, 0(DX) 434 #else 435 /* 436 * When linking against the system libraries, 437 * we use its pthread_create and let it set up %gs 438 * for us. When we do that, the private storage 439 * we get is not at 0(GS), but -4(GS). 440 * To insulate the rest of the tool chain from this 441 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us. 442 * To accommodate that rewrite, we translate 443 * the address here and bump the limit to 0xffffffff (no limit) 444 * so that -4(GS) maps to 0(address). 445 * Also, the final 0(GS) (current 4(DX)) has to point 446 * to itself, to mimic ELF. 447 */ 448 ADDL $0x4, DX // address 449 MOVL DX, 0(DX) 450 #endif 451 452 // get entry number 453 MOVL runtime·tls_entry_number(SB), CX 454 455 // set up user_desc 456 LEAL 16(SP), AX // struct user_desc 457 MOVL CX, 0(AX) // unsigned int entry_number 458 MOVL DX, 4(AX) // unsigned long base_addr 459 MOVL $0xfffff, 8(AX) // unsigned int limit 460 MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits 461 462 // call set_thread_area 463 MOVL AX, BX // user_desc 464 MOVL $243, AX // syscall - set_thread_area 465 // We can't call this via 0x10(GS) because this is called from setldt0 to set that up. 466 INT $0x80 467 468 // breakpoint on error 469 CMPL AX, $0xfffff001 470 JLS 2(PC) 471 INT $3 472 473 // read allocated entry number back out of user_desc 474 LEAL 16(SP), AX // get our user_desc back 475 MOVL 0(AX), AX 476 477 // store entry number if the kernel allocated it 478 CMPL CX, $-1 479 JNE 2(PC) 480 MOVL AX, runtime·tls_entry_number(SB) 481 482 // compute segment selector - (entry*8+3) 483 SHLL $3, AX 484 ADDL $3, AX 485 MOVW AX, GS 486 487 RET 488 489 TEXT runtime·osyield(SB),NOSPLIT,$0 490 MOVL $158, AX 491 INVOKE_SYSCALL 492 RET 493 494 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 495 MOVL $242, AX // syscall - sched_getaffinity 496 MOVL pid+0(FP), BX 497 MOVL len+4(FP), CX 498 MOVL buf+8(FP), DX 499 INVOKE_SYSCALL 500 MOVL AX, ret+12(FP) 501 RET 502 503 // int32 runtime·epollcreate(int32 size); 504 TEXT runtime·epollcreate(SB),NOSPLIT,$0 505 MOVL $254, AX 506 MOVL size+0(FP), BX 507 INVOKE_SYSCALL 508 MOVL AX, ret+4(FP) 509 RET 510 511 // int32 runtime·epollcreate1(int32 flags); 512 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 513 MOVL $329, AX 514 MOVL flags+0(FP), BX 515 INVOKE_SYSCALL 516 MOVL AX, ret+4(FP) 517 RET 518 519 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 520 TEXT runtime·epollctl(SB),NOSPLIT,$0 521 MOVL $255, AX 522 MOVL epfd+0(FP), BX 523 MOVL op+4(FP), CX 524 MOVL fd+8(FP), DX 525 MOVL ev+12(FP), SI 526 INVOKE_SYSCALL 527 MOVL AX, ret+16(FP) 528 RET 529 530 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 531 TEXT runtime·epollwait(SB),NOSPLIT,$0 532 MOVL $256, AX 533 MOVL epfd+0(FP), BX 534 MOVL ev+4(FP), CX 535 MOVL nev+8(FP), DX 536 MOVL timeout+12(FP), SI 537 INVOKE_SYSCALL 538 MOVL AX, ret+16(FP) 539 RET 540 541 // void runtime·closeonexec(int32 fd); 542 TEXT runtime·closeonexec(SB),NOSPLIT,$0 543 MOVL $55, AX // fcntl 544 MOVL fd+0(FP), BX // fd 545 MOVL $2, CX // F_SETFD 546 MOVL $1, DX // FD_CLOEXEC 547 INVOKE_SYSCALL 548 RET 549 550 // int access(const char *name, int mode) 551 TEXT runtime·access(SB),NOSPLIT,$0 552 MOVL $33, AX // syscall - access 553 MOVL name+0(FP), BX 554 MOVL mode+4(FP), CX 555 INVOKE_SYSCALL 556 MOVL AX, ret+8(FP) 557 RET 558 559 // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) 560 TEXT runtime·connect(SB),NOSPLIT,$0-16 561 // connect is implemented as socketcall(NR_socket, 3, *(rest of args)) 562 // stack already should have fd, addr, addrlen. 563 MOVL $102, AX // syscall - socketcall 564 MOVL $3, BX // connect 565 LEAL fd+0(FP), CX 566 INVOKE_SYSCALL 567 MOVL AX, ret+12(FP) 568 RET 569 570 // int socket(int domain, int type, int protocol) 571 TEXT runtime·socket(SB),NOSPLIT,$0-16 572 // socket is implemented as socketcall(NR_socket, 1, *(rest of args)) 573 // stack already should have domain, type, protocol. 574 MOVL $102, AX // syscall - socketcall 575 MOVL $1, BX // socket 576 LEAL domain+0(FP), CX 577 INVOKE_SYSCALL 578 MOVL AX, ret+12(FP) 579 RET