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