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, OpenBSD
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_MONOTONIC	$3
14
15// Exit the entire program (like C exit)
16TEXT runtime·exit(SB),NOSPLIT,$-4
17	MOVL	$1, AX
18	INT	$0x80
19	MOVL	$0xf1, 0xf1		// crash
20	RET
21
22// func exitThread(wait *uint32)
23TEXT runtime·exitThread(SB),NOSPLIT,$0-4
24	MOVL	$302, AX		// sys___threxit
25	INT	$0x80
26	MOVL	$0xf1, 0xf1		// crash
27	JMP	0(PC)
28
29TEXT runtime·open(SB),NOSPLIT,$-4
30	MOVL	$5, AX
31	INT	$0x80
32	JAE	2(PC)
33	MOVL	$-1, AX
34	MOVL	AX, ret+12(FP)
35	RET
36
37TEXT runtime·closefd(SB),NOSPLIT,$-4
38	MOVL	$6, AX
39	INT	$0x80
40	JAE	2(PC)
41	MOVL	$-1, AX
42	MOVL	AX, ret+4(FP)
43	RET
44
45TEXT runtime·read(SB),NOSPLIT,$-4
46	MOVL	$3, AX
47	INT	$0x80
48	JAE	2(PC)
49	NEGL	AX			// caller expects negative errno
50	MOVL	AX, ret+12(FP)
51	RET
52
53// func pipe() (r, w int32, errno int32)
54TEXT runtime·pipe(SB),NOSPLIT,$8-12
55	MOVL	$263, AX
56	LEAL	r+0(FP), BX
57	MOVL	BX, 4(SP)
58	INT	$0x80
59	MOVL	AX, errno+8(FP)
60	RET
61
62// func pipe2(flags int32) (r, w int32, errno int32)
63TEXT runtime·pipe2(SB),NOSPLIT,$12-16
64	MOVL	$101, AX
65	LEAL	r+4(FP), BX
66	MOVL	BX, 4(SP)
67	MOVL	flags+0(FP), BX
68	MOVL	BX, 8(SP)
69	INT	$0x80
70	MOVL	AX, errno+12(FP)
71	RET
72
73TEXT runtime·write1(SB),NOSPLIT,$-4
74	MOVL	$4, AX			// sys_write
75	INT	$0x80
76	JAE	2(PC)
77	NEGL	AX			// caller expects negative errno
78	MOVL	AX, ret+12(FP)
79	RET
80
81TEXT runtime·usleep(SB),NOSPLIT,$24
82	MOVL	$0, DX
83	MOVL	usec+0(FP), AX
84	MOVL	$1000000, CX
85	DIVL	CX
86	MOVL	AX, 12(SP)		// tv_sec - l32
87	MOVL	$0, 16(SP)		// tv_sec - h32
88	MOVL	$1000, AX
89	MULL	DX
90	MOVL	AX, 20(SP)		// tv_nsec
91
92	MOVL	$0, 0(SP)
93	LEAL	12(SP), AX
94	MOVL	AX, 4(SP)		// arg 1 - rqtp
95	MOVL	$0, 8(SP)		// arg 2 - rmtp
96	MOVL	$91, AX			// sys_nanosleep
97	INT	$0x80
98	RET
99
100TEXT runtime·getthrid(SB),NOSPLIT,$0-4
101	MOVL	$299, AX		// sys_getthrid
102	INT	$0x80
103	MOVL	AX, ret+0(FP)
104	RET
105
106TEXT runtime·thrkill(SB),NOSPLIT,$16-8
107	MOVL	$0, 0(SP)
108	MOVL	tid+0(FP), AX
109	MOVL	AX, 4(SP)		// arg 1 - tid
110	MOVL	sig+4(FP), AX
111	MOVL	AX, 8(SP)		// arg 2 - signum
112	MOVL	$0, 12(SP)		// arg 3 - tcb
113	MOVL	$119, AX		// sys_thrkill
114	INT	$0x80
115	RET
116
117TEXT runtime·raiseproc(SB),NOSPLIT,$12
118	MOVL	$20, AX			// sys_getpid
119	INT	$0x80
120	MOVL	$0, 0(SP)
121	MOVL	AX, 4(SP)		// arg 1 - pid
122	MOVL	sig+0(FP), AX
123	MOVL	AX, 8(SP)		// arg 2 - signum
124	MOVL	$122, AX		// sys_kill
125	INT	$0x80
126	RET
127
128TEXT runtime·mmap(SB),NOSPLIT,$36
129	LEAL	addr+0(FP), SI
130	LEAL	4(SP), DI
131	CLD
132	MOVSL				// arg 1 - addr
133	MOVSL				// arg 2 - len
134	MOVSL				// arg 3 - prot
135	MOVSL				// arg 4 - flags
136	MOVSL				// arg 5 - fd
137	MOVL	$0, AX
138	STOSL				// arg 6 - pad
139	MOVSL				// arg 7 - offset
140	MOVL	$0, AX			// top 32 bits of file offset
141	STOSL
142	MOVL	$197, AX		// sys_mmap
143	INT	$0x80
144	JAE	ok
145	MOVL	$0, p+24(FP)
146	MOVL	AX, err+28(FP)
147	RET
148ok:
149	MOVL	AX, p+24(FP)
150	MOVL	$0, err+28(FP)
151	RET
152
153TEXT runtime·munmap(SB),NOSPLIT,$-4
154	MOVL	$73, AX			// sys_munmap
155	INT	$0x80
156	JAE	2(PC)
157	MOVL	$0xf1, 0xf1		// crash
158	RET
159
160TEXT runtime·madvise(SB),NOSPLIT,$-4
161	MOVL	$75, AX			// sys_madvise
162	INT	$0x80
163	JAE	2(PC)
164	MOVL	$-1, AX
165	MOVL	AX, ret+12(FP)
166	RET
167
168TEXT runtime·setitimer(SB),NOSPLIT,$-4
169	MOVL	$69, AX
170	INT	$0x80
171	RET
172
173// func walltime1() (sec int64, nsec int32)
174TEXT runtime·walltime1(SB), NOSPLIT, $32
175	LEAL	12(SP), BX
176	MOVL	$0, 4(SP)		// arg 1 - clock_id
177	MOVL	BX, 8(SP)		// arg 2 - tp
178	MOVL	$87, AX			// sys_clock_gettime
179	INT	$0x80
180
181	MOVL	12(SP), AX		// sec - l32
182	MOVL	AX, sec_lo+0(FP)
183	MOVL	16(SP), AX		// sec - h32
184	MOVL	AX, sec_hi+4(FP)
185
186	MOVL	20(SP), BX		// nsec
187	MOVL	BX, nsec+8(FP)
188	RET
189
190// int64 nanotime1(void) so really
191// void nanotime1(int64 *nsec)
192TEXT runtime·nanotime1(SB),NOSPLIT,$32
193	LEAL	12(SP), BX
194	MOVL	CLOCK_MONOTONIC, 4(SP)	// arg 1 - clock_id
195	MOVL	BX, 8(SP)		// arg 2 - tp
196	MOVL	$87, AX			// sys_clock_gettime
197	INT	$0x80
198
199	MOVL    16(SP), CX		// sec - h32
200	IMULL   $1000000000, CX
201
202	MOVL    12(SP), AX		// sec - l32
203	MOVL    $1000000000, BX
204	MULL    BX			// result in dx:ax
205
206	MOVL	20(SP), BX		// nsec
207	ADDL	BX, AX
208	ADCL	CX, DX			// add high bits with carry
209
210	MOVL	AX, ret_lo+0(FP)
211	MOVL	DX, ret_hi+4(FP)
212	RET
213
214TEXT runtime·sigaction(SB),NOSPLIT,$-4
215	MOVL	$46, AX			// sys_sigaction
216	INT	$0x80
217	JAE	2(PC)
218	MOVL	$0xf1, 0xf1		// crash
219	RET
220
221TEXT runtime·obsdsigprocmask(SB),NOSPLIT,$-4
222	MOVL	$48, AX			// sys_sigprocmask
223	INT	$0x80
224	JAE	2(PC)
225	MOVL	$0xf1, 0xf1		// crash
226	MOVL	AX, ret+8(FP)
227	RET
228
229TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
230	MOVL	fn+0(FP), AX
231	MOVL	sig+4(FP), BX
232	MOVL	info+8(FP), CX
233	MOVL	ctx+12(FP), DX
234	MOVL	SP, SI
235	SUBL	$32, SP
236	ANDL	$~15, SP	// align stack: handler might be a C function
237	MOVL	BX, 0(SP)
238	MOVL	CX, 4(SP)
239	MOVL	DX, 8(SP)
240	MOVL	SI, 12(SP)	// save SI: handler might be a Go function
241	CALL	AX
242	MOVL	12(SP), AX
243	MOVL	AX, SP
244	RET
245
246// Called by OS using C ABI.
247TEXT runtime·sigtramp(SB),NOSPLIT,$28
248	NOP	SP	// tell vet SP changed - stop checking offsets
249	// Save callee-saved C registers, since the caller may be a C signal handler.
250	MOVL	BX, bx-4(SP)
251	MOVL	BP, bp-8(SP)
252	MOVL	SI, si-12(SP)
253	MOVL	DI, di-16(SP)
254	// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
255	// modify them.
256
257	MOVL	32(SP), BX // signo
258	MOVL	BX, 0(SP)
259	MOVL	36(SP), BX // info
260	MOVL	BX, 4(SP)
261	MOVL	40(SP), BX // context
262	MOVL	BX, 8(SP)
263	CALL	runtime·sigtrampgo(SB)
264
265	MOVL	di-16(SP), DI
266	MOVL	si-12(SP), SI
267	MOVL	bp-8(SP),  BP
268	MOVL	bx-4(SP),  BX
269	RET
270
271// int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
272TEXT runtime·tfork(SB),NOSPLIT,$12
273
274	// Copy mp, gp and fn from the parent stack onto the child stack.
275	MOVL	param+0(FP), AX
276	MOVL	8(AX), CX		// tf_stack
277	SUBL	$16, CX
278	MOVL	CX, 8(AX)
279	MOVL	mm+8(FP), SI
280	MOVL	SI, 0(CX)
281	MOVL	gg+12(FP), SI
282	MOVL	SI, 4(CX)
283	MOVL	fn+16(FP), SI
284	MOVL	SI, 8(CX)
285	MOVL	$1234, 12(CX)
286
287	MOVL	$0, 0(SP)		// syscall gap
288	MOVL	param+0(FP), AX
289	MOVL	AX, 4(SP)		// arg 1 - param
290	MOVL	psize+4(FP), AX
291	MOVL	AX, 8(SP)		// arg 2 - psize
292	MOVL	$8, AX			// sys___tfork
293	INT	$0x80
294
295	// Return if tfork syscall failed.
296	JCC	4(PC)
297	NEGL	AX
298	MOVL	AX, ret+20(FP)
299	RET
300
301	// In parent, return.
302	CMPL	AX, $0
303	JEQ	3(PC)
304	MOVL	AX, ret+20(FP)
305	RET
306
307	// Paranoia: check that SP is as we expect.
308	MOVL	12(SP), BP
309	CMPL	BP, $1234
310	JEQ	2(PC)
311	INT	$3
312
313	// Reload registers.
314	MOVL	0(SP), BX		// m
315	MOVL	4(SP), DX		// g
316	MOVL	8(SP), SI		// fn
317
318	// Set FS to point at m->tls.
319	LEAL	m_tls(BX), BP
320	PUSHAL				// save registers
321	PUSHL	BP
322	CALL	set_tcb<>(SB)
323	POPL	AX
324	POPAL
325
326	// Now segment is established. Initialize m, g.
327	get_tls(AX)
328	MOVL	DX, g(AX)
329	MOVL	BX, g_m(DX)
330
331	CALL	runtime·stackcheck(SB)	// smashes AX, CX
332	MOVL	0(DX), DX		// paranoia; check they are not nil
333	MOVL	0(BX), BX
334
335	// More paranoia; check that stack splitting code works.
336	PUSHAL
337	CALL	runtime·emptyfunc(SB)
338	POPAL
339
340	// Call fn.
341	CALL	SI
342
343	// fn should never return.
344	MOVL	$0x1234, 0x1005
345	RET
346
347TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
348	MOVL	$288, AX		// sys_sigaltstack
349	MOVL	new+0(FP), BX
350	MOVL	old+4(FP), CX
351	INT	$0x80
352	CMPL	AX, $0xfffff001
353	JLS	2(PC)
354	INT	$3
355	RET
356
357TEXT runtime·setldt(SB),NOSPLIT,$4
358	// Under OpenBSD we set the GS base instead of messing with the LDT.
359	MOVL	base+4(FP), AX
360	MOVL	AX, 0(SP)
361	CALL	set_tcb<>(SB)
362	RET
363
364TEXT set_tcb<>(SB),NOSPLIT,$8
365	// adjust for ELF: wants to use -4(GS) for g
366	MOVL	tlsbase+0(FP), CX
367	ADDL	$4, CX
368	MOVL	$0, 0(SP)		// syscall gap
369	MOVL	CX, 4(SP)		// arg 1 - tcb
370	MOVL	$329, AX		// sys___set_tcb
371	INT	$0x80
372	JCC	2(PC)
373	MOVL	$0xf1, 0xf1		// crash
374	RET
375
376TEXT runtime·osyield(SB),NOSPLIT,$-4
377	MOVL	$298, AX		// sys_sched_yield
378	INT	$0x80
379	RET
380
381TEXT runtime·thrsleep(SB),NOSPLIT,$-4
382	MOVL	$94, AX			// sys___thrsleep
383	INT	$0x80
384	MOVL	AX, ret+20(FP)
385	RET
386
387TEXT runtime·thrwakeup(SB),NOSPLIT,$-4
388	MOVL	$301, AX		// sys___thrwakeup
389	INT	$0x80
390	MOVL	AX, ret+8(FP)
391	RET
392
393TEXT runtime·sysctl(SB),NOSPLIT,$28
394	LEAL	mib+0(FP), SI
395	LEAL	4(SP), DI
396	CLD
397	MOVSL				// arg 1 - name
398	MOVSL				// arg 2 - namelen
399	MOVSL				// arg 3 - oldp
400	MOVSL				// arg 4 - oldlenp
401	MOVSL				// arg 5 - newp
402	MOVSL				// arg 6 - newlen
403	MOVL	$202, AX		// sys___sysctl
404	INT	$0x80
405	JCC	4(PC)
406	NEGL	AX
407	MOVL	AX, ret+24(FP)
408	RET
409	MOVL	$0, AX
410	MOVL	AX, ret+24(FP)
411	RET
412
413// int32 runtime·kqueue(void);
414TEXT runtime·kqueue(SB),NOSPLIT,$0
415	MOVL	$269, AX
416	INT	$0x80
417	JAE	2(PC)
418	NEGL	AX
419	MOVL	AX, ret+0(FP)
420	RET
421
422// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
423TEXT runtime·kevent(SB),NOSPLIT,$0
424	MOVL	$72, AX			// sys_kevent
425	INT	$0x80
426	JAE	2(PC)
427	NEGL	AX
428	MOVL	AX, ret+24(FP)
429	RET
430
431// int32 runtime·closeonexec(int32 fd);
432TEXT runtime·closeonexec(SB),NOSPLIT,$32
433	MOVL	$92, AX			// sys_fcntl
434	// 0(SP) is where the caller PC would be; kernel skips it
435	MOVL	fd+0(FP), BX
436	MOVL	BX, 4(SP)	// fd
437	MOVL	$2, 8(SP)	// F_SETFD
438	MOVL	$1, 12(SP)	// FD_CLOEXEC
439	INT	$0x80
440	JAE	2(PC)
441	NEGL	AX
442	RET
443
444// func runtime·setNonblock(fd int32)
445TEXT runtime·setNonblock(SB),NOSPLIT,$16-4
446	MOVL	$92, AX // fcntl
447	MOVL	fd+0(FP), BX // fd
448	MOVL	BX, 4(SP)
449	MOVL	$3, 8(SP) // F_GETFL
450	MOVL	$0, 12(SP)
451	INT	$0x80
452	MOVL	fd+0(FP), BX // fd
453	MOVL	BX, 4(SP)
454	MOVL	$4, 8(SP) // F_SETFL
455	ORL	$4, AX // O_NONBLOCK
456	MOVL	AX, 12(SP)
457	MOVL	$92, AX // fcntl
458	INT	$0x80
459	RET
460
461GLOBL runtime·tlsoffset(SB),NOPTR,$4
462