1/* $Id: entry64.S,v 1.1.1.1 2008/10/15 03:26:19 james26_jang Exp $
2 * entry64.S:  Solaris syscall emulation entry point.
3 *
4 * Copyright (C) 1996,1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
5 * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
6 * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
7 */
8
9#include <linux/errno.h>
10
11#include <asm/head.h>
12#include <asm/asi.h>
13#include <asm/smp.h>
14#include <asm/ptrace.h>
15#include <asm/page.h>
16#include <asm/signal.h>
17#include <asm/pgtable.h>
18#include <asm/processor.h>
19
20#include "conv.h"
21
22#define NR_SYSCALLS	256
23
24	.text
25solaris_syscall_trace:
26	call		syscall_trace
27	 nop
28	srl		%i0, 0, %o0
29	mov		%i4, %o4
30	srl		%i1, 0, %o1
31	mov		%i5, %o5
32	andcc		%l3, 1, %g0
33	be,pt		%icc, 2f
34	 srl		%i2, 0, %o2
35	b,pt		%xcc, 2f
36	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
37
38solaris_sucks:
39/* Solaris is a big system which needs to be able to do all the things
40 * in Inf+1 different ways */
41	add		%i6, 0x5c, %o0
42	mov		%i0, %g1
43	mov		%i1, %i0
44	mov		%i2, %i1
45	srl		%o0, 0, %o0
46	mov		%i3, %i2
47	movrz		%g1, 256, %g1 /* Ensure we don't loop forever */
48	mov		%i4, %i3
49	mov		%i5, %i4
50	ba,pt		%xcc, solaris_sparc_syscall
51exen:	 lduwa		[%o0] ASI_S, %i5
52
53exenf:	ba,pt		%xcc, solaris_sparc_syscall
54	 clr		%i5
55
56/* For shared binaries, binfmt_elf32 already sets up personality
57   and exec_domain. This is to handle static binaries as well */
58solaris_reg:
59	call		solaris_register
60	 nop
61	ba,pt		%xcc, 1f
62	 mov		%i4, %o4
63
64linux_syscall_for_solaris:
65	sll		%l3, 2, %l4
66	ba,pt		%xcc, 10f
67	 lduw		[%l6 + %l4], %l3
68
69	/* Solaris system calls enter here... */
70	.align	32
71	.globl	solaris_sparc_syscall
72solaris_sparc_syscall:
73	ldub		[%g6 + AOFF_task_personality + ASIZ_task_personality - 1], %l0
74	cmp		%g1, 255
75	bg,pn		%icc, solaris_unimplemented
76	 srl		%g1, 0, %g1
77	sethi		%hi(solaris_sys_table), %l7
78	brz,pn		%g1, solaris_sucks
79	 mov		%i4, %o4
80	sll		%g1, 2, %l4
81	cmp		%l0, 1
82	bne,pn		%icc, solaris_reg
831:	 srl		%i0, 0, %o0
84	lduw		[%l7 + %l4], %l3
85	srl		%i1, 0, %o1
86	ldx		[%g6 + AOFF_task_flags], %l5
87	cmp		%l3, NR_SYSCALLS
88	bleu,a,pn	%xcc, linux_syscall_for_solaris
89	 sethi		%hi(sys_call_table32), %l6
90	andcc		%l3, 1, %g0
91	bne,a,pn	%icc, 10f
92	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
9310:	srl		%i2, 0, %o2
94	mov		%i5, %o5
95	andn		%l3, 3, %l7
96	andcc		%l5, 0x20, %g0
97	bne,pn		%icc, solaris_syscall_trace
98	 mov		%i0, %l5
992:	call		%l7
100	 srl		%i3, 0, %o3
101ret_from_solaris:
102	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
103	ldx		[%g6 + AOFF_task_flags], %l6
104	sra		%o0, 0, %o0
105	mov		%ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
106	ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
107	cmp		%o0, -ENOIOCTLCMD
108	sllx		%g2, 32, %g2
109	bgeu,pn		%xcc, 1f
110	 andcc		%l6, 0x20, %l6
111
112	/* System call success, clear Carry condition code. */
113	andn		%g3, %g2, %g3
114	stx		%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
115	bne,pn		%icc, solaris_syscall_trace2
116	 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1
117	andcc		%l1, 1, %g0
118	bne,pn		%icc, 2f
119	 clr		%l6
120	add		%l1, 0x4, %l2
121	stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]	 ! pc = npc
122	call		rtrap
123	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] !npc = npc+4
124
125	/* When tnpc & 1, this comes from setcontext and we don't want to advance pc */
1262:	andn		%l1, 3, %l1
127	call		rtrap
128	 stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] !npc = npc&~3
129
1301:
131	/* System call failure, set Carry condition code.
132	 * Also, get abs(errno) to return to the process.
133	 */
134	sub		%g0, %o0, %o0
135	or		%g3, %g2, %g3
136	cmp		%o0, ERANGE	/* 0-ERANGE are identity mapped */
137	bleu,pt		%icc, 1f
138	 cmp		%o0, EMEDIUMTYPE
139	bgu,pn		%icc, 1f
140	 sethi		%hi(solaris_err_table), %l6
141	sll		%o0, 2, %o0
142	or		%l6, %lo(solaris_err_table), %l6
143	ldsw		[%l6 + %o0], %o0
1441:	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
145	mov		1, %l6
146	stx		%g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
147	bne,pn		%icc, solaris_syscall_trace2
148	 ldx		[%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1
149	andcc		%l1, 1, %g0
150	bne,pn		%icc, 2b
151	 add		%l1, 0x4, %l2
152	stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]  ! pc = npc
153	call		rtrap
154	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] !npc = npc+4
155
156solaris_syscall_trace2:
157	call		syscall_trace
158	 add		%l1, 0x4, %l2			/* npc = npc+4 */
159	andcc		%l1, 1, %g0
160	bne,pn		%icc, 2b
161	 nop
162	stx		%l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
163	call		rtrap
164	 stx		%l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
165
166	/* This one is tricky, so that's why we do it in assembly */
167	.globl		solaris_sigsuspend
168solaris_sigsuspend:
169	call		do_sol_sigsuspend
170	 nop
171	brlz,pn		%o0, ret_from_solaris
172	 nop
173	call		sys_sigsuspend
174	 stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
175
176	.globl		solaris_getpid
177solaris_getpid:
178	call		sys_getppid	/* This is tricky, so don't do it in assembly */
179	 nop
180	stx		%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
181	b,pt		%xcc, ret_from_solaris
182	 lduw		[%g6 + AOFF_task_pid], %o0
183
184	.globl	solaris_getuid
185solaris_getuid:
186	lduw		[%g6 + AOFF_task_euid], %o1
187	lduw		[%g6 + AOFF_task_uid], %o0
188	b,pt		%xcc, ret_from_solaris
189	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
190
191	.globl	solaris_getgid
192solaris_getgid:
193	lduw		[%g6 + AOFF_task_egid], %o1
194	lduw		[%g6 + AOFF_task_gid], %o0
195	b,pt		%xcc, ret_from_solaris
196	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
197
198	.globl		solaris_unimplemented
199solaris_unimplemented:
200	call		do_sol_unimplemented
201	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
202	ba,pt		%xcc, ret_from_solaris
203	 nop
204
205	.section	__ex_table,#alloc
206	.align		4
207	.word		exen, exenf
208
209