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