...

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_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
    63TEXT 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
    70TEXT 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)
    78TEXT 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
    89TEXT 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
   101TEXT 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
   111TEXT 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
   120TEXT 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)
   130TEXT 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
   138TEXT 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
   155TEXT runtime·gettid(SB),NOSPLIT,$0-4
   156	MOVL	$SYS_gettid, AX
   157	INVOKE_SYSCALL
   158	MOVL	AX, ret+0(FP)
   159	RET
   160
   161TEXT 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
   173TEXT 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
   182TEXT ·getpid(SB),NOSPLIT,$0-4
   183	MOVL	$SYS_getpid, AX
   184	INVOKE_SYSCALL
   185	MOVL	AX, ret+0(FP)
   186	RET
   187
   188TEXT ·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
   196TEXT 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
   204TEXT 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
   214TEXT 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
   224TEXT 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
   234TEXT 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
   241TEXT 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)
   251TEXT 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
   280noswitch:
   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
   301fallback:
   302	MOVL	$SYS_clock_gettime, AX
   303	MOVL	$0, BX		// CLOCK_REALTIME
   304	LEAL	8(SP), CX
   305	INVOKE_SYSCALL
   306
   307finish:
   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)
   330TEXT 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
   358noswitch:
   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
   372fallback:
   373	MOVL	$SYS_clock_gettime, AX
   374	MOVL	$1, BX		// CLOCK_MONOTONIC
   375	LEAL	8(SP), CX
   376	INVOKE_SYSCALL
   377
   378finish:
   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
   404TEXT 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
   416TEXT 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.
   427TEXT 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
   445TEXT 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.
   463TEXT 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
   486TEXT 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
   499TEXT 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
   507TEXT 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
   524ok:
   525	MOVL	AX, p+24(FP)
   526	MOVL	$0, err+28(FP)
   527	RET
   528
   529TEXT 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
   539TEXT 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);
   551TEXT 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);
   566TEXT 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));
   579TEXT 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
   658nog:
   659	CALL	SI	// fn()
   660	CALL	exit1<>(SB)
   661	MOVL	$0x1234, 0x1005
   662
   663TEXT 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.
   698DATA  runtime·tls_entry_number+0(SB)/4, $-1
   699GLOBL 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.
   706TEXT 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
   768TEXT runtime·osyield(SB),NOSPLIT,$0
   769	MOVL	$SYS_sched_yield, AX
   770	INVOKE_SYSCALL
   771	RET
   772
   773TEXT 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)
   783TEXT 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)
   792TEXT 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)
   803TEXT 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
   814TEXT 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

View as plain text