Text file
src/runtime/sys_linux_386.s
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 #define SYS_exit 1
28 #define SYS_read 3
29 #define SYS_write 4
30 #define SYS_open 5
31 #define SYS_close 6
32 #define SYS_getpid 20
33 #define SYS_access 33
34 #define SYS_kill 37
35 #define SYS_pipe 42
36 #define SYS_brk 45
37 #define SYS_fcntl 55
38 #define SYS_munmap 91
39 #define SYS_socketcall 102
40 #define SYS_setittimer 104
41 #define SYS_clone 120
42 #define SYS_sched_yield 158
43 #define SYS_nanosleep 162
44 #define SYS_rt_sigreturn 173
45 #define SYS_rt_sigaction 174
46 #define SYS_rt_sigprocmask 175
47 #define SYS_sigaltstack 186
48 #define SYS_mmap2 192
49 #define SYS_mincore 218
50 #define SYS_madvise 219
51 #define SYS_gettid 224
52 #define SYS_futex 240
53 #define SYS_sched_getaffinity 242
54 #define SYS_set_thread_area 243
55 #define SYS_exit_group 252
56 #define SYS_epoll_create 254
57 #define SYS_epoll_ctl 255
58 #define SYS_epoll_wait 256
59 #define SYS_timer_create 259
60 #define SYS_timer_settime 260
61 #define SYS_timer_delete 263
62 #define SYS_clock_gettime 265
63 #define SYS_tgkill 270
64 #define SYS_epoll_create1 329
65 #define SYS_pipe2 331
66
67 TEXT runtime·exit(SB),NOSPLIT,$0
68 MOVL $SYS_exit_group, AX
69 MOVL code+0(FP), BX
70 INVOKE_SYSCALL
71 INT $3 // not reached
72 RET
73
74 TEXT exit1<>(SB),NOSPLIT,$0
75 MOVL $SYS_exit, AX
76 MOVL code+0(FP), BX
77 INVOKE_SYSCALL
78 INT $3 // not reached
79 RET
80
81 // func exitThread(wait *uint32)
82 TEXT runtime·exitThread(SB),NOSPLIT,$0-4
83 MOVL wait+0(FP), AX
84 // We're done using the stack.
85 MOVL $0, (AX)
86 MOVL $1, AX // exit (just this thread)
87 MOVL $0, BX // exit code
88 INT $0x80 // no stack; must not use CALL
89 // We may not even have a stack any more.
90 INT $3
91 JMP 0(PC)
92
93 TEXT runtime·open(SB),NOSPLIT,$0
94 MOVL $SYS_open, AX
95 MOVL name+0(FP), BX
96 MOVL mode+4(FP), CX
97 MOVL perm+8(FP), DX
98 INVOKE_SYSCALL
99 CMPL AX, $0xfffff001
100 JLS 2(PC)
101 MOVL $-1, AX
102 MOVL AX, ret+12(FP)
103 RET
104
105 TEXT runtime·closefd(SB),NOSPLIT,$0
106 MOVL $SYS_close, AX
107 MOVL fd+0(FP), BX
108 INVOKE_SYSCALL
109 CMPL AX, $0xfffff001
110 JLS 2(PC)
111 MOVL $-1, AX
112 MOVL AX, ret+4(FP)
113 RET
114
115 TEXT runtime·write1(SB),NOSPLIT,$0
116 MOVL $SYS_write, AX
117 MOVL fd+0(FP), BX
118 MOVL p+4(FP), CX
119 MOVL n+8(FP), DX
120 INVOKE_SYSCALL
121 MOVL AX, ret+12(FP)
122 RET
123
124 TEXT runtime·read(SB),NOSPLIT,$0
125 MOVL $SYS_read, AX
126 MOVL fd+0(FP), BX
127 MOVL p+4(FP), CX
128 MOVL n+8(FP), DX
129 INVOKE_SYSCALL
130 MOVL AX, ret+12(FP)
131 RET
132
133 // func pipe() (r, w int32, errno int32)
134 TEXT runtime·pipe(SB),NOSPLIT,$0-12
135 MOVL $SYS_pipe, AX
136 LEAL r+0(FP), BX
137 INVOKE_SYSCALL
138 MOVL AX, errno+8(FP)
139 RET
140
141 // func pipe2(flags int32) (r, w int32, errno int32)
142 TEXT runtime·pipe2(SB),NOSPLIT,$0-16
143 MOVL $SYS_pipe2, AX
144 LEAL r+4(FP), BX
145 MOVL flags+0(FP), CX
146 INVOKE_SYSCALL
147 MOVL AX, errno+12(FP)
148 RET
149
150 TEXT runtime·usleep(SB),NOSPLIT,$8
151 MOVL $0, DX
152 MOVL usec+0(FP), AX
153 MOVL $1000000, CX
154 DIVL CX
155 MOVL AX, 0(SP)
156 MOVL $1000, AX // usec to nsec
157 MULL DX
158 MOVL AX, 4(SP)
159
160 // nanosleep(&ts, 0)
161 MOVL $SYS_nanosleep, AX
162 LEAL 0(SP), BX
163 MOVL $0, CX
164 INVOKE_SYSCALL
165 RET
166
167 TEXT runtime·gettid(SB),NOSPLIT,$0-4
168 MOVL $SYS_gettid, AX
169 INVOKE_SYSCALL
170 MOVL AX, ret+0(FP)
171 RET
172
173 TEXT runtime·raise(SB),NOSPLIT,$12
174 MOVL $SYS_getpid, AX
175 INVOKE_SYSCALL
176 MOVL AX, BX // arg 1 pid
177 MOVL $SYS_gettid, AX
178 INVOKE_SYSCALL
179 MOVL AX, CX // arg 2 tid
180 MOVL sig+0(FP), DX // arg 3 signal
181 MOVL $SYS_tgkill, AX
182 INVOKE_SYSCALL
183 RET
184
185 TEXT runtime·raiseproc(SB),NOSPLIT,$12
186 MOVL $SYS_getpid, AX
187 INVOKE_SYSCALL
188 MOVL AX, BX // arg 1 pid
189 MOVL sig+0(FP), CX // arg 2 signal
190 MOVL $SYS_kill, AX
191 INVOKE_SYSCALL
192 RET
193
194 TEXT ·getpid(SB),NOSPLIT,$0-4
195 MOVL $SYS_getpid, AX
196 INVOKE_SYSCALL
197 MOVL AX, ret+0(FP)
198 RET
199
200 TEXT ·tgkill(SB),NOSPLIT,$0
201 MOVL $SYS_tgkill, AX
202 MOVL tgid+0(FP), BX
203 MOVL tid+4(FP), CX
204 MOVL sig+8(FP), DX
205 INVOKE_SYSCALL
206 RET
207
208 TEXT runtime·setitimer(SB),NOSPLIT,$0-12
209 MOVL $SYS_setittimer, AX
210 MOVL mode+0(FP), BX
211 MOVL new+4(FP), CX
212 MOVL old+8(FP), DX
213 INVOKE_SYSCALL
214 RET
215
216 TEXT runtime·timer_create(SB),NOSPLIT,$0-16
217 MOVL $SYS_timer_create, AX
218 MOVL clockid+0(FP), BX
219 MOVL sevp+4(FP), CX
220 MOVL timerid+8(FP), DX
221 INVOKE_SYSCALL
222 MOVL AX, ret+12(FP)
223 RET
224
225 TEXT runtime·timer_settime(SB),NOSPLIT,$0-20
226 MOVL $SYS_timer_settime, AX
227 MOVL timerid+0(FP), BX
228 MOVL flags+4(FP), CX
229 MOVL new+8(FP), DX
230 MOVL old+12(FP), SI
231 INVOKE_SYSCALL
232 MOVL AX, ret+16(FP)
233 RET
234
235 TEXT runtime·timer_delete(SB),NOSPLIT,$0-8
236 MOVL $SYS_timer_delete, AX
237 MOVL timerid+0(FP), BX
238 INVOKE_SYSCALL
239 MOVL AX, ret+4(FP)
240 RET
241
242 TEXT runtime·mincore(SB),NOSPLIT,$0-16
243 MOVL $SYS_mincore, AX
244 MOVL addr+0(FP), BX
245 MOVL n+4(FP), CX
246 MOVL dst+8(FP), DX
247 INVOKE_SYSCALL
248 MOVL AX, ret+12(FP)
249 RET
250
251 // func walltime() (sec int64, nsec int32)
252 TEXT runtime·walltime(SB), NOSPLIT, $8-12
253 // We don't know how much stack space the VDSO code will need,
254 // so switch to g0.
255
256 MOVL SP, BP // Save old SP; BP unchanged by C code.
257
258 get_tls(CX)
259 MOVL g(CX), AX
260 MOVL g_m(AX), SI // SI unchanged by C code.
261
262 // Set vdsoPC and vdsoSP for SIGPROF traceback.
263 // Save the old values on stack and restore them on exit,
264 // so this function is reentrant.
265 MOVL m_vdsoPC(SI), CX
266 MOVL m_vdsoSP(SI), DX
267 MOVL CX, 0(SP)
268 MOVL DX, 4(SP)
269
270 LEAL sec+0(FP), DX
271 MOVL -4(DX), CX
272 MOVL CX, m_vdsoPC(SI)
273 MOVL DX, m_vdsoSP(SI)
274
275 CMPL AX, m_curg(SI) // Only switch if on curg.
276 JNE noswitch
277
278 MOVL m_g0(SI), DX
279 MOVL (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
280
281 noswitch:
282 SUBL $16, SP // Space for results
283 ANDL $~15, SP // Align for C code
284
285 // Stack layout, depending on call path:
286 // x(SP) vDSO INVOKE_SYSCALL
287 // 12 ts.tv_nsec ts.tv_nsec
288 // 8 ts.tv_sec ts.tv_sec
289 // 4 &ts -
290 // 0 CLOCK_<id> -
291
292 MOVL runtime·vdsoClockgettimeSym(SB), AX
293 CMPL AX, $0
294 JEQ fallback
295
296 LEAL 8(SP), BX // &ts (struct timespec)
297 MOVL BX, 4(SP)
298 MOVL $0, 0(SP) // CLOCK_REALTIME
299 CALL AX
300 JMP finish
301
302 fallback:
303 MOVL $SYS_clock_gettime, AX
304 MOVL $0, BX // CLOCK_REALTIME
305 LEAL 8(SP), CX
306 INVOKE_SYSCALL
307
308 finish:
309 MOVL 8(SP), AX // sec
310 MOVL 12(SP), BX // nsec
311
312 MOVL BP, SP // Restore real SP
313 // Restore vdsoPC, vdsoSP
314 // We don't worry about being signaled between the two stores.
315 // If we are not in a signal handler, we'll restore vdsoSP to 0,
316 // and no one will care about vdsoPC. If we are in a signal handler,
317 // we cannot receive another signal.
318 MOVL 4(SP), CX
319 MOVL CX, m_vdsoSP(SI)
320 MOVL 0(SP), CX
321 MOVL CX, m_vdsoPC(SI)
322
323 // sec is in AX, nsec in BX
324 MOVL AX, sec_lo+0(FP)
325 MOVL $0, sec_hi+4(FP)
326 MOVL BX, nsec+8(FP)
327 RET
328
329 // int64 nanotime(void) so really
330 // void nanotime(int64 *nsec)
331 TEXT runtime·nanotime1(SB), NOSPLIT, $8-8
332 // Switch to g0 stack. See comment above in runtime·walltime.
333
334 MOVL SP, BP // Save old SP; BP unchanged by C code.
335
336 get_tls(CX)
337 MOVL g(CX), AX
338 MOVL g_m(AX), SI // SI unchanged by C code.
339
340 // Set vdsoPC and vdsoSP for SIGPROF traceback.
341 // Save the old values on stack and restore them on exit,
342 // so this function is reentrant.
343 MOVL m_vdsoPC(SI), CX
344 MOVL m_vdsoSP(SI), DX
345 MOVL CX, 0(SP)
346 MOVL DX, 4(SP)
347
348 LEAL ret+0(FP), DX
349 MOVL -4(DX), CX
350 MOVL CX, m_vdsoPC(SI)
351 MOVL DX, m_vdsoSP(SI)
352
353 CMPL AX, m_curg(SI) // Only switch if on curg.
354 JNE noswitch
355
356 MOVL m_g0(SI), DX
357 MOVL (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
358
359 noswitch:
360 SUBL $16, SP // Space for results
361 ANDL $~15, SP // Align for C code
362
363 MOVL runtime·vdsoClockgettimeSym(SB), AX
364 CMPL AX, $0
365 JEQ fallback
366
367 LEAL 8(SP), BX // &ts (struct timespec)
368 MOVL BX, 4(SP)
369 MOVL $1, 0(SP) // CLOCK_MONOTONIC
370 CALL AX
371 JMP finish
372
373 fallback:
374 MOVL $SYS_clock_gettime, AX
375 MOVL $1, BX // CLOCK_MONOTONIC
376 LEAL 8(SP), CX
377 INVOKE_SYSCALL
378
379 finish:
380 MOVL 8(SP), AX // sec
381 MOVL 12(SP), BX // nsec
382
383 MOVL BP, SP // Restore real SP
384 // Restore vdsoPC, vdsoSP
385 // We don't worry about being signaled between the two stores.
386 // If we are not in a signal handler, we'll restore vdsoSP to 0,
387 // and no one will care about vdsoPC. If we are in a signal handler,
388 // we cannot receive another signal.
389 MOVL 4(SP), CX
390 MOVL CX, m_vdsoSP(SI)
391 MOVL 0(SP), CX
392 MOVL CX, m_vdsoPC(SI)
393
394 // sec is in AX, nsec in BX
395 // convert to DX:AX nsec
396 MOVL $1000000000, CX
397 MULL CX
398 ADDL BX, AX
399 ADCL $0, DX
400
401 MOVL AX, ret_lo+0(FP)
402 MOVL DX, ret_hi+4(FP)
403 RET
404
405 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0
406 MOVL $SYS_rt_sigprocmask, AX
407 MOVL how+0(FP), BX
408 MOVL new+4(FP), CX
409 MOVL old+8(FP), DX
410 MOVL size+12(FP), SI
411 INVOKE_SYSCALL
412 CMPL AX, $0xfffff001
413 JLS 2(PC)
414 INT $3
415 RET
416
417 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
418 MOVL $SYS_rt_sigaction, AX
419 MOVL sig+0(FP), BX
420 MOVL new+4(FP), CX
421 MOVL old+8(FP), DX
422 MOVL size+12(FP), SI
423 INVOKE_SYSCALL
424 MOVL AX, ret+16(FP)
425 RET
426
427 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
428 MOVL fn+0(FP), AX
429 MOVL sig+4(FP), BX
430 MOVL info+8(FP), CX
431 MOVL ctx+12(FP), DX
432 MOVL SP, SI
433 SUBL $32, SP
434 ANDL $-15, SP // align stack: handler might be a C function
435 MOVL BX, 0(SP)
436 MOVL CX, 4(SP)
437 MOVL DX, 8(SP)
438 MOVL SI, 12(SP) // save SI: handler might be a Go function
439 CALL AX
440 MOVL 12(SP), AX
441 MOVL AX, SP
442 RET
443
444 // Called using C ABI.
445 TEXT runtime·sigtramp(SB),NOSPLIT,$28
446 // Save callee-saved C registers, since the caller may be a C signal handler.
447 MOVL BX, bx-4(SP)
448 MOVL BP, bp-8(SP)
449 MOVL SI, si-12(SP)
450 MOVL DI, di-16(SP)
451 // We don't save mxcsr or the x87 control word because sigtrampgo doesn't
452 // modify them.
453
454 MOVL (28+4)(SP), BX
455 MOVL BX, 0(SP)
456 MOVL (28+8)(SP), BX
457 MOVL BX, 4(SP)
458 MOVL (28+12)(SP), BX
459 MOVL BX, 8(SP)
460 CALL runtime·sigtrampgo(SB)
461
462 MOVL di-16(SP), DI
463 MOVL si-12(SP), SI
464 MOVL bp-8(SP), BP
465 MOVL bx-4(SP), BX
466 RET
467
468 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
469 JMP runtime·sigtramp(SB)
470
471 TEXT runtime·sigreturn(SB),NOSPLIT,$0
472 MOVL $SYS_rt_sigreturn, AX
473 // Sigreturn expects same SP as signal handler,
474 // so cannot CALL 0x10(GS) here.
475 INT $0x80
476 INT $3 // not reached
477 RET
478
479 TEXT runtime·mmap(SB),NOSPLIT,$0
480 MOVL $SYS_mmap2, AX
481 MOVL addr+0(FP), BX
482 MOVL n+4(FP), CX
483 MOVL prot+8(FP), DX
484 MOVL flags+12(FP), SI
485 MOVL fd+16(FP), DI
486 MOVL off+20(FP), BP
487 SHRL $12, BP
488 INVOKE_SYSCALL
489 CMPL AX, $0xfffff001
490 JLS ok
491 NOTL AX
492 INCL AX
493 MOVL $0, p+24(FP)
494 MOVL AX, err+28(FP)
495 RET
496 ok:
497 MOVL AX, p+24(FP)
498 MOVL $0, err+28(FP)
499 RET
500
501 TEXT runtime·munmap(SB),NOSPLIT,$0
502 MOVL $SYS_munmap, AX
503 MOVL addr+0(FP), BX
504 MOVL n+4(FP), CX
505 INVOKE_SYSCALL
506 CMPL AX, $0xfffff001
507 JLS 2(PC)
508 INT $3
509 RET
510
511 TEXT runtime·madvise(SB),NOSPLIT,$0
512 MOVL $SYS_madvise, AX
513 MOVL addr+0(FP), BX
514 MOVL n+4(FP), CX
515 MOVL flags+8(FP), DX
516 INVOKE_SYSCALL
517 MOVL AX, ret+12(FP)
518 RET
519
520 // int32 futex(int32 *uaddr, int32 op, int32 val,
521 // struct timespec *timeout, int32 *uaddr2, int32 val2);
522 TEXT runtime·futex(SB),NOSPLIT,$0
523 MOVL $SYS_futex, AX
524 MOVL addr+0(FP), BX
525 MOVL op+4(FP), CX
526 MOVL val+8(FP), DX
527 MOVL ts+12(FP), SI
528 MOVL addr2+16(FP), DI
529 MOVL val3+20(FP), BP
530 INVOKE_SYSCALL
531 MOVL AX, ret+24(FP)
532 RET
533
534 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
535 TEXT runtime·clone(SB),NOSPLIT,$0
536 MOVL $SYS_clone, AX
537 MOVL flags+0(FP), BX
538 MOVL stk+4(FP), CX
539 MOVL $0, DX // parent tid ptr
540 MOVL $0, DI // child tid ptr
541
542 // Copy mp, gp, fn off parent stack for use by child.
543 SUBL $16, CX
544 MOVL mp+8(FP), SI
545 MOVL SI, 0(CX)
546 MOVL gp+12(FP), SI
547 MOVL SI, 4(CX)
548 MOVL fn+16(FP), SI
549 MOVL SI, 8(CX)
550 MOVL $1234, 12(CX)
551
552 // cannot use CALL 0x10(GS) here, because the stack changes during the
553 // system call (after CALL 0x10(GS), the child is still using the
554 // parent's stack when executing its RET instruction).
555 INT $0x80
556
557 // In parent, return.
558 CMPL AX, $0
559 JEQ 3(PC)
560 MOVL AX, ret+20(FP)
561 RET
562
563 // Paranoia: check that SP is as we expect.
564 NOP SP // tell vet SP changed - stop checking offsets
565 MOVL 12(SP), BP
566 CMPL BP, $1234
567 JEQ 2(PC)
568 INT $3
569
570 // Initialize AX to Linux tid
571 MOVL $SYS_gettid, AX
572 INVOKE_SYSCALL
573
574 MOVL 0(SP), BX // m
575 MOVL 4(SP), DX // g
576 MOVL 8(SP), SI // fn
577
578 CMPL BX, $0
579 JEQ nog
580 CMPL DX, $0
581 JEQ nog
582
583 MOVL AX, m_procid(BX) // save tid as m->procid
584
585 // set up ldt 7+id to point at m->tls.
586 LEAL m_tls(BX), BP
587 MOVL m_id(BX), DI
588 ADDL $7, DI // m0 is LDT#7. count up.
589 // setldt(tls#, &tls, sizeof tls)
590 PUSHAL // save registers
591 PUSHL $32 // sizeof tls
592 PUSHL BP // &tls
593 PUSHL DI // tls #
594 CALL runtime·setldt(SB)
595 POPL AX
596 POPL AX
597 POPL AX
598 POPAL
599
600 // Now segment is established. Initialize m, g.
601 get_tls(AX)
602 MOVL DX, g(AX)
603 MOVL BX, g_m(DX)
604
605 CALL runtime·stackcheck(SB) // smashes AX, CX
606 MOVL 0(DX), DX // paranoia; check they are not nil
607 MOVL 0(BX), BX
608
609 // more paranoia; check that stack splitting code works
610 PUSHAL
611 CALL runtime·emptyfunc(SB)
612 POPAL
613
614 nog:
615 CALL SI // fn()
616 CALL exit1<>(SB)
617 MOVL $0x1234, 0x1005
618
619 TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
620 MOVL $SYS_sigaltstack, AX
621 MOVL new+0(FP), BX
622 MOVL old+4(FP), CX
623 INVOKE_SYSCALL
624 CMPL AX, $0xfffff001
625 JLS 2(PC)
626 INT $3
627 RET
628
629 // <asm-i386/ldt.h>
630 // struct user_desc {
631 // unsigned int entry_number;
632 // unsigned long base_addr;
633 // unsigned int limit;
634 // unsigned int seg_32bit:1;
635 // unsigned int contents:2;
636 // unsigned int read_exec_only:1;
637 // unsigned int limit_in_pages:1;
638 // unsigned int seg_not_present:1;
639 // unsigned int useable:1;
640 // };
641 #define SEG_32BIT 0x01
642 // contents are the 2 bits 0x02 and 0x04.
643 #define CONTENTS_DATA 0x00
644 #define CONTENTS_STACK 0x02
645 #define CONTENTS_CODE 0x04
646 #define READ_EXEC_ONLY 0x08
647 #define LIMIT_IN_PAGES 0x10
648 #define SEG_NOT_PRESENT 0x20
649 #define USEABLE 0x40
650
651 // `-1` means the kernel will pick a TLS entry on the first setldt call,
652 // which happens during runtime init, and that we'll store back the saved
653 // entry and reuse that on subsequent calls when creating new threads.
654 DATA runtime·tls_entry_number+0(SB)/4, $-1
655 GLOBL runtime·tls_entry_number(SB), NOPTR, $4
656
657 // setldt(int entry, int address, int limit)
658 // We use set_thread_area, which mucks with the GDT, instead of modify_ldt,
659 // which would modify the LDT, but is disabled on some kernels.
660 // The name, setldt, is a misnomer, although we leave this name as it is for
661 // the compatibility with other platforms.
662 TEXT runtime·setldt(SB),NOSPLIT,$32
663 MOVL base+4(FP), DX
664
665 #ifdef GOOS_android
666 // Android stores the TLS offset in runtime·tls_g.
667 SUBL runtime·tls_g(SB), DX
668 MOVL DX, 0(DX)
669 #else
670 /*
671 * When linking against the system libraries,
672 * we use its pthread_create and let it set up %gs
673 * for us. When we do that, the private storage
674 * we get is not at 0(GS), but -4(GS).
675 * To insulate the rest of the tool chain from this
676 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us.
677 * To accommodate that rewrite, we translate
678 * the address here and bump the limit to 0xffffffff (no limit)
679 * so that -4(GS) maps to 0(address).
680 * Also, the final 0(GS) (current 4(DX)) has to point
681 * to itself, to mimic ELF.
682 */
683 ADDL $0x4, DX // address
684 MOVL DX, 0(DX)
685 #endif
686
687 // get entry number
688 MOVL runtime·tls_entry_number(SB), CX
689
690 // set up user_desc
691 LEAL 16(SP), AX // struct user_desc
692 MOVL CX, 0(AX) // unsigned int entry_number
693 MOVL DX, 4(AX) // unsigned long base_addr
694 MOVL $0xfffff, 8(AX) // unsigned int limit
695 MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits
696
697 // call set_thread_area
698 MOVL AX, BX // user_desc
699 MOVL $SYS_set_thread_area, AX
700 // We can't call this via 0x10(GS) because this is called from setldt0 to set that up.
701 INT $0x80
702
703 // breakpoint on error
704 CMPL AX, $0xfffff001
705 JLS 2(PC)
706 INT $3
707
708 // read allocated entry number back out of user_desc
709 LEAL 16(SP), AX // get our user_desc back
710 MOVL 0(AX), AX
711
712 // store entry number if the kernel allocated it
713 CMPL CX, $-1
714 JNE 2(PC)
715 MOVL AX, runtime·tls_entry_number(SB)
716
717 // compute segment selector - (entry*8+3)
718 SHLL $3, AX
719 ADDL $3, AX
720 MOVW AX, GS
721
722 RET
723
724 TEXT runtime·osyield(SB),NOSPLIT,$0
725 MOVL $SYS_sched_yield, AX
726 INVOKE_SYSCALL
727 RET
728
729 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
730 MOVL $SYS_sched_getaffinity, AX
731 MOVL pid+0(FP), BX
732 MOVL len+4(FP), CX
733 MOVL buf+8(FP), DX
734 INVOKE_SYSCALL
735 MOVL AX, ret+12(FP)
736 RET
737
738 // int32 runtime·epollcreate(int32 size);
739 TEXT runtime·epollcreate(SB),NOSPLIT,$0
740 MOVL $SYS_epoll_create, AX
741 MOVL size+0(FP), BX
742 INVOKE_SYSCALL
743 MOVL AX, ret+4(FP)
744 RET
745
746 // int32 runtime·epollcreate1(int32 flags);
747 TEXT runtime·epollcreate1(SB),NOSPLIT,$0
748 MOVL $SYS_epoll_create1, AX
749 MOVL flags+0(FP), BX
750 INVOKE_SYSCALL
751 MOVL AX, ret+4(FP)
752 RET
753
754 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
755 TEXT runtime·epollctl(SB),NOSPLIT,$0
756 MOVL $SYS_epoll_ctl, AX
757 MOVL epfd+0(FP), BX
758 MOVL op+4(FP), CX
759 MOVL fd+8(FP), DX
760 MOVL ev+12(FP), SI
761 INVOKE_SYSCALL
762 MOVL AX, ret+16(FP)
763 RET
764
765 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
766 TEXT runtime·epollwait(SB),NOSPLIT,$0
767 MOVL $SYS_epoll_wait, AX
768 MOVL epfd+0(FP), BX
769 MOVL ev+4(FP), CX
770 MOVL nev+8(FP), DX
771 MOVL timeout+12(FP), SI
772 INVOKE_SYSCALL
773 MOVL AX, ret+16(FP)
774 RET
775
776 // void runtime·closeonexec(int32 fd);
777 TEXT runtime·closeonexec(SB),NOSPLIT,$0
778 MOVL $SYS_fcntl, AX
779 MOVL fd+0(FP), BX // fd
780 MOVL $2, CX // F_SETFD
781 MOVL $1, DX // FD_CLOEXEC
782 INVOKE_SYSCALL
783 RET
784
785 // func runtime·setNonblock(fd int32)
786 TEXT runtime·setNonblock(SB),NOSPLIT,$0-4
787 MOVL $SYS_fcntl, AX
788 MOVL fd+0(FP), BX // fd
789 MOVL $3, CX // F_GETFL
790 MOVL $0, DX
791 INVOKE_SYSCALL
792 MOVL fd+0(FP), BX // fd
793 MOVL $4, CX // F_SETFL
794 MOVL $0x800, DX // O_NONBLOCK
795 ORL AX, DX
796 MOVL $SYS_fcntl, AX
797 INVOKE_SYSCALL
798 RET
799
800 // int access(const char *name, int mode)
801 TEXT runtime·access(SB),NOSPLIT,$0
802 MOVL $SYS_access, AX
803 MOVL name+0(FP), BX
804 MOVL mode+4(FP), CX
805 INVOKE_SYSCALL
806 MOVL AX, ret+8(FP)
807 RET
808
809 // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
810 TEXT runtime·connect(SB),NOSPLIT,$0-16
811 // connect is implemented as socketcall(NR_socket, 3, *(rest of args))
812 // stack already should have fd, addr, addrlen.
813 MOVL $SYS_socketcall, AX
814 MOVL $3, BX // connect
815 LEAL fd+0(FP), CX
816 INVOKE_SYSCALL
817 MOVL AX, ret+12(FP)
818 RET
819
820 // int socket(int domain, int type, int protocol)
821 TEXT runtime·socket(SB),NOSPLIT,$0-16
822 // socket is implemented as socketcall(NR_socket, 1, *(rest of args))
823 // stack already should have domain, type, protocol.
824 MOVL $SYS_socketcall, AX
825 MOVL $1, BX // socket
826 LEAL domain+0(FP), CX
827 INVOKE_SYSCALL
828 MOVL AX, ret+12(FP)
829 RET
830
831 // func sbrk0() uintptr
832 TEXT runtime·sbrk0(SB),NOSPLIT,$0-4
833 // Implemented as brk(NULL).
834 MOVL $SYS_brk, AX
835 MOVL $0, BX // NULL
836 INVOKE_SYSCALL
837 MOVL AX, ret+0(FP)
838 RET
839
View as plain text