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 TEXT runtimeexit(SB),NOSPLIT,$0 14 MOVL $252, AX // syscall number 15 MOVL code+0(FP), BX 16 CALL *runtime_vdso(SB) 17 INT $3 // not reached 18 RET 19 20 TEXT runtimeexit1(SB),NOSPLIT,$0 21 MOVL $1, AX // exit - exit the current os thread 22 MOVL code+0(FP), BX 23 CALL *runtime_vdso(SB) 24 INT $3 // not reached 25 RET 26 27 TEXT runtimeopen(SB),NOSPLIT,$0 28 MOVL $5, AX // syscall - open 29 MOVL name+0(FP), BX 30 MOVL mode+4(FP), CX 31 MOVL perm+8(FP), DX 32 CALL *runtime_vdso(SB) 33 CMPL AX, $0xfffff001 34 JLS 2(PC) 35 MOVL $-1, AX 36 MOVL AX, ret+12(FP) 37 RET 38 39 TEXT runtimeclosefd(SB),NOSPLIT,$0 40 MOVL $6, AX // syscall - close 41 MOVL fd+0(FP), BX 42 CALL *runtime_vdso(SB) 43 CMPL AX, $0xfffff001 44 JLS 2(PC) 45 MOVL $-1, AX 46 MOVL AX, ret+4(FP) 47 RET 48 49 TEXT runtimewrite(SB),NOSPLIT,$0 50 MOVL $4, AX // syscall - write 51 MOVL fd+0(FP), BX 52 MOVL p+4(FP), CX 53 MOVL n+8(FP), DX 54 CALL *runtime_vdso(SB) 55 CMPL AX, $0xfffff001 56 JLS 2(PC) 57 MOVL $-1, AX 58 MOVL AX, ret+12(FP) 59 RET 60 61 TEXT runtimeread(SB),NOSPLIT,$0 62 MOVL $3, AX // syscall - read 63 MOVL fd+0(FP), BX 64 MOVL p+4(FP), CX 65 MOVL n+8(FP), DX 66 CALL *runtime_vdso(SB) 67 CMPL AX, $0xfffff001 68 JLS 2(PC) 69 MOVL $-1, AX 70 MOVL AX, ret+12(FP) 71 RET 72 73 TEXT runtimegetrlimit(SB),NOSPLIT,$0 74 MOVL $191, AX // syscall - ugetrlimit 75 MOVL kind+0(FP), BX 76 MOVL limit+4(FP), CX 77 CALL *runtime_vdso(SB) 78 MOVL AX, ret+8(FP) 79 RET 80 81 TEXT runtimeusleep(SB),NOSPLIT,$8 82 MOVL $0, DX 83 MOVL usec+0(FP), AX 84 MOVL $1000000, CX 85 DIVL CX 86 MOVL AX, 0(SP) 87 MOVL DX, 4(SP) 88 89 // select(0, 0, 0, 0, &tv) 90 MOVL $142, AX 91 MOVL $0, BX 92 MOVL $0, CX 93 MOVL $0, DX 94 MOVL $0, SI 95 LEAL 0(SP), DI 96 CALL *runtime_vdso(SB) 97 RET 98 99 TEXT runtimegettid(SB),NOSPLIT,$0-4 100 MOVL $224, AX // syscall - gettid 101 CALL *runtime_vdso(SB) 102 MOVL AX, ret+0(FP) 103 RET 104 105 TEXT runtimeraise(SB),NOSPLIT,$12 106 MOVL $224, AX // syscall - gettid 107 CALL *runtime_vdso(SB) 108 MOVL AX, BX // arg 1 tid 109 MOVL sig+0(FP), CX // arg 2 signal 110 MOVL $238, AX // syscall - tkill 111 CALL *runtime_vdso(SB) 112 RET 113 114 TEXT runtimeraiseproc(SB),NOSPLIT,$12 115 MOVL $20, AX // syscall - getpid 116 CALL *runtime_vdso(SB) 117 MOVL AX, BX // arg 1 pid 118 MOVL sig+0(FP), CX // arg 2 signal 119 MOVL $37, AX // syscall - kill 120 CALL *runtime_vdso(SB) 121 RET 122 123 TEXT runtimesetitimer(SB),NOSPLIT,$0-12 124 MOVL $104, AX // syscall - setitimer 125 MOVL mode+0(FP), BX 126 MOVL new+4(FP), CX 127 MOVL old+8(FP), DX 128 CALL *runtime_vdso(SB) 129 RET 130 131 TEXT runtimemincore(SB),NOSPLIT,$0-16 132 MOVL $218, AX // syscall - mincore 133 MOVL addr+0(FP), BX 134 MOVL n+4(FP), CX 135 MOVL dst+8(FP), DX 136 CALL *runtime_vdso(SB) 137 MOVL AX, ret+12(FP) 138 RET 139 140 // func now() (sec int64, nsec int32) 141 TEXT timenow(SB), NOSPLIT, $32 142 MOVL $265, AX // syscall - clock_gettime 143 MOVL $0, BX // CLOCK_REALTIME 144 LEAL 8(SP), CX 145 MOVL $0, DX 146 CALL *runtime_vdso(SB) 147 MOVL 8(SP), AX // sec 148 MOVL 12(SP), BX // nsec 149 150 // sec is in AX, nsec in BX 151 MOVL AX, sec+0(FP) 152 MOVL $0, sec+4(FP) 153 MOVL BX, nsec+8(FP) 154 RET 155 156 // int64 nanotime(void) so really 157 // void nanotime(int64 *nsec) 158 TEXT runtimenanotime(SB), NOSPLIT, $32 159 MOVL $265, AX // syscall - clock_gettime 160 MOVL $1, BX // CLOCK_MONOTONIC 161 LEAL 8(SP), CX 162 MOVL $0, DX 163 CALL *runtime_vdso(SB) 164 MOVL 8(SP), AX // sec 165 MOVL 12(SP), BX // nsec 166 167 // sec is in AX, nsec in BX 168 // convert to DX:AX nsec 169 MOVL $1000000000, CX 170 MULL CX 171 ADDL BX, AX 172 ADCL $0, DX 173 174 MOVL AX, ret_lo+0(FP) 175 MOVL DX, ret_hi+4(FP) 176 RET 177 178 TEXT runtimertsigprocmask(SB),NOSPLIT,$0 179 MOVL $175, AX // syscall entry 180 MOVL sig+0(FP), BX 181 MOVL new+4(FP), CX 182 MOVL old+8(FP), DX 183 MOVL size+12(FP), SI 184 CALL *runtime_vdso(SB) 185 CMPL AX, $0xfffff001 186 JLS 2(PC) 187 INT $3 188 RET 189 190 TEXT runtimert_sigaction(SB),NOSPLIT,$0 191 MOVL $174, AX // syscall - rt_sigaction 192 MOVL sig+0(FP), BX 193 MOVL new+4(FP), CX 194 MOVL old+8(FP), DX 195 MOVL size+12(FP), SI 196 CALL *runtime_vdso(SB) 197 MOVL AX, ret+16(FP) 198 RET 199 200 TEXT runtimesigfwd(SB),NOSPLIT,$12-16 201 MOVL sig+4(FP), AX 202 MOVL AX, 0(SP) 203 MOVL info+8(FP), AX 204 MOVL AX, 4(SP) 205 MOVL ctx+12(FP), AX 206 MOVL AX, 8(SP) 207 MOVL fn+0(FP), AX 208 CALL AX 209 RET 210 211 TEXT runtimesigtramp(SB),NOSPLIT,$12 212 MOVL sig+0(FP), BX 213 MOVL BX, 0(SP) 214 MOVL info+4(FP), BX 215 MOVL BX, 4(SP) 216 MOVL context+8(FP), BX 217 MOVL BX, 8(SP) 218 CALL runtimesigtrampgo(SB) 219 RET 220 221 TEXT runtimesigreturn(SB),NOSPLIT,$0 222 MOVL $173, AX // rt_sigreturn 223 // Sigreturn expects same SP as signal handler, 224 // so cannot CALL *runtime._vsdo(SB) here. 225 INT $0x80 226 INT $3 // not reached 227 RET 228 229 TEXT runtimemmap(SB),NOSPLIT,$0 230 MOVL $192, AX // mmap2 231 MOVL addr+0(FP), BX 232 MOVL n+4(FP), CX 233 MOVL prot+8(FP), DX 234 MOVL flags+12(FP), SI 235 MOVL fd+16(FP), DI 236 MOVL off+20(FP), BP 237 SHRL $12, BP 238 CALL *runtime_vdso(SB) 239 CMPL AX, $0xfffff001 240 JLS 3(PC) 241 NOTL AX 242 INCL AX 243 MOVL AX, ret+24(FP) 244 RET 245 246 TEXT runtimemunmap(SB),NOSPLIT,$0 247 MOVL $91, AX // munmap 248 MOVL addr+0(FP), BX 249 MOVL n+4(FP), CX 250 CALL *runtime_vdso(SB) 251 CMPL AX, $0xfffff001 252 JLS 2(PC) 253 INT $3 254 RET 255 256 TEXT runtimemadvise(SB),NOSPLIT,$0 257 MOVL $219, AX // madvise 258 MOVL addr+0(FP), BX 259 MOVL n+4(FP), CX 260 MOVL flags+8(FP), DX 261 CALL *runtime_vdso(SB) 262 // ignore failure - maybe pages are locked 263 RET 264 265 // int32 futex(int32 *uaddr, int32 op, int32 val, 266 // struct timespec *timeout, int32 *uaddr2, int32 val2); 267 TEXT runtimefutex(SB),NOSPLIT,$0 268 MOVL $240, AX // futex 269 MOVL addr+0(FP), BX 270 MOVL op+4(FP), CX 271 MOVL val+8(FP), DX 272 MOVL ts+12(FP), SI 273 MOVL addr2+16(FP), DI 274 MOVL val3+20(FP), BP 275 CALL *runtime_vdso(SB) 276 MOVL AX, ret+24(FP) 277 RET 278 279 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 280 TEXT runtimeclone(SB),NOSPLIT,$0 281 MOVL $120, AX // clone 282 MOVL flags+0(FP), BX 283 MOVL stack+4(FP), CX 284 MOVL $0, DX // parent tid ptr 285 MOVL $0, DI // child tid ptr 286 287 // Copy mp, gp, fn off parent stack for use by child. 288 SUBL $16, CX 289 MOVL mm+8(FP), SI 290 MOVL SI, 0(CX) 291 MOVL gg+12(FP), SI 292 MOVL SI, 4(CX) 293 MOVL fn+16(FP), SI 294 MOVL SI, 8(CX) 295 MOVL $1234, 12(CX) 296 297 // cannot use CALL *runtime_vdso(SB) here, because 298 // the stack changes during the system call (after 299 // CALL *runtime_vdso(SB), the child is still using 300 // the parent's stack when executing its RET instruction). 301 INT $0x80 302 303 // In parent, return. 304 CMPL AX, $0 305 JEQ 3(PC) 306 MOVL AX, ret+20(FP) 307 RET 308 309 // Paranoia: check that SP is as we expect. 310 MOVL 12(SP), BP 311 CMPL BP, $1234 312 JEQ 2(PC) 313 INT $3 314 315 // Initialize AX to Linux tid 316 MOVL $224, AX 317 CALL *runtime_vdso(SB) 318 319 MOVL 0(SP), BX // m 320 MOVL 4(SP), DX // g 321 MOVL 8(SP), SI // fn 322 323 CMPL BX, $0 324 JEQ nog 325 CMPL DX, $0 326 JEQ nog 327 328 MOVL AX, m_procid(BX) // save tid as m->procid 329 330 // set up ldt 7+id to point at m->tls. 331 // newosproc left the id in tls[0]. 332 LEAL m_tls(BX), BP 333 MOVL 0(BP), DI 334 ADDL $7, DI // m0 is LDT#7. count up. 335 // setldt(tls#, &tls, sizeof tls) 336 PUSHAL // save registers 337 PUSHL $32 // sizeof tls 338 PUSHL BP // &tls 339 PUSHL DI // tls # 340 CALL runtimesetldt(SB) 341 POPL AX 342 POPL AX 343 POPL AX 344 POPAL 345 346 // Now segment is established. Initialize m, g. 347 get_tls(AX) 348 MOVL DX, g(AX) 349 MOVL BX, g_m(DX) 350 351 CALL runtimestackcheck(SB) // smashes AX, CX 352 MOVL 0(DX), DX // paranoia; check they are not nil 353 MOVL 0(BX), BX 354 355 // more paranoia; check that stack splitting code works 356 PUSHAL 357 CALL runtimeemptyfunc(SB) 358 POPAL 359 360 nog: 361 CALL SI // fn() 362 CALL runtimeexit1(SB) 363 MOVL $0x1234, 0x1005 364 365 TEXT runtimesigaltstack(SB),NOSPLIT,$-8 366 MOVL $186, AX // sigaltstack 367 MOVL new+4(SP), BX 368 MOVL old+8(SP), CX 369 CALL *runtime_vdso(SB) 370 CMPL AX, $0xfffff001 371 JLS 2(PC) 372 INT $3 373 RET 374 375 // <asm-i386/ldt.h> 376 // struct user_desc { 377 // unsigned int entry_number; 378 // unsigned long base_addr; 379 // unsigned int limit; 380 // unsigned int seg_32bit:1; 381 // unsigned int contents:2; 382 // unsigned int read_exec_only:1; 383 // unsigned int limit_in_pages:1; 384 // unsigned int seg_not_present:1; 385 // unsigned int useable:1; 386 // }; 387 #define SEG_32BIT 0x01 388 // contents are the 2 bits 0x02 and 0x04. 389 #define CONTENTS_DATA 0x00 390 #define CONTENTS_STACK 0x02 391 #define CONTENTS_CODE 0x04 392 #define READ_EXEC_ONLY 0x08 393 #define LIMIT_IN_PAGES 0x10 394 #define SEG_NOT_PRESENT 0x20 395 #define USEABLE 0x40 396 397 // setldt(int entry, int address, int limit) 398 TEXT runtimesetldt(SB),NOSPLIT,$32 399 MOVL entry+0(FP), BX // entry 400 MOVL address+4(FP), CX // base address 401 402 /* 403 * When linking against the system libraries, 404 * we use its pthread_create and let it set up %gs 405 * for us. When we do that, the private storage 406 * we get is not at 0(GS), but -4(GS). 407 * To insulate the rest of the tool chain from this 408 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us. 409 * To accommodate that rewrite, we translate 410 * the address here and bump the limit to 0xffffffff (no limit) 411 * so that -4(GS) maps to 0(address). 412 * Also, the final 0(GS) (current 4(CX)) has to point 413 * to itself, to mimic ELF. 414 */ 415 ADDL $0x4, CX // address 416 MOVL CX, 0(CX) 417 418 // set up user_desc 419 LEAL 16(SP), AX // struct user_desc 420 MOVL BX, 0(AX) 421 MOVL CX, 4(AX) 422 MOVL $0xfffff, 8(AX) 423 MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits 424 425 // call modify_ldt 426 MOVL $1, BX // func = 1 (write) 427 MOVL AX, CX // user_desc 428 MOVL $16, DX // sizeof(user_desc) 429 MOVL $123, AX // syscall - modify_ldt 430 CALL *runtime_vdso(SB) 431 432 // breakpoint on error 433 CMPL AX, $0xfffff001 434 JLS 2(PC) 435 INT $3 436 437 // compute segment selector - (entry*8+7) 438 MOVL entry+0(FP), AX 439 SHLL $3, AX 440 ADDL $7, AX 441 MOVW AX, GS 442 443 RET 444 445 TEXT runtimeosyield(SB),NOSPLIT,$0 446 MOVL $158, AX 447 CALL *runtime_vdso(SB) 448 RET 449 450 TEXT runtimesched_getaffinity(SB),NOSPLIT,$0 451 MOVL $242, AX // syscall - sched_getaffinity 452 MOVL pid+0(FP), BX 453 MOVL len+4(FP), CX 454 MOVL buf+8(FP), DX 455 CALL *runtime_vdso(SB) 456 MOVL AX, ret+12(FP) 457 RET 458 459 // int32 runtimeepollcreate(int32 size); 460 TEXT runtimeepollcreate(SB),NOSPLIT,$0 461 MOVL $254, AX 462 MOVL size+0(FP), BX 463 CALL *runtime_vdso(SB) 464 MOVL AX, ret+4(FP) 465 RET 466 467 // int32 runtimeepollcreate1(int32 flags); 468 TEXT runtimeepollcreate1(SB),NOSPLIT,$0 469 MOVL $329, AX 470 MOVL flags+0(FP), BX 471 CALL *runtime_vdso(SB) 472 MOVL AX, ret+4(FP) 473 RET 474 475 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 476 TEXT runtimeepollctl(SB),NOSPLIT,$0 477 MOVL $255, AX 478 MOVL epfd+0(FP), BX 479 MOVL op+4(FP), CX 480 MOVL fd+8(FP), DX 481 MOVL ev+12(FP), SI 482 CALL *runtime_vdso(SB) 483 MOVL AX, ret+16(FP) 484 RET 485 486 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 487 TEXT runtimeepollwait(SB),NOSPLIT,$0 488 MOVL $256, AX 489 MOVL epfd+0(FP), BX 490 MOVL ev+4(FP), CX 491 MOVL nev+8(FP), DX 492 MOVL timeout+12(FP), SI 493 CALL *runtime_vdso(SB) 494 MOVL AX, ret+16(FP) 495 RET 496 497 // void runtimecloseonexec(int32 fd); 498 TEXT runtimecloseonexec(SB),NOSPLIT,$0 499 MOVL $55, AX // fcntl 500 MOVL fd+0(FP), BX // fd 501 MOVL $2, CX // F_SETFD 502 MOVL $1, DX // FD_CLOEXEC 503 CALL *runtime_vdso(SB) 504 RET 505