Home | History | Annotate | Download | only in 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 TEXT runtimeexit(SB),NOSPLIT,$0
     14 	MOVL	$252, AX	// syscall number
     15 	MOVL	code+0(FP), BX
     16 	CALL	*runtime_vdso(SB)
     17 	INT $3	// not reached
     18 	RET
     19 
     20 TEXT runtimeexit1(SB),NOSPLIT,$0
     21 	MOVL	$1, AX	// exit - exit the current os thread
     22 	MOVL	code+0(FP), BX
     23 	CALL	*runtime_vdso(SB)
     24 	INT $3	// not reached
     25 	RET
     26 
     27 TEXT runtimeopen(SB),NOSPLIT,$0
     28 	MOVL	$5, AX		// syscall - open
     29 	MOVL	name+0(FP), BX
     30 	MOVL	mode+4(FP), CX
     31 	MOVL	perm+8(FP), DX
     32 	CALL	*runtime_vdso(SB)
     33 	CMPL	AX, $0xfffff001
     34 	JLS	2(PC)
     35 	MOVL	$-1, AX
     36 	MOVL	AX, ret+12(FP)
     37 	RET
     38 
     39 TEXT runtimeclosefd(SB),NOSPLIT,$0
     40 	MOVL	$6, AX		// syscall - close
     41 	MOVL	fd+0(FP), BX
     42 	CALL	*runtime_vdso(SB)
     43 	CMPL	AX, $0xfffff001
     44 	JLS	2(PC)
     45 	MOVL	$-1, AX
     46 	MOVL	AX, ret+4(FP)
     47 	RET
     48 
     49 TEXT runtimewrite(SB),NOSPLIT,$0
     50 	MOVL	$4, AX		// syscall - write
     51 	MOVL	fd+0(FP), BX
     52 	MOVL	p+4(FP), CX
     53 	MOVL	n+8(FP), DX
     54 	CALL	*runtime_vdso(SB)
     55 	CMPL	AX, $0xfffff001
     56 	JLS	2(PC)
     57 	MOVL	$-1, AX
     58 	MOVL	AX, ret+12(FP)
     59 	RET
     60 
     61 TEXT runtimeread(SB),NOSPLIT,$0
     62 	MOVL	$3, AX		// syscall - read
     63 	MOVL	fd+0(FP), BX
     64 	MOVL	p+4(FP), CX
     65 	MOVL	n+8(FP), DX
     66 	CALL	*runtime_vdso(SB)
     67 	CMPL	AX, $0xfffff001
     68 	JLS	2(PC)
     69 	MOVL	$-1, AX
     70 	MOVL	AX, ret+12(FP)
     71 	RET
     72 
     73 TEXT runtimegetrlimit(SB),NOSPLIT,$0
     74 	MOVL	$191, AX		// syscall - ugetrlimit
     75 	MOVL	kind+0(FP), BX
     76 	MOVL	limit+4(FP), CX
     77 	CALL	*runtime_vdso(SB)
     78 	MOVL	AX, ret+8(FP)
     79 	RET
     80 
     81 TEXT runtimeusleep(SB),NOSPLIT,$8
     82 	MOVL	$0, DX
     83 	MOVL	usec+0(FP), AX
     84 	MOVL	$1000000, CX
     85 	DIVL	CX
     86 	MOVL	AX, 0(SP)
     87 	MOVL	DX, 4(SP)
     88 
     89 	// select(0, 0, 0, 0, &tv)
     90 	MOVL	$142, AX
     91 	MOVL	$0, BX
     92 	MOVL	$0, CX
     93 	MOVL	$0, DX
     94 	MOVL	$0, SI
     95 	LEAL	0(SP), DI
     96 	CALL	*runtime_vdso(SB)
     97 	RET
     98 
     99 TEXT runtimegettid(SB),NOSPLIT,$0-4
    100 	MOVL	$224, AX	// syscall - gettid
    101 	CALL	*runtime_vdso(SB)
    102 	MOVL	AX, ret+0(FP)
    103 	RET
    104 
    105 TEXT runtimeraise(SB),NOSPLIT,$12
    106 	MOVL	$224, AX	// syscall - gettid
    107 	CALL	*runtime_vdso(SB)
    108 	MOVL	AX, BX	// arg 1 tid
    109 	MOVL	sig+0(FP), CX	// arg 2 signal
    110 	MOVL	$238, AX	// syscall - tkill
    111 	CALL	*runtime_vdso(SB)
    112 	RET
    113 
    114 TEXT runtimeraiseproc(SB),NOSPLIT,$12
    115 	MOVL	$20, AX	// syscall - getpid
    116 	CALL	*runtime_vdso(SB)
    117 	MOVL	AX, BX	// arg 1 pid
    118 	MOVL	sig+0(FP), CX	// arg 2 signal
    119 	MOVL	$37, AX	// syscall - kill
    120 	CALL	*runtime_vdso(SB)
    121 	RET
    122 
    123 TEXT runtimesetitimer(SB),NOSPLIT,$0-12
    124 	MOVL	$104, AX			// syscall - setitimer
    125 	MOVL	mode+0(FP), BX
    126 	MOVL	new+4(FP), CX
    127 	MOVL	old+8(FP), DX
    128 	CALL	*runtime_vdso(SB)
    129 	RET
    130 
    131 TEXT runtimemincore(SB),NOSPLIT,$0-16
    132 	MOVL	$218, AX			// syscall - mincore
    133 	MOVL	addr+0(FP), BX
    134 	MOVL	n+4(FP), CX
    135 	MOVL	dst+8(FP), DX
    136 	CALL	*runtime_vdso(SB)
    137 	MOVL	AX, ret+12(FP)
    138 	RET
    139 
    140 // func now() (sec int64, nsec int32)
    141 TEXT timenow(SB), NOSPLIT, $32
    142 	MOVL	$265, AX			// syscall - clock_gettime
    143 	MOVL	$0, BX		// CLOCK_REALTIME
    144 	LEAL	8(SP), CX
    145 	MOVL	$0, DX
    146 	CALL	*runtime_vdso(SB)
    147 	MOVL	8(SP), AX	// sec
    148 	MOVL	12(SP), BX	// nsec
    149 
    150 	// sec is in AX, nsec in BX
    151 	MOVL	AX, sec+0(FP)
    152 	MOVL	$0, sec+4(FP)
    153 	MOVL	BX, nsec+8(FP)
    154 	RET
    155 
    156 // int64 nanotime(void) so really
    157 // void nanotime(int64 *nsec)
    158 TEXT runtimenanotime(SB), NOSPLIT, $32
    159 	MOVL	$265, AX			// syscall - clock_gettime
    160 	MOVL	$1, BX		// CLOCK_MONOTONIC
    161 	LEAL	8(SP), CX
    162 	MOVL	$0, DX
    163 	CALL	*runtime_vdso(SB)
    164 	MOVL	8(SP), AX	// sec
    165 	MOVL	12(SP), BX	// nsec
    166 
    167 	// sec is in AX, nsec in BX
    168 	// convert to DX:AX nsec
    169 	MOVL	$1000000000, CX
    170 	MULL	CX
    171 	ADDL	BX, AX
    172 	ADCL	$0, DX
    173 
    174 	MOVL	AX, ret_lo+0(FP)
    175 	MOVL	DX, ret_hi+4(FP)
    176 	RET
    177 
    178 TEXT runtimertsigprocmask(SB),NOSPLIT,$0
    179 	MOVL	$175, AX		// syscall entry
    180 	MOVL	sig+0(FP), BX
    181 	MOVL	new+4(FP), CX
    182 	MOVL	old+8(FP), DX
    183 	MOVL	size+12(FP), SI
    184 	CALL	*runtime_vdso(SB)
    185 	CMPL	AX, $0xfffff001
    186 	JLS	2(PC)
    187 	INT $3
    188 	RET
    189 
    190 TEXT runtimert_sigaction(SB),NOSPLIT,$0
    191 	MOVL	$174, AX		// syscall - rt_sigaction
    192 	MOVL	sig+0(FP), BX
    193 	MOVL	new+4(FP), CX
    194 	MOVL	old+8(FP), DX
    195 	MOVL	size+12(FP), SI
    196 	CALL	*runtime_vdso(SB)
    197 	MOVL	AX, ret+16(FP)
    198 	RET
    199 
    200 TEXT runtimesigfwd(SB),NOSPLIT,$12-16
    201 	MOVL	sig+4(FP), AX
    202 	MOVL	AX, 0(SP)
    203 	MOVL	info+8(FP), AX
    204 	MOVL	AX, 4(SP)
    205 	MOVL	ctx+12(FP), AX
    206 	MOVL	AX, 8(SP)
    207 	MOVL	fn+0(FP), AX
    208 	CALL	AX
    209 	RET
    210 
    211 TEXT runtimesigtramp(SB),NOSPLIT,$12
    212 	MOVL	sig+0(FP), BX
    213 	MOVL	BX, 0(SP)
    214 	MOVL	info+4(FP), BX
    215 	MOVL	BX, 4(SP)
    216 	MOVL	context+8(FP), BX
    217 	MOVL	BX, 8(SP)
    218 	CALL	runtimesigtrampgo(SB)
    219 	RET
    220 
    221 TEXT runtimesigreturn(SB),NOSPLIT,$0
    222 	MOVL	$173, AX	// rt_sigreturn
    223 	// Sigreturn expects same SP as signal handler,
    224 	// so cannot CALL *runtime._vsdo(SB) here.
    225 	INT	$0x80
    226 	INT $3	// not reached
    227 	RET
    228 
    229 TEXT runtimemmap(SB),NOSPLIT,$0
    230 	MOVL	$192, AX	// mmap2
    231 	MOVL	addr+0(FP), BX
    232 	MOVL	n+4(FP), CX
    233 	MOVL	prot+8(FP), DX
    234 	MOVL	flags+12(FP), SI
    235 	MOVL	fd+16(FP), DI
    236 	MOVL	off+20(FP), BP
    237 	SHRL	$12, BP
    238 	CALL	*runtime_vdso(SB)
    239 	CMPL	AX, $0xfffff001
    240 	JLS	3(PC)
    241 	NOTL	AX
    242 	INCL	AX
    243 	MOVL	AX, ret+24(FP)
    244 	RET
    245 
    246 TEXT runtimemunmap(SB),NOSPLIT,$0
    247 	MOVL	$91, AX	// munmap
    248 	MOVL	addr+0(FP), BX
    249 	MOVL	n+4(FP), CX
    250 	CALL	*runtime_vdso(SB)
    251 	CMPL	AX, $0xfffff001
    252 	JLS	2(PC)
    253 	INT $3
    254 	RET
    255 
    256 TEXT runtimemadvise(SB),NOSPLIT,$0
    257 	MOVL	$219, AX	// madvise
    258 	MOVL	addr+0(FP), BX
    259 	MOVL	n+4(FP), CX
    260 	MOVL	flags+8(FP), DX
    261 	CALL	*runtime_vdso(SB)
    262 	// ignore failure - maybe pages are locked
    263 	RET
    264 
    265 // int32 futex(int32 *uaddr, int32 op, int32 val,
    266 //	struct timespec *timeout, int32 *uaddr2, int32 val2);
    267 TEXT runtimefutex(SB),NOSPLIT,$0
    268 	MOVL	$240, AX	// futex
    269 	MOVL	addr+0(FP), BX
    270 	MOVL	op+4(FP), CX
    271 	MOVL	val+8(FP), DX
    272 	MOVL	ts+12(FP), SI
    273 	MOVL	addr2+16(FP), DI
    274 	MOVL	val3+20(FP), BP
    275 	CALL	*runtime_vdso(SB)
    276 	MOVL	AX, ret+24(FP)
    277 	RET
    278 
    279 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
    280 TEXT runtimeclone(SB),NOSPLIT,$0
    281 	MOVL	$120, AX	// clone
    282 	MOVL	flags+0(FP), BX
    283 	MOVL	stack+4(FP), CX
    284 	MOVL	$0, DX	// parent tid ptr
    285 	MOVL	$0, DI	// child tid ptr
    286 
    287 	// Copy mp, gp, fn off parent stack for use by child.
    288 	SUBL	$16, CX
    289 	MOVL	mm+8(FP), SI
    290 	MOVL	SI, 0(CX)
    291 	MOVL	gg+12(FP), SI
    292 	MOVL	SI, 4(CX)
    293 	MOVL	fn+16(FP), SI
    294 	MOVL	SI, 8(CX)
    295 	MOVL	$1234, 12(CX)
    296 
    297 	// cannot use CALL *runtime_vdso(SB) here, because
    298 	// the stack changes during the system call (after
    299 	// CALL *runtime_vdso(SB), the child is still using
    300 	// the parent's stack when executing its RET instruction).
    301 	INT	$0x80
    302 
    303 	// In parent, return.
    304 	CMPL	AX, $0
    305 	JEQ	3(PC)
    306 	MOVL	AX, ret+20(FP)
    307 	RET
    308 
    309 	// Paranoia: check that SP is as we expect.
    310 	MOVL	12(SP), BP
    311 	CMPL	BP, $1234
    312 	JEQ	2(PC)
    313 	INT	$3
    314 
    315 	// Initialize AX to Linux tid
    316 	MOVL	$224, AX
    317 	CALL	*runtime_vdso(SB)
    318 
    319 	MOVL	0(SP), BX	    // m
    320 	MOVL	4(SP), DX	    // g
    321 	MOVL	8(SP), SI	    // fn
    322 
    323 	CMPL	BX, $0
    324 	JEQ	nog
    325 	CMPL	DX, $0
    326 	JEQ	nog
    327 
    328 	MOVL	AX, m_procid(BX)	// save tid as m->procid
    329 
    330 	// set up ldt 7+id to point at m->tls.
    331 	// newosproc left the id in tls[0].
    332 	LEAL	m_tls(BX), BP
    333 	MOVL	0(BP), DI
    334 	ADDL	$7, DI	// m0 is LDT#7. count up.
    335 	// setldt(tls#, &tls, sizeof tls)
    336 	PUSHAL	// save registers
    337 	PUSHL	$32	// sizeof tls
    338 	PUSHL	BP	// &tls
    339 	PUSHL	DI	// tls #
    340 	CALL	runtimesetldt(SB)
    341 	POPL	AX
    342 	POPL	AX
    343 	POPL	AX
    344 	POPAL
    345 
    346 	// Now segment is established.  Initialize m, g.
    347 	get_tls(AX)
    348 	MOVL	DX, g(AX)
    349 	MOVL	BX, g_m(DX)
    350 
    351 	CALL	runtimestackcheck(SB)	// smashes AX, CX
    352 	MOVL	0(DX), DX	// paranoia; check they are not nil
    353 	MOVL	0(BX), BX
    354 
    355 	// more paranoia; check that stack splitting code works
    356 	PUSHAL
    357 	CALL	runtimeemptyfunc(SB)
    358 	POPAL
    359 
    360 nog:
    361 	CALL	SI	// fn()
    362 	CALL	runtimeexit1(SB)
    363 	MOVL	$0x1234, 0x1005
    364 
    365 TEXT runtimesigaltstack(SB),NOSPLIT,$-8
    366 	MOVL	$186, AX	// sigaltstack
    367 	MOVL	new+4(SP), BX
    368 	MOVL	old+8(SP), CX
    369 	CALL	*runtime_vdso(SB)
    370 	CMPL	AX, $0xfffff001
    371 	JLS	2(PC)
    372 	INT	$3
    373 	RET
    374 
    375 // <asm-i386/ldt.h>
    376 // struct user_desc {
    377 //	unsigned int  entry_number;
    378 //	unsigned long base_addr;
    379 //	unsigned int  limit;
    380 //	unsigned int  seg_32bit:1;
    381 //	unsigned int  contents:2;
    382 //	unsigned int  read_exec_only:1;
    383 //	unsigned int  limit_in_pages:1;
    384 //	unsigned int  seg_not_present:1;
    385 //	unsigned int  useable:1;
    386 // };
    387 #define SEG_32BIT 0x01
    388 // contents are the 2 bits 0x02 and 0x04.
    389 #define CONTENTS_DATA 0x00
    390 #define CONTENTS_STACK 0x02
    391 #define CONTENTS_CODE 0x04
    392 #define READ_EXEC_ONLY 0x08
    393 #define LIMIT_IN_PAGES 0x10
    394 #define SEG_NOT_PRESENT 0x20
    395 #define USEABLE 0x40
    396 
    397 // setldt(int entry, int address, int limit)
    398 TEXT runtimesetldt(SB),NOSPLIT,$32
    399 	MOVL	entry+0(FP), BX	// entry
    400 	MOVL	address+4(FP), CX	// base address
    401 
    402 	/*
    403 	 * When linking against the system libraries,
    404 	 * we use its pthread_create and let it set up %gs
    405 	 * for us.  When we do that, the private storage
    406 	 * we get is not at 0(GS), but -4(GS).
    407 	 * To insulate the rest of the tool chain from this
    408 	 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us.
    409 	 * To accommodate that rewrite, we translate
    410 	 * the address here and bump the limit to 0xffffffff (no limit)
    411 	 * so that -4(GS) maps to 0(address).
    412 	 * Also, the final 0(GS) (current 4(CX)) has to point
    413 	 * to itself, to mimic ELF.
    414 	 */
    415 	ADDL	$0x4, CX	// address
    416 	MOVL	CX, 0(CX)
    417 
    418 	// set up user_desc
    419 	LEAL	16(SP), AX	// struct user_desc
    420 	MOVL	BX, 0(AX)
    421 	MOVL	CX, 4(AX)
    422 	MOVL	$0xfffff, 8(AX)
    423 	MOVL	$(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX)	// flag bits
    424 
    425 	// call modify_ldt
    426 	MOVL	$1, BX	// func = 1 (write)
    427 	MOVL	AX, CX	// user_desc
    428 	MOVL	$16, DX	// sizeof(user_desc)
    429 	MOVL	$123, AX	// syscall - modify_ldt
    430 	CALL	*runtime_vdso(SB)
    431 
    432 	// breakpoint on error
    433 	CMPL AX, $0xfffff001
    434 	JLS 2(PC)
    435 	INT $3
    436 
    437 	// compute segment selector - (entry*8+7)
    438 	MOVL	entry+0(FP), AX
    439 	SHLL	$3, AX
    440 	ADDL	$7, AX
    441 	MOVW	AX, GS
    442 
    443 	RET
    444 
    445 TEXT runtimeosyield(SB),NOSPLIT,$0
    446 	MOVL	$158, AX
    447 	CALL	*runtime_vdso(SB)
    448 	RET
    449 
    450 TEXT runtimesched_getaffinity(SB),NOSPLIT,$0
    451 	MOVL	$242, AX		// syscall - sched_getaffinity
    452 	MOVL	pid+0(FP), BX
    453 	MOVL	len+4(FP), CX
    454 	MOVL	buf+8(FP), DX
    455 	CALL	*runtime_vdso(SB)
    456 	MOVL	AX, ret+12(FP)
    457 	RET
    458 
    459 // int32 runtimeepollcreate(int32 size);
    460 TEXT runtimeepollcreate(SB),NOSPLIT,$0
    461 	MOVL    $254, AX
    462 	MOVL	size+0(FP), BX
    463 	CALL	*runtime_vdso(SB)
    464 	MOVL	AX, ret+4(FP)
    465 	RET
    466 
    467 // int32 runtimeepollcreate1(int32 flags);
    468 TEXT runtimeepollcreate1(SB),NOSPLIT,$0
    469 	MOVL    $329, AX
    470 	MOVL	flags+0(FP), BX
    471 	CALL	*runtime_vdso(SB)
    472 	MOVL	AX, ret+4(FP)
    473 	RET
    474 
    475 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
    476 TEXT runtimeepollctl(SB),NOSPLIT,$0
    477 	MOVL	$255, AX
    478 	MOVL	epfd+0(FP), BX
    479 	MOVL	op+4(FP), CX
    480 	MOVL	fd+8(FP), DX
    481 	MOVL	ev+12(FP), SI
    482 	CALL	*runtime_vdso(SB)
    483 	MOVL	AX, ret+16(FP)
    484 	RET
    485 
    486 // int32 runtimeepollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
    487 TEXT runtimeepollwait(SB),NOSPLIT,$0
    488 	MOVL	$256, AX
    489 	MOVL	epfd+0(FP), BX
    490 	MOVL	ev+4(FP), CX
    491 	MOVL	nev+8(FP), DX
    492 	MOVL	timeout+12(FP), SI
    493 	CALL	*runtime_vdso(SB)
    494 	MOVL	AX, ret+16(FP)
    495 	RET
    496 
    497 // void runtimecloseonexec(int32 fd);
    498 TEXT runtimecloseonexec(SB),NOSPLIT,$0
    499 	MOVL	$55, AX  // fcntl
    500 	MOVL	fd+0(FP), BX  // fd
    501 	MOVL	$2, CX  // F_SETFD
    502 	MOVL	$1, DX  // FD_CLOEXEC
    503 	CALL	*runtime_vdso(SB)
    504 	RET
    505