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