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

View as plain text