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