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