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_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  // Call the function stored in _cgo_sigaction using the GCC calling convention.
   414  TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0-16
   415  	MOVL	_cgo_sigaction(SB), AX
   416  	MOVL	sig+0(FP), BX
   417  	MOVL	new+4(FP), CX
   418  	MOVL	old+8(FP), DX
   419  	MOVL	SP, SI // align stack to call C function
   420  	SUBL	$32, SP
   421  	ANDL	$~15, SP
   422  	MOVL	BX, 0(SP)
   423  	MOVL	CX, 4(SP)
   424  	MOVL	DX, 8(SP)
   425  	MOVL	SI, 12(SP)
   426  	CALL	AX
   427  	MOVL	12(SP), BX
   428  	MOVL	BX, SP
   429  	MOVL	AX, ret+12(FP)
   430  	RET
   431  
   432  TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
   433  	MOVL	fn+0(FP), AX
   434  	MOVL	sig+4(FP), BX
   435  	MOVL	info+8(FP), CX
   436  	MOVL	ctx+12(FP), DX
   437  	MOVL	SP, SI
   438  	SUBL	$32, SP
   439  	ANDL	$-15, SP	// align stack: handler might be a C function
   440  	MOVL	BX, 0(SP)
   441  	MOVL	CX, 4(SP)
   442  	MOVL	DX, 8(SP)
   443  	MOVL	SI, 12(SP)	// save SI: handler might be a Go function
   444  	CALL	AX
   445  	MOVL	12(SP), AX
   446  	MOVL	AX, SP
   447  	RET
   448  
   449  // Called using C ABI.
   450  TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$28
   451  	// Save callee-saved C registers, since the caller may be a C signal handler.
   452  	MOVL	BX, bx-4(SP)
   453  	MOVL	BP, bp-8(SP)
   454  	MOVL	SI, si-12(SP)
   455  	MOVL	DI, di-16(SP)
   456  	// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
   457  	// modify them.
   458  
   459  	MOVL	(28+4)(SP), BX
   460  	MOVL	BX, 0(SP)
   461  	MOVL	(28+8)(SP), BX
   462  	MOVL	BX, 4(SP)
   463  	MOVL	(28+12)(SP), BX
   464  	MOVL	BX, 8(SP)
   465  	CALL	runtime·sigtrampgo(SB)
   466  
   467  	MOVL	di-16(SP), DI
   468  	MOVL	si-12(SP), SI
   469  	MOVL	bp-8(SP),  BP
   470  	MOVL	bx-4(SP),  BX
   471  	RET
   472  
   473  TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
   474  	JMP	runtime·sigtramp(SB)
   475  
   476  // For cgo unwinding to work, this function must look precisely like
   477  // the one in glibc. The glibc source code is:
   478  // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/i386/libc_sigaction.c;h=0665b41bbcd0986f0b33bf19a7ecbcedf9961d0a#l59
   479  // The code that cares about the precise instructions used is:
   480  // https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libgcc/config/i386/linux-unwind.h;h=5486223d60272c73d5103b29ae592d2ee998e1cf#l136
   481  //
   482  // For gdb unwinding to work, this function must look precisely like the one in
   483  // glibc and must be named "__restore_rt" or contain the string "sigaction" in
   484  // the name. The gdb source code is:
   485  // https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/i386-linux-tdep.c;h=a6adeca1b97416f7194341151a8ce30723a786a3#l168
   486  TEXT runtime·sigreturn__sigaction(SB),NOSPLIT,$0
   487  	MOVL	$SYS_rt_sigreturn, AX
   488  	// Sigreturn expects same SP as signal handler,
   489  	// so cannot CALL 0x10(GS) here.
   490  	INT	$0x80
   491  	INT	$3	// not reached
   492  	RET
   493  
   494  TEXT runtime·mmap(SB),NOSPLIT,$0
   495  	MOVL	$SYS_mmap2, AX
   496  	MOVL	addr+0(FP), BX
   497  	MOVL	n+4(FP), CX
   498  	MOVL	prot+8(FP), DX
   499  	MOVL	flags+12(FP), SI
   500  	MOVL	fd+16(FP), DI
   501  	MOVL	off+20(FP), BP
   502  	SHRL	$12, BP
   503  	INVOKE_SYSCALL
   504  	CMPL	AX, $0xfffff001
   505  	JLS	ok
   506  	NOTL	AX
   507  	INCL	AX
   508  	MOVL	$0, p+24(FP)
   509  	MOVL	AX, err+28(FP)
   510  	RET
   511  ok:
   512  	MOVL	AX, p+24(FP)
   513  	MOVL	$0, err+28(FP)
   514  	RET
   515  
   516  TEXT runtime·munmap(SB),NOSPLIT,$0
   517  	MOVL	$SYS_munmap, AX
   518  	MOVL	addr+0(FP), BX
   519  	MOVL	n+4(FP), CX
   520  	INVOKE_SYSCALL
   521  	CMPL	AX, $0xfffff001
   522  	JLS	2(PC)
   523  	INT $3
   524  	RET
   525  
   526  TEXT runtime·madvise(SB),NOSPLIT,$0
   527  	MOVL	$SYS_madvise, AX
   528  	MOVL	addr+0(FP), BX
   529  	MOVL	n+4(FP), CX
   530  	MOVL	flags+8(FP), DX
   531  	INVOKE_SYSCALL
   532  	MOVL	AX, ret+12(FP)
   533  	RET
   534  
   535  // int32 futex(int32 *uaddr, int32 op, int32 val,
   536  //	struct timespec *timeout, int32 *uaddr2, int32 val2);
   537  TEXT runtime·futex(SB),NOSPLIT,$0
   538  	MOVL	$SYS_futex, AX
   539  	MOVL	addr+0(FP), BX
   540  	MOVL	op+4(FP), CX
   541  	MOVL	val+8(FP), DX
   542  	MOVL	ts+12(FP), SI
   543  	MOVL	addr2+16(FP), DI
   544  	MOVL	val3+20(FP), BP
   545  	INVOKE_SYSCALL
   546  	MOVL	AX, ret+24(FP)
   547  	RET
   548  
   549  // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
   550  TEXT runtime·clone(SB),NOSPLIT,$0
   551  	MOVL	$SYS_clone, AX
   552  	MOVL	flags+0(FP), BX
   553  	MOVL	stk+4(FP), CX
   554  	MOVL	$0, DX	// parent tid ptr
   555  	MOVL	$0, DI	// child tid ptr
   556  
   557  	// Copy mp, gp, fn off parent stack for use by child.
   558  	SUBL	$16, CX
   559  	MOVL	mp+8(FP), SI
   560  	MOVL	SI, 0(CX)
   561  	MOVL	gp+12(FP), SI
   562  	MOVL	SI, 4(CX)
   563  	MOVL	fn+16(FP), SI
   564  	MOVL	SI, 8(CX)
   565  	MOVL	$1234, 12(CX)
   566  
   567  	// cannot use CALL 0x10(GS) here, because the stack changes during the
   568  	// system call (after CALL 0x10(GS), the child is still using the
   569  	// parent's stack when executing its RET instruction).
   570  	INT	$0x80
   571  
   572  	// In parent, return.
   573  	CMPL	AX, $0
   574  	JEQ	3(PC)
   575  	MOVL	AX, ret+20(FP)
   576  	RET
   577  
   578  	// Paranoia: check that SP is as we expect.
   579  	NOP	SP // tell vet SP changed - stop checking offsets
   580  	MOVL	12(SP), BP
   581  	CMPL	BP, $1234
   582  	JEQ	2(PC)
   583  	INT	$3
   584  
   585  	// Initialize AX to Linux tid
   586  	MOVL	$SYS_gettid, AX
   587  	INVOKE_SYSCALL
   588  
   589  	MOVL	0(SP), BX	    // m
   590  	MOVL	4(SP), DX	    // g
   591  	MOVL	8(SP), SI	    // fn
   592  
   593  	CMPL	BX, $0
   594  	JEQ	nog
   595  	CMPL	DX, $0
   596  	JEQ	nog
   597  
   598  	MOVL	AX, m_procid(BX)	// save tid as m->procid
   599  
   600  	// set up ldt 7+id to point at m->tls.
   601  	LEAL	m_tls(BX), BP
   602  	MOVL	m_id(BX), DI
   603  	ADDL	$7, DI	// m0 is LDT#7. count up.
   604  	// setldt(tls#, &tls, sizeof tls)
   605  	PUSHAL	// save registers
   606  	PUSHL	$32	// sizeof tls
   607  	PUSHL	BP	// &tls
   608  	PUSHL	DI	// tls #
   609  	CALL	runtime·setldt(SB)
   610  	POPL	AX
   611  	POPL	AX
   612  	POPL	AX
   613  	POPAL
   614  
   615  	// Now segment is established. Initialize m, g.
   616  	get_tls(AX)
   617  	MOVL	DX, g(AX)
   618  	MOVL	BX, g_m(DX)
   619  
   620  	CALL	runtime·stackcheck(SB)	// smashes AX, CX
   621  	MOVL	0(DX), DX	// paranoia; check they are not nil
   622  	MOVL	0(BX), BX
   623  
   624  	// more paranoia; check that stack splitting code works
   625  	PUSHAL
   626  	CALL	runtime·emptyfunc(SB)
   627  	POPAL
   628  
   629  nog:
   630  	CALL	SI	// fn()
   631  	CALL	exit1<>(SB)
   632  	MOVL	$0x1234, 0x1005
   633  
   634  TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
   635  	MOVL	$SYS_sigaltstack, AX
   636  	MOVL	new+0(FP), BX
   637  	MOVL	old+4(FP), CX
   638  	INVOKE_SYSCALL
   639  	CMPL	AX, $0xfffff001
   640  	JLS	2(PC)
   641  	INT	$3
   642  	RET
   643  
   644  // <asm-i386/ldt.h>
   645  // struct user_desc {
   646  //	unsigned int  entry_number;
   647  //	unsigned long base_addr;
   648  //	unsigned int  limit;
   649  //	unsigned int  seg_32bit:1;
   650  //	unsigned int  contents:2;
   651  //	unsigned int  read_exec_only:1;
   652  //	unsigned int  limit_in_pages:1;
   653  //	unsigned int  seg_not_present:1;
   654  //	unsigned int  useable:1;
   655  // };
   656  #define SEG_32BIT 0x01
   657  // contents are the 2 bits 0x02 and 0x04.
   658  #define CONTENTS_DATA 0x00
   659  #define CONTENTS_STACK 0x02
   660  #define CONTENTS_CODE 0x04
   661  #define READ_EXEC_ONLY 0x08
   662  #define LIMIT_IN_PAGES 0x10
   663  #define SEG_NOT_PRESENT 0x20
   664  #define USEABLE 0x40
   665  
   666  // `-1` means the kernel will pick a TLS entry on the first setldt call,
   667  // which happens during runtime init, and that we'll store back the saved
   668  // entry and reuse that on subsequent calls when creating new threads.
   669  DATA  runtime·tls_entry_number+0(SB)/4, $-1
   670  GLOBL runtime·tls_entry_number(SB), NOPTR, $4
   671  
   672  // setldt(int entry, int address, int limit)
   673  // We use set_thread_area, which mucks with the GDT, instead of modify_ldt,
   674  // which would modify the LDT, but is disabled on some kernels.
   675  // The name, setldt, is a misnomer, although we leave this name as it is for
   676  // the compatibility with other platforms.
   677  TEXT runtime·setldt(SB),NOSPLIT,$32
   678  	MOVL	base+4(FP), DX
   679  
   680  #ifdef GOOS_android
   681  	// Android stores the TLS offset in runtime·tls_g.
   682  	SUBL	runtime·tls_g(SB), DX
   683  	MOVL	DX, 0(DX)
   684  #else
   685  	/*
   686  	 * When linking against the system libraries,
   687  	 * we use its pthread_create and let it set up %gs
   688  	 * for us.  When we do that, the private storage
   689  	 * we get is not at 0(GS), but -4(GS).
   690  	 * To insulate the rest of the tool chain from this
   691  	 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us.
   692  	 * To accommodate that rewrite, we translate
   693  	 * the address here and bump the limit to 0xffffffff (no limit)
   694  	 * so that -4(GS) maps to 0(address).
   695  	 * Also, the final 0(GS) (current 4(DX)) has to point
   696  	 * to itself, to mimic ELF.
   697  	 */
   698  	ADDL	$0x4, DX	// address
   699  	MOVL	DX, 0(DX)
   700  #endif
   701  
   702  	// get entry number
   703  	MOVL	runtime·tls_entry_number(SB), CX
   704  
   705  	// set up user_desc
   706  	LEAL	16(SP), AX	// struct user_desc
   707  	MOVL	CX, 0(AX)	// unsigned int entry_number
   708  	MOVL	DX, 4(AX)	// unsigned long base_addr
   709  	MOVL	$0xfffff, 8(AX)	// unsigned int limit
   710  	MOVL	$(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX)	// flag bits
   711  
   712  	// call set_thread_area
   713  	MOVL	AX, BX	// user_desc
   714  	MOVL	$SYS_set_thread_area, AX
   715  	// We can't call this via 0x10(GS) because this is called from setldt0 to set that up.
   716  	INT     $0x80
   717  
   718  	// breakpoint on error
   719  	CMPL AX, $0xfffff001
   720  	JLS 2(PC)
   721  	INT $3
   722  
   723  	// read allocated entry number back out of user_desc
   724  	LEAL	16(SP), AX	// get our user_desc back
   725  	MOVL	0(AX), AX
   726  
   727  	// store entry number if the kernel allocated it
   728  	CMPL	CX, $-1
   729  	JNE	2(PC)
   730  	MOVL	AX, runtime·tls_entry_number(SB)
   731  
   732  	// compute segment selector - (entry*8+3)
   733  	SHLL	$3, AX
   734  	ADDL	$3, AX
   735  	MOVW	AX, GS
   736  
   737  	RET
   738  
   739  TEXT runtime·osyield(SB),NOSPLIT,$0
   740  	MOVL	$SYS_sched_yield, AX
   741  	INVOKE_SYSCALL
   742  	RET
   743  
   744  TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
   745  	MOVL	$SYS_sched_getaffinity, AX
   746  	MOVL	pid+0(FP), BX
   747  	MOVL	len+4(FP), CX
   748  	MOVL	buf+8(FP), DX
   749  	INVOKE_SYSCALL
   750  	MOVL	AX, ret+12(FP)
   751  	RET
   752  
   753  // int access(const char *name, int mode)
   754  TEXT runtime·access(SB),NOSPLIT,$0
   755  	MOVL	$SYS_access, AX
   756  	MOVL	name+0(FP), BX
   757  	MOVL	mode+4(FP), CX
   758  	INVOKE_SYSCALL
   759  	MOVL	AX, ret+8(FP)
   760  	RET
   761  
   762  // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
   763  TEXT runtime·connect(SB),NOSPLIT,$0-16
   764  	// connect is implemented as socketcall(NR_socket, 3, *(rest of args))
   765  	// stack already should have fd, addr, addrlen.
   766  	MOVL	$SYS_socketcall, AX
   767  	MOVL	$3, BX  // connect
   768  	LEAL	fd+0(FP), CX
   769  	INVOKE_SYSCALL
   770  	MOVL	AX, ret+12(FP)
   771  	RET
   772  
   773  // int socket(int domain, int type, int protocol)
   774  TEXT runtime·socket(SB),NOSPLIT,$0-16
   775  	// socket is implemented as socketcall(NR_socket, 1, *(rest of args))
   776  	// stack already should have domain, type, protocol.
   777  	MOVL	$SYS_socketcall, AX
   778  	MOVL	$1, BX  // socket
   779  	LEAL	domain+0(FP), CX
   780  	INVOKE_SYSCALL
   781  	MOVL	AX, ret+12(FP)
   782  	RET
   783  
   784  // func sbrk0() uintptr
   785  TEXT runtime·sbrk0(SB),NOSPLIT,$0-4
   786  	// Implemented as brk(NULL).
   787  	MOVL	$SYS_brk, AX
   788  	MOVL	$0, BX  // NULL
   789  	INVOKE_SYSCALL
   790  	MOVL	AX, ret+0(FP)
   791  	RET
   792  

View as plain text