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// System calls and other sys.stuff for 386, FreeBSD
6// /usr/src/sys/kern/syscalls.master for syscall numbers.
7//
8
9#include "go_asm.h"
10#include "go_tls.h"
11#include "textflag.h"
12
13#define CLOCK_REALTIME		0
14#define CLOCK_MONOTONIC		4
15
16#define SYS_exit		1
17#define SYS_read		3
18#define SYS_write		4
19#define SYS_open		5
20#define SYS_close		6
21#define SYS_getpid		20
22#define SYS_kill		37
23#define SYS_sigaltstack		53
24#define SYS_munmap		73
25#define SYS_madvise		75
26#define SYS_setitimer		83
27#define SYS_fcntl		92
28#define SYS_sysarch		165
29#define SYS___sysctl		202
30#define SYS_clock_gettime	232
31#define SYS_nanosleep		240
32#define SYS_issetugid		253
33#define SYS_sched_yield		331
34#define SYS_sigprocmask		340
35#define SYS_kqueue		362
36#define SYS_sigaction		416
37#define SYS_sigreturn		417
38#define SYS_thr_exit		431
39#define SYS_thr_self		432
40#define SYS_thr_kill		433
41#define SYS__umtx_op		454
42#define SYS_thr_new		455
43#define SYS_mmap		477
44#define SYS_cpuset_getaffinity	487
45#define SYS_pipe2 		542
46#define SYS_kevent		560
47
48TEXT runtime·sys_umtx_op(SB),NOSPLIT,$-4
49	MOVL	$SYS__umtx_op, AX
50	INT	$0x80
51	JAE	2(PC)
52	NEGL	AX
53	MOVL	AX, ret+20(FP)
54	RET
55
56TEXT runtime·thr_new(SB),NOSPLIT,$-4
57	MOVL	$SYS_thr_new, AX
58	INT	$0x80
59	JAE	2(PC)
60	NEGL	AX
61	MOVL	AX, ret+8(FP)
62	RET
63
64// Called by OS using C ABI.
65TEXT runtime·thr_start(SB),NOSPLIT,$0
66	NOP	SP	// tell vet SP changed - stop checking offsets
67	MOVL	4(SP), AX // m
68	MOVL	m_g0(AX), BX
69	LEAL	m_tls(AX), BP
70	MOVL	m_id(AX), DI
71	ADDL	$7, DI
72	PUSHAL
73	PUSHL	$32
74	PUSHL	BP
75	PUSHL	DI
76	CALL	runtime·setldt(SB)
77	POPL	AX
78	POPL	AX
79	POPL	AX
80	POPAL
81	get_tls(CX)
82	MOVL	BX, g(CX)
83
84	MOVL	AX, g_m(BX)
85	CALL	runtime·stackcheck(SB)		// smashes AX
86	CALL	runtime·mstart(SB)
87
88	MOVL	0, AX			// crash (not reached)
89
90// Exit the entire program (like C exit)
91TEXT runtime·exit(SB),NOSPLIT,$-4
92	MOVL	$SYS_exit, AX
93	INT	$0x80
94	MOVL	$0xf1, 0xf1  // crash
95	RET
96
97GLOBL exitStack<>(SB),RODATA,$8
98DATA exitStack<>+0x00(SB)/4, $0
99DATA exitStack<>+0x04(SB)/4, $0
100
101// func exitThread(wait *atomic.Uint32)
102TEXT runtime·exitThread(SB),NOSPLIT,$0-4
103	MOVL	wait+0(FP), AX
104	// We're done using the stack.
105	MOVL	$0, (AX)
106	// thr_exit takes a single pointer argument, which it expects
107	// on the stack. We want to pass 0, so switch over to a fake
108	// stack of 0s. It won't write to the stack.
109	MOVL	$exitStack<>(SB), SP
110	MOVL	$SYS_thr_exit, AX
111	INT	$0x80
112	MOVL	$0xf1, 0xf1  // crash
113	JMP	0(PC)
114
115TEXT runtime·open(SB),NOSPLIT,$-4
116	MOVL	$SYS_open, AX
117	INT	$0x80
118	JAE	2(PC)
119	MOVL	$-1, AX
120	MOVL	AX, ret+12(FP)
121	RET
122
123TEXT runtime·closefd(SB),NOSPLIT,$-4
124	MOVL	$SYS_close, AX
125	INT	$0x80
126	JAE	2(PC)
127	MOVL	$-1, AX
128	MOVL	AX, ret+4(FP)
129	RET
130
131TEXT runtime·read(SB),NOSPLIT,$-4
132	MOVL	$SYS_read, AX
133	INT	$0x80
134	JAE	2(PC)
135	NEGL	AX			// caller expects negative errno
136	MOVL	AX, ret+12(FP)
137	RET
138
139// func pipe2(flags int32) (r, w int32, errno int32)
140TEXT runtime·pipe2(SB),NOSPLIT,$12-16
141	MOVL	$SYS_pipe2, AX
142	LEAL	r+4(FP), BX
143	MOVL	BX, 4(SP)
144	MOVL	flags+0(FP), BX
145	MOVL	BX, 8(SP)
146	INT	$0x80
147	JAE	2(PC)
148	NEGL	AX
149	MOVL	AX, errno+12(FP)
150	RET
151
152TEXT runtime·write1(SB),NOSPLIT,$-4
153	MOVL	$SYS_write, AX
154	INT	$0x80
155	JAE	2(PC)
156	NEGL	AX			// caller expects negative errno
157	MOVL	AX, ret+12(FP)
158	RET
159
160TEXT runtime·thr_self(SB),NOSPLIT,$8-4
161	// thr_self(&0(FP))
162	LEAL	ret+0(FP), AX
163	MOVL	AX, 4(SP)
164	MOVL	$SYS_thr_self, AX
165	INT	$0x80
166	RET
167
168TEXT runtime·thr_kill(SB),NOSPLIT,$-4
169	// thr_kill(tid, sig)
170	MOVL	$SYS_thr_kill, AX
171	INT	$0x80
172	RET
173
174TEXT runtime·raiseproc(SB),NOSPLIT,$16
175	// getpid
176	MOVL	$SYS_getpid, AX
177	INT	$0x80
178	// kill(self, sig)
179	MOVL	AX, 4(SP)
180	MOVL	sig+0(FP), AX
181	MOVL	AX, 8(SP)
182	MOVL	$SYS_kill, AX
183	INT	$0x80
184	RET
185
186TEXT runtime·mmap(SB),NOSPLIT,$32
187	LEAL addr+0(FP), SI
188	LEAL	4(SP), DI
189	CLD
190	MOVSL
191	MOVSL
192	MOVSL
193	MOVSL
194	MOVSL
195	MOVSL
196	MOVL	$0, AX	// top 32 bits of file offset
197	STOSL
198	MOVL	$SYS_mmap, AX
199	INT	$0x80
200	JAE	ok
201	MOVL	$0, p+24(FP)
202	MOVL	AX, err+28(FP)
203	RET
204ok:
205	MOVL	AX, p+24(FP)
206	MOVL	$0, err+28(FP)
207	RET
208
209TEXT runtime·munmap(SB),NOSPLIT,$-4
210	MOVL	$SYS_munmap, AX
211	INT	$0x80
212	JAE	2(PC)
213	MOVL	$0xf1, 0xf1  // crash
214	RET
215
216TEXT runtime·madvise(SB),NOSPLIT,$-4
217	MOVL	$SYS_madvise, AX
218	INT	$0x80
219	JAE	2(PC)
220	MOVL	$-1, AX
221	MOVL	AX, ret+12(FP)
222	RET
223
224TEXT runtime·setitimer(SB), NOSPLIT, $-4
225	MOVL	$SYS_setitimer, AX
226	INT	$0x80
227	RET
228
229// func fallback_walltime() (sec int64, nsec int32)
230TEXT runtime·fallback_walltime(SB), NOSPLIT, $32-12
231	MOVL	$SYS_clock_gettime, AX
232	LEAL	12(SP), BX
233	MOVL	$CLOCK_REALTIME, 4(SP)
234	MOVL	BX, 8(SP)
235	INT	$0x80
236	MOVL	12(SP), AX	// sec
237	MOVL	16(SP), BX	// nsec
238
239	// sec is in AX, nsec in BX
240	MOVL	AX, sec_lo+0(FP)
241	MOVL	$0, sec_hi+4(FP)
242	MOVL	BX, nsec+8(FP)
243	RET
244
245// func fallback_nanotime() int64
246TEXT runtime·fallback_nanotime(SB), NOSPLIT, $32-8
247	MOVL	$SYS_clock_gettime, AX
248	LEAL	12(SP), BX
249	MOVL	$CLOCK_MONOTONIC, 4(SP)
250	MOVL	BX, 8(SP)
251	INT	$0x80
252	MOVL	12(SP), AX	// sec
253	MOVL	16(SP), BX	// nsec
254
255	// sec is in AX, nsec in BX
256	// convert to DX:AX nsec
257	MOVL	$1000000000, CX
258	MULL	CX
259	ADDL	BX, AX
260	ADCL	$0, DX
261
262	MOVL	AX, ret_lo+0(FP)
263	MOVL	DX, ret_hi+4(FP)
264	RET
265
266
267TEXT runtime·asmSigaction(SB),NOSPLIT,$-4
268	MOVL	$SYS_sigaction, AX
269	INT	$0x80
270	MOVL	AX, ret+12(FP)
271	RET
272
273TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
274	MOVL	fn+0(FP), AX
275	MOVL	sig+4(FP), BX
276	MOVL	info+8(FP), CX
277	MOVL	ctx+12(FP), DX
278	MOVL	SP, SI
279	SUBL	$32, SP
280	ANDL	$~15, SP	// align stack: handler might be a C function
281	MOVL	BX, 0(SP)
282	MOVL	CX, 4(SP)
283	MOVL	DX, 8(SP)
284	MOVL	SI, 12(SP)	// save SI: handler might be a Go function
285	CALL	AX
286	MOVL	12(SP), AX
287	MOVL	AX, SP
288	RET
289
290// Called by OS using C ABI.
291TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$12
292	NOP	SP	// tell vet SP changed - stop checking offsets
293	MOVL	16(SP), BX	// signo
294	MOVL	BX, 0(SP)
295	MOVL	20(SP), BX // info
296	MOVL	BX, 4(SP)
297	MOVL	24(SP), BX // context
298	MOVL	BX, 8(SP)
299	CALL	runtime·sigtrampgo(SB)
300
301	// call sigreturn
302	MOVL	24(SP), AX	// context
303	MOVL	$0, 0(SP)	// syscall gap
304	MOVL	AX, 4(SP)
305	MOVL	$SYS_sigreturn, AX
306	INT	$0x80
307	MOVL	$0xf1, 0xf1  // crash
308	RET
309
310TEXT runtime·sigaltstack(SB),NOSPLIT,$0
311	MOVL	$SYS_sigaltstack, AX
312	INT	$0x80
313	JAE	2(PC)
314	MOVL	$0xf1, 0xf1  // crash
315	RET
316
317TEXT runtime·usleep(SB),NOSPLIT,$20
318	MOVL	$0, DX
319	MOVL	usec+0(FP), AX
320	MOVL	$1000000, CX
321	DIVL	CX
322	MOVL	AX, 12(SP)		// tv_sec
323	MOVL	$1000, AX
324	MULL	DX
325	MOVL	AX, 16(SP)		// tv_nsec
326
327	MOVL	$0, 0(SP)
328	LEAL	12(SP), AX
329	MOVL	AX, 4(SP)		// arg 1 - rqtp
330	MOVL	$0, 8(SP)		// arg 2 - rmtp
331	MOVL	$SYS_nanosleep, AX
332	INT	$0x80
333	RET
334
335/*
336descriptor entry format for system call
337is the native machine format, ugly as it is:
338
339	2-byte limit
340	3-byte base
341	1-byte: 0x80=present, 0x60=dpl<<5, 0x1F=type
342	1-byte: 0x80=limit is *4k, 0x40=32-bit operand size,
343		0x0F=4 more bits of limit
344	1 byte: 8 more bits of base
345
346int i386_get_ldt(int, union ldt_entry *, int);
347int i386_set_ldt(int, const union ldt_entry *, int);
348
349*/
350
351// setldt(int entry, int address, int limit)
352TEXT runtime·setldt(SB),NOSPLIT,$32
353	MOVL	base+4(FP), BX
354	// see comment in sys_linux_386.s; freebsd is similar
355	ADDL	$0x4, BX
356
357	// set up data_desc
358	LEAL	16(SP), AX	// struct data_desc
359	MOVL	$0, 0(AX)
360	MOVL	$0, 4(AX)
361
362	MOVW	BX, 2(AX)
363	SHRL	$16, BX
364	MOVB	BX, 4(AX)
365	SHRL	$8, BX
366	MOVB	BX, 7(AX)
367
368	MOVW	$0xffff, 0(AX)
369	MOVB	$0xCF, 6(AX)	// 32-bit operand, 4k limit unit, 4 more bits of limit
370
371	MOVB	$0xF2, 5(AX)	// r/w data descriptor, dpl=3, present
372
373	// call i386_set_ldt(entry, desc, 1)
374	MOVL	$0xffffffff, 0(SP)	// auto-allocate entry and return in AX
375	MOVL	AX, 4(SP)
376	MOVL	$1, 8(SP)
377	CALL	i386_set_ldt<>(SB)
378
379	// compute segment selector - (entry*8+7)
380	SHLL	$3, AX
381	ADDL	$7, AX
382	MOVW	AX, GS
383	RET
384
385TEXT i386_set_ldt<>(SB),NOSPLIT,$16
386	LEAL	args+0(FP), AX	// 0(FP) == 4(SP) before SP got moved
387	MOVL	$0, 0(SP)	// syscall gap
388	MOVL	$1, 4(SP)
389	MOVL	AX, 8(SP)
390	MOVL	$SYS_sysarch, AX
391	INT	$0x80
392	JAE	2(PC)
393	INT	$3
394	RET
395
396TEXT runtime·sysctl(SB),NOSPLIT,$28
397	LEAL	mib+0(FP), SI
398	LEAL	4(SP), DI
399	CLD
400	MOVSL				// arg 1 - name
401	MOVSL				// arg 2 - namelen
402	MOVSL				// arg 3 - oldp
403	MOVSL				// arg 4 - oldlenp
404	MOVSL				// arg 5 - newp
405	MOVSL				// arg 6 - newlen
406	MOVL	$SYS___sysctl, AX
407	INT	$0x80
408	JAE	4(PC)
409	NEGL	AX
410	MOVL	AX, ret+24(FP)
411	RET
412	MOVL	$0, AX
413	MOVL	AX, ret+24(FP)
414	RET
415
416TEXT runtime·osyield(SB),NOSPLIT,$-4
417	MOVL	$SYS_sched_yield, AX
418	INT	$0x80
419	RET
420
421TEXT runtime·sigprocmask(SB),NOSPLIT,$16
422	MOVL	$0, 0(SP)		// syscall gap
423	MOVL	how+0(FP), AX		// arg 1 - how
424	MOVL	AX, 4(SP)
425	MOVL	new+4(FP), AX
426	MOVL	AX, 8(SP)		// arg 2 - set
427	MOVL	old+8(FP), AX
428	MOVL	AX, 12(SP)		// arg 3 - oset
429	MOVL	$SYS_sigprocmask, AX
430	INT	$0x80
431	JAE	2(PC)
432	MOVL	$0xf1, 0xf1  // crash
433	RET
434
435// int32 runtime·kqueue(void);
436TEXT runtime·kqueue(SB),NOSPLIT,$0
437	MOVL	$SYS_kqueue, AX
438	INT	$0x80
439	JAE	2(PC)
440	NEGL	AX
441	MOVL	AX, ret+0(FP)
442	RET
443
444// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
445TEXT runtime·kevent(SB),NOSPLIT,$0
446	MOVL	$SYS_kevent, AX
447	INT	$0x80
448	JAE	2(PC)
449	NEGL	AX
450	MOVL	AX, ret+24(FP)
451	RET
452
453// func fcntl(fd, cmd, arg int32) (int32, int32)
454TEXT runtime·fcntl(SB),NOSPLIT,$-4
455	MOVL	$SYS_fcntl, AX
456	INT	$0x80
457	JAE	noerr
458	MOVL	$-1, ret+12(FP)
459	MOVL	AX, errno+16(FP)
460	RET
461noerr:
462	MOVL	AX, ret+12(FP)
463	MOVL	$0, errno+16(FP)
464	RET
465
466// func cpuset_getaffinity(level int, which int, id int64, size int, mask *byte) int32
467TEXT runtime·cpuset_getaffinity(SB), NOSPLIT, $0-28
468	MOVL	$SYS_cpuset_getaffinity, AX
469	INT	$0x80
470	JAE	2(PC)
471	NEGL	AX
472	MOVL	AX, ret+24(FP)
473	RET
474
475GLOBL runtime·tlsoffset(SB),NOPTR,$4
476
477// func issetugid() int32
478TEXT runtime·issetugid(SB),NOSPLIT,$0
479	MOVL	$SYS_issetugid, AX
480	INT	$0x80
481	MOVL	AX, ret+0(FP)
482	RET
483