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