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