| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $ | 
 | 2 |  * signal.c: Signal emulation for Solaris | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | 
 | 5 |  */ | 
 | 6 |  | 
 | 7 | #include <linux/types.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | #include <linux/errno.h> | 
 | 9 |  | 
 | 10 | #include <asm/uaccess.h> | 
 | 11 | #include <asm/svr4.h> | 
 | 12 | #include <asm/string.h> | 
 | 13 |  | 
 | 14 | #include "conv.h" | 
 | 15 | #include "signal.h" | 
 | 16 |  | 
 | 17 | #define _S(nr) (1L<<((nr)-1)) | 
 | 18 |  | 
 | 19 | #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) | 
 | 20 |  | 
 | 21 | long linux_to_solaris_signals[] = { | 
 | 22 |         0, | 
 | 23 | 	SOLARIS_SIGHUP,		SOLARIS_SIGINT,	 | 
 | 24 | 	SOLARIS_SIGQUIT,	SOLARIS_SIGILL, | 
 | 25 | 	SOLARIS_SIGTRAP,	SOLARIS_SIGIOT, | 
 | 26 | 	SOLARIS_SIGEMT,		SOLARIS_SIGFPE, | 
 | 27 | 	SOLARIS_SIGKILL,	SOLARIS_SIGBUS, | 
 | 28 | 	SOLARIS_SIGSEGV,	SOLARIS_SIGSYS, | 
 | 29 | 	SOLARIS_SIGPIPE,	SOLARIS_SIGALRM, | 
 | 30 | 	SOLARIS_SIGTERM,	SOLARIS_SIGURG, | 
 | 31 | 	SOLARIS_SIGSTOP,	SOLARIS_SIGTSTP, | 
 | 32 | 	SOLARIS_SIGCONT,	SOLARIS_SIGCLD, | 
 | 33 | 	SOLARIS_SIGTTIN,	SOLARIS_SIGTTOU, | 
 | 34 | 	SOLARIS_SIGPOLL,	SOLARIS_SIGXCPU, | 
 | 35 | 	SOLARIS_SIGXFSZ,	SOLARIS_SIGVTALRM, | 
 | 36 | 	SOLARIS_SIGPROF,	SOLARIS_SIGWINCH, | 
 | 37 | 	SOLARIS_SIGUSR1,	SOLARIS_SIGUSR1, | 
 | 38 | 	SOLARIS_SIGUSR2,	-1, | 
 | 39 | }; | 
 | 40 |  | 
 | 41 | long solaris_to_linux_signals[] = { | 
 | 42 |         0, | 
 | 43 |         SIGHUP,		SIGINT,		SIGQUIT,	SIGILL, | 
 | 44 |         SIGTRAP,	SIGIOT,		SIGEMT,		SIGFPE, | 
 | 45 |         SIGKILL,	SIGBUS,		SIGSEGV,	SIGSYS, | 
 | 46 |         SIGPIPE,	SIGALRM,	SIGTERM,	SIGUSR1, | 
 | 47 |         SIGUSR2,	SIGCHLD,	-1,		SIGWINCH, | 
 | 48 |         SIGURG,		SIGPOLL,	SIGSTOP,	SIGTSTP, | 
 | 49 |         SIGCONT,	SIGTTIN,	SIGTTOU,	SIGVTALRM, | 
 | 50 |         SIGPROF,	SIGXCPU,	SIGXFSZ,        -1, | 
 | 51 | 	-1,		-1,		-1,		-1, | 
 | 52 | 	-1,		-1,		-1,		-1, | 
 | 53 | 	-1,		-1,		-1,		-1, | 
 | 54 | }; | 
 | 55 |  | 
 | 56 | static inline long mapsig(long sig) | 
 | 57 | { | 
 | 58 | 	if ((unsigned long)sig > SOLARIS_NSIGNALS) | 
 | 59 | 		return -EINVAL; | 
 | 60 | 	return solaris_to_linux_signals[sig]; | 
 | 61 | } | 
 | 62 |  | 
 | 63 | asmlinkage int solaris_kill(int pid, int sig) | 
 | 64 | { | 
 | 65 | 	int (*sys_kill)(int,int) =  | 
 | 66 | 		(int (*)(int,int))SYS(kill); | 
 | 67 | 	int s = mapsig(sig); | 
 | 68 | 	 | 
 | 69 | 	if (s < 0) return s; | 
 | 70 | 	return sys_kill(pid, s); | 
 | 71 | } | 
 | 72 |  | 
 | 73 | static long sig_handler(int sig, u32 arg, int one_shot) | 
 | 74 | { | 
 | 75 | 	struct sigaction sa, old; | 
 | 76 | 	int ret; | 
 | 77 | 	mm_segment_t old_fs = get_fs(); | 
 | 78 | 	int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) =  | 
 | 79 | 		(int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); | 
 | 80 | 	 | 
 | 81 | 	sigemptyset(&sa.sa_mask); | 
 | 82 | 	sa.sa_restorer = NULL; | 
 | 83 | 	sa.sa_handler = (__sighandler_t)A(arg); | 
 | 84 | 	sa.sa_flags = 0; | 
 | 85 | 	if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK; | 
 | 86 | 	set_fs (KERNEL_DS); | 
 | 87 | 	ret = sys_sigaction(sig, (void __user *)&sa, (void __user *)&old); | 
 | 88 | 	set_fs (old_fs); | 
 | 89 | 	if (ret < 0) return ret; | 
 | 90 | 	return (u32)(unsigned long)old.sa_handler; | 
 | 91 | } | 
 | 92 |  | 
 | 93 | static inline long solaris_signal(int sig, u32 arg) | 
 | 94 | { | 
 | 95 | 	return sig_handler (sig, arg, 1); | 
 | 96 | } | 
 | 97 |  | 
 | 98 | static long solaris_sigset(int sig, u32 arg) | 
 | 99 | { | 
 | 100 | 	if (arg != 2) /* HOLD */ { | 
 | 101 | 		spin_lock_irq(¤t->sighand->siglock); | 
 | 102 | 		sigdelsetmask(¤t->blocked, _S(sig)); | 
 | 103 | 		recalc_sigpending(); | 
 | 104 | 		spin_unlock_irq(¤t->sighand->siglock); | 
 | 105 | 		return sig_handler (sig, arg, 0); | 
 | 106 | 	} else { | 
 | 107 | 		spin_lock_irq(¤t->sighand->siglock); | 
 | 108 | 		sigaddsetmask(¤t->blocked, (_S(sig) & ~_BLOCKABLE)); | 
 | 109 | 		recalc_sigpending(); | 
 | 110 | 		spin_unlock_irq(¤t->sighand->siglock); | 
 | 111 | 		return 0; | 
 | 112 | 	} | 
 | 113 | } | 
 | 114 |  | 
 | 115 | static inline long solaris_sighold(int sig) | 
 | 116 | { | 
 | 117 | 	return solaris_sigset(sig, 2); | 
 | 118 | } | 
 | 119 |  | 
 | 120 | static inline long solaris_sigrelse(int sig) | 
 | 121 | { | 
 | 122 | 	spin_lock_irq(¤t->sighand->siglock); | 
 | 123 | 	sigdelsetmask(¤t->blocked, _S(sig)); | 
 | 124 | 	recalc_sigpending(); | 
 | 125 | 	spin_unlock_irq(¤t->sighand->siglock); | 
 | 126 | 	return 0; | 
 | 127 | } | 
 | 128 |  | 
 | 129 | static inline long solaris_sigignore(int sig) | 
 | 130 | { | 
 | 131 | 	return sig_handler(sig, (u32)(unsigned long)SIG_IGN, 0); | 
 | 132 | } | 
 | 133 |  | 
 | 134 | static inline long solaris_sigpause(int sig) | 
 | 135 | { | 
 | 136 | 	printk ("Need to support solaris sigpause\n"); | 
 | 137 | 	return -ENOSYS; | 
 | 138 | } | 
 | 139 |  | 
 | 140 | asmlinkage long solaris_sigfunc(int sig, u32 arg) | 
 | 141 | { | 
 | 142 | 	int func = sig & ~0xff; | 
 | 143 | 	 | 
 | 144 | 	sig = mapsig(sig & 0xff);  | 
 | 145 | 	if (sig < 0) return sig;  | 
 | 146 | 	switch (func) { | 
 | 147 | 	case 0: return solaris_signal(sig, arg);  | 
 | 148 | 	case 0x100: return solaris_sigset(sig, arg);  | 
 | 149 | 	case 0x200: return solaris_sighold(sig); | 
 | 150 | 	case 0x400: return solaris_sigrelse(sig);  | 
 | 151 | 	case 0x800: return solaris_sigignore(sig);  | 
 | 152 | 	case 0x1000: return solaris_sigpause(sig); | 
 | 153 | 	} | 
 | 154 | 	return -EINVAL; | 
 | 155 | } | 
 | 156 |  | 
 | 157 | typedef struct { | 
 | 158 | 	u32 __sigbits[4]; | 
 | 159 | } sol_sigset_t; | 
 | 160 |  | 
 | 161 | static inline int mapin(u32 *p, sigset_t *q) | 
 | 162 | { | 
 | 163 | 	int i; | 
 | 164 | 	u32 x; | 
 | 165 | 	int sig; | 
 | 166 | 	 | 
 | 167 | 	sigemptyset(q); | 
 | 168 | 	x = p[0]; | 
 | 169 | 	for (i = 1; i <= SOLARIS_NSIGNALS; i++) { | 
 | 170 | 		if (x & 1) { | 
 | 171 | 			sig = solaris_to_linux_signals[i]; | 
 | 172 | 			if (sig == -1) | 
 | 173 | 				return -EINVAL; | 
 | 174 | 			sigaddsetmask(q, (1L << (sig - 1))); | 
 | 175 | 		} | 
 | 176 | 		x >>= 1; | 
 | 177 | 		if (i == 32) | 
 | 178 | 			x = p[1]; | 
 | 179 | 	} | 
 | 180 | 	return 0; | 
 | 181 | } | 
 | 182 |  | 
 | 183 | static inline int mapout(sigset_t *q, u32 *p) | 
 | 184 | { | 
 | 185 | 	int i; | 
 | 186 | 	int sig; | 
 | 187 | 	 | 
 | 188 | 	p[0] = 0; | 
 | 189 | 	p[1] = 0; | 
 | 190 | 	for (i = 1; i <= 32; i++) { | 
 | 191 | 		if (sigismember(q, sigmask(i))) { | 
 | 192 | 			sig = linux_to_solaris_signals[i]; | 
 | 193 | 			if (sig == -1) | 
 | 194 | 				return -EINVAL; | 
 | 195 | 			if (sig > 32) | 
 | 196 | 				p[1] |= 1L << (sig - 33); | 
 | 197 | 			else | 
 | 198 | 				p[0] |= 1L << (sig - 1); | 
 | 199 | 		} | 
 | 200 | 	} | 
 | 201 | 	return 0; | 
 | 202 | } | 
 | 203 |  | 
 | 204 | asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out) | 
 | 205 | { | 
 | 206 | 	sigset_t in_s, *ins, out_s, *outs; | 
 | 207 | 	mm_segment_t old_fs = get_fs(); | 
 | 208 | 	int ret; | 
 | 209 | 	int (*sys_sigprocmask)(int,sigset_t __user *,sigset_t __user *) =  | 
 | 210 | 		(int (*)(int,sigset_t __user *,sigset_t __user *))SYS(sigprocmask); | 
 | 211 | 	 | 
 | 212 | 	ins = NULL; outs = NULL; | 
 | 213 | 	if (in) { | 
 | 214 | 		u32 tmp[2]; | 
 | 215 | 		 | 
 | 216 | 		if (copy_from_user (tmp, (void __user *)A(in), 2*sizeof(u32))) | 
 | 217 | 			return -EFAULT; | 
 | 218 | 		ins = &in_s; | 
 | 219 | 		if (mapin (tmp, ins)) return -EINVAL; | 
 | 220 | 	} | 
 | 221 | 	if (out) outs = &out_s; | 
 | 222 | 	set_fs (KERNEL_DS); | 
 | 223 | 	ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how, | 
 | 224 | 				(void __user *)ins, (void __user *)outs); | 
 | 225 | 	set_fs (old_fs); | 
 | 226 | 	if (ret) return ret; | 
 | 227 | 	if (out) { | 
 | 228 | 		u32 tmp[4]; | 
 | 229 | 		 | 
 | 230 | 		tmp[2] = 0; tmp[3] = 0; | 
 | 231 | 		if (mapout (outs, tmp)) return -EINVAL; | 
 | 232 | 		if (copy_to_user((void __user *)A(out), tmp, 4*sizeof(u32))) | 
 | 233 | 			return -EFAULT; | 
 | 234 | 	} | 
 | 235 | 	return 0; | 
 | 236 | } | 
 | 237 |  | 
 | 238 | asmlinkage long do_sol_sigsuspend(u32 mask) | 
 | 239 | { | 
 | 240 | 	sigset_t s; | 
 | 241 | 	u32 tmp[2]; | 
 | 242 | 		 | 
 | 243 | 	if (copy_from_user (tmp, (sol_sigset_t __user *)A(mask), 2*sizeof(u32))) | 
 | 244 | 		return -EFAULT; | 
 | 245 | 	if (mapin (tmp, &s)) return -EINVAL; | 
 | 246 | 	return (long)s.sig[0]; | 
 | 247 | } | 
 | 248 |  | 
 | 249 | struct sol_sigaction { | 
 | 250 | 	int	sa_flags; | 
 | 251 | 	u32	sa_handler; | 
 | 252 | 	u32	sa_mask[4]; | 
 | 253 | 	int	sa_resv[2]; | 
 | 254 | }; | 
 | 255 |  | 
 | 256 | asmlinkage int solaris_sigaction(int sig, u32 act, u32 old) | 
 | 257 | { | 
 | 258 | 	u32 tmp, tmp2[4]; | 
 | 259 | 	struct sigaction s, s2; | 
 | 260 | 	int ret; | 
 | 261 | 	mm_segment_t old_fs = get_fs(); | 
 | 262 | 	struct sol_sigaction __user *p = (void __user *)A(old); | 
 | 263 | 	int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) =  | 
 | 264 | 		(int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); | 
 | 265 | 	 | 
 | 266 | 	sig = mapsig(sig);  | 
 | 267 | 	if (sig < 0) { | 
 | 268 | 		/* We cheat a little bit for Solaris only signals */ | 
 | 269 | 		if (old && clear_user(p, sizeof(struct sol_sigaction))) | 
 | 270 | 			return -EFAULT; | 
 | 271 | 		return 0; | 
 | 272 | 	} | 
 | 273 | 	if (act) { | 
 | 274 | 		if (get_user (tmp, &p->sa_flags)) | 
 | 275 | 			return -EFAULT; | 
 | 276 | 		s.sa_flags = 0; | 
 | 277 | 		if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK; | 
 | 278 | 		if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART; | 
 | 279 | 		if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK; | 
 | 280 | 		if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT; | 
 | 281 | 		if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP; | 
 | 282 | 		if (get_user (tmp, &p->sa_handler) || | 
 | 283 | 		    copy_from_user (tmp2, &p->sa_mask, 2*sizeof(u32))) | 
 | 284 | 			return -EFAULT; | 
 | 285 | 		s.sa_handler = (__sighandler_t)A(tmp); | 
 | 286 | 		if (mapin (tmp2, &s.sa_mask)) return -EINVAL; | 
 | 287 | 		s.sa_restorer = NULL; | 
 | 288 | 	} | 
 | 289 | 	set_fs(KERNEL_DS); | 
 | 290 | 	ret = sys_sigaction(sig, act ? (void __user *)&s : NULL, | 
 | 291 | 				 old ? (void __user *)&s2 : NULL); | 
 | 292 | 	set_fs(old_fs); | 
 | 293 | 	if (ret) return ret; | 
 | 294 | 	if (old) { | 
 | 295 | 		if (mapout (&s2.sa_mask, tmp2)) return -EINVAL; | 
 | 296 | 		tmp = 0; tmp2[2] = 0; tmp2[3] = 0; | 
 | 297 | 		if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK; | 
 | 298 | 		if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART; | 
 | 299 | 		if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER; | 
 | 300 | 		if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND; | 
 | 301 | 		if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP; | 
 | 302 | 		if (put_user (tmp, &p->sa_flags) || | 
 | 303 | 		    __put_user ((u32)(unsigned long)s2.sa_handler, &p->sa_handler) || | 
 | 304 | 		    copy_to_user (&p->sa_mask, tmp2, 4*sizeof(u32))) | 
 | 305 | 			return -EFAULT; | 
 | 306 | 	} | 
 | 307 | 	return 0; | 
 | 308 | } | 
 | 309 |  | 
 | 310 | asmlinkage int solaris_sigpending(int which, u32 set) | 
 | 311 | { | 
 | 312 | 	sigset_t s; | 
 | 313 | 	u32 tmp[4]; | 
 | 314 | 	switch (which) { | 
 | 315 | 	case 1: /* sigpending */ | 
 | 316 | 		spin_lock_irq(¤t->sighand->siglock); | 
 | 317 | 		sigandsets(&s, ¤t->blocked, ¤t->pending.signal); | 
 | 318 | 		recalc_sigpending(); | 
 | 319 | 		spin_unlock_irq(¤t->sighand->siglock); | 
 | 320 | 		break; | 
 | 321 | 	case 2: /* sigfillset - I just set signals which have linux equivalents */ | 
 | 322 | 		sigfillset(&s); | 
 | 323 | 		break; | 
 | 324 | 	default: return -EINVAL; | 
 | 325 | 	} | 
 | 326 | 	if (mapout (&s, tmp)) return -EINVAL; | 
 | 327 | 	tmp[2] = 0; tmp[3] = 0; | 
 | 328 | 	if (copy_to_user ((u32 __user *)A(set), tmp, sizeof(tmp))) | 
 | 329 | 		return -EFAULT; | 
 | 330 | 	return 0; | 
 | 331 | } | 
 | 332 |  | 
 | 333 | asmlinkage int solaris_wait(u32 stat_loc) | 
 | 334 | { | 
 | 335 | 	unsigned __user *p = (unsigned __user *)A(stat_loc); | 
 | 336 | 	int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = | 
 | 337 | 		(int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); | 
 | 338 | 	int ret, status; | 
 | 339 | 	 | 
 | 340 | 	ret = sys_wait4(-1, p, WUNTRACED, NULL); | 
 | 341 | 	if (ret >= 0 && stat_loc) { | 
 | 342 | 		if (get_user (status, p)) | 
 | 343 | 			return -EFAULT; | 
 | 344 | 		if (((status - 1) & 0xffff) < 0xff) | 
 | 345 | 			status = linux_to_solaris_signals[status & 0x7f] & 0x7f; | 
 | 346 | 		else if ((status & 0xff) == 0x7f) | 
 | 347 | 			status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f; | 
 | 348 | 		if (__put_user (status, p)) | 
 | 349 | 			return -EFAULT; | 
 | 350 | 	} | 
 | 351 | 	return ret; | 
 | 352 | } | 
 | 353 |  | 
 | 354 | asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) | 
 | 355 | { | 
 | 356 | 	int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = | 
 | 357 | 		(int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); | 
 | 358 | 	int opts, status, ret; | 
 | 359 | 	 | 
 | 360 | 	switch (idtype) { | 
 | 361 | 	case 0: /* P_PID */ break; | 
 | 362 | 	case 1: /* P_PGID */ pid = -pid; break; | 
 | 363 | 	case 7: /* P_ALL */ pid = -1; break; | 
 | 364 | 	default: return -EINVAL; | 
 | 365 | 	} | 
 | 366 | 	opts = 0; | 
 | 367 | 	if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED; | 
 | 368 | 	if (options & SOLARIS_WNOHANG) opts |= WNOHANG; | 
 | 369 | 	current->state = TASK_RUNNING; | 
 | 370 | 	ret = sys_wait4(pid, (unsigned int __user *)A(info), opts, NULL); | 
 | 371 | 	if (ret < 0) return ret; | 
 | 372 | 	if (info) { | 
 | 373 | 		struct sol_siginfo __user *s = (void __user *)A(info); | 
 | 374 | 	 | 
 | 375 | 		if (get_user (status, (unsigned int __user *)A(info))) | 
 | 376 | 			return -EFAULT; | 
 | 377 |  | 
 | 378 | 		if (__put_user (SOLARIS_SIGCLD, &s->si_signo) || | 
 | 379 | 		    __put_user (ret, &s->_data._proc._pid)) | 
 | 380 | 			return -EFAULT; | 
 | 381 |  | 
 | 382 | 		switch (status & 0xff) { | 
 | 383 | 		case 0: ret = SOLARIS_CLD_EXITED; | 
 | 384 | 			status = (status >> 8) & 0xff; | 
 | 385 | 			break; | 
 | 386 | 		case 0x7f: | 
 | 387 | 			status = (status >> 8) & 0xff; | 
 | 388 | 			switch (status) { | 
 | 389 | 			case SIGSTOP: | 
 | 390 | 			case SIGTSTP: ret = SOLARIS_CLD_STOPPED; | 
 | 391 | 			default: ret = SOLARIS_CLD_EXITED; | 
 | 392 | 			} | 
 | 393 | 			status = linux_to_solaris_signals[status]; | 
 | 394 | 			break; | 
 | 395 | 		default: | 
 | 396 | 			if (status & 0x80) ret = SOLARIS_CLD_DUMPED; | 
 | 397 | 			else ret = SOLARIS_CLD_KILLED; | 
 | 398 | 			status = linux_to_solaris_signals[status & 0x7f]; | 
 | 399 | 			break; | 
 | 400 | 		} | 
 | 401 |  | 
 | 402 | 		if (__put_user (ret, &s->si_code) || | 
 | 403 | 		    __put_user (status, &s->_data._proc._pdata._cld._status)) | 
 | 404 | 			return -EFAULT; | 
 | 405 | 	} | 
 | 406 | 	return 0; | 
 | 407 | } | 
 | 408 |  | 
 | 409 | extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs); | 
 | 410 | extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs); | 
 | 411 |  | 
 | 412 | asmlinkage int solaris_context(struct pt_regs *regs) | 
 | 413 | { | 
 | 414 | 	switch ((unsigned)regs->u_regs[UREG_I0]) { | 
 | 415 | 	case 0: /* getcontext */ | 
 | 416 | 		return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); | 
 | 417 | 	case 1: /* setcontext */ | 
 | 418 | 		return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); | 
 | 419 | 	default: | 
 | 420 | 		return -EINVAL; | 
 | 421 |  | 
 | 422 | 	} | 
 | 423 | } | 
 | 424 |  | 
 | 425 | asmlinkage int solaris_sigaltstack(u32 ss, u32 oss) | 
 | 426 | { | 
 | 427 | /* XXX Implement this soon */ | 
 | 428 | 	return 0; | 
 | 429 | } |