1/*	$NetBSD: syscall.c,v 1.58 2023/10/05 19:41:05 ad Exp $	*/
2
3/*
4 * Copyright (C) 2002 Matt Thomas
5 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6 * Copyright (C) 1995, 1996 TooLs GmbH.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by TooLs GmbH.
20 * 4. The name of TooLs GmbH may not be used to endorse or promote products
21 *    derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/* DO NOT INCLUDE opt_compat_XXX.h */
36/* If needed, they will be included by file that includes this one */
37
38#include <sys/param.h>
39#include <sys/cpu.h>
40#include <sys/ktrace.h>
41#include <sys/proc.h>
42#include <sys/reboot.h>
43#include <sys/systm.h>
44#include <sys/syscallvar.h>
45
46#include <uvm/uvm_extern.h>
47
48#include <powerpc/frame.h>
49#include <powerpc/pcb.h>
50#include <powerpc/userret.h>
51
52#define	FIRSTARG	3		/* first argument is in reg 3 */
53#define	NARGREG		8		/* 8 args are in registers */
54#define	MOREARGS(sp)	((void *)((uintptr_t)(sp) + 8)) /* more args go here */
55
56#ifndef EMULNAME
57#include <sys/syscall.h>
58
59#define EMULNAME(x)	(x)
60#define EMULNAMEU(x)	(x)
61
62__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.58 2023/10/05 19:41:05 ad Exp $");
63
64void
65md_child_return(struct lwp *l)
66{
67	struct trapframe * const tf = l->l_md.md_utf;
68
69	tf->tf_fixreg[FIRSTARG] = 0;
70	tf->tf_fixreg[FIRSTARG + 1] = 1;
71	tf->tf_cr &= ~0x10000000;
72	tf->tf_srr1 &= ~(PSL_FP|PSL_VEC); /* Disable FP & AltiVec, as we can't
73					   be them. */
74}
75#endif
76
77#include <powerpc/spr.h>
78
79static void EMULNAME(syscall)(struct trapframe *);
80
81void
82EMULNAME(syscall)(struct trapframe *tf)
83{
84	struct lwp * const l = curlwp;
85	struct proc * const p = l->l_proc;
86	const struct sysent *callp;
87	size_t argsize;
88	register_t code;
89	register_t *params, rval[2];
90	register_t args[10];
91	int error;
92	int n;
93
94	curcpu()->ci_ev_scalls.ev_count++;
95
96	code = tf->tf_fixreg[0];
97	params = tf->tf_fixreg + FIRSTARG;
98	n = NARGREG;
99
100	{
101		switch (code) {
102		case EMULNAMEU(SYS_syscall):
103			/*
104			 * code is first argument,
105			 * followed by actual args.
106			 */
107			code = *params++;
108			n -= 1;
109			break;
110#if !defined(COMPAT_LINUX)
111		case EMULNAMEU(SYS___syscall):
112			params++;
113			code = *params++;
114			n -= 2;
115			break;
116#endif
117		default:
118			break;
119		}
120
121		code &= EMULNAMEU(SYS_NSYSENT) - 1;
122		callp = p->p_emul->e_sysent + code;
123	}
124
125	argsize = callp->sy_argsize;
126
127	if (argsize > n * sizeof(register_t)) {
128		memcpy(args, params, n * sizeof(register_t));
129		error = copyin(MOREARGS(tf->tf_fixreg[1]),
130		    args + n,
131		    argsize - n * sizeof(register_t));
132		if (error)
133			goto bad;
134		params = args;
135	}
136
137	error = sy_invoke(callp, l, params, rval, code);
138
139	if (__predict_true(error == 0)) {
140		tf->tf_fixreg[FIRSTARG] = rval[0];
141		tf->tf_fixreg[FIRSTARG + 1] = rval[1];
142		tf->tf_cr &= ~0x10000000;
143	} else {
144		switch (error) {
145		case ERESTART:
146			/*
147			 * Set user's pc back to redo the system call.
148			 */
149			tf->tf_srr0 -= 4;
150			break;
151		case EJUSTRETURN:
152			/* nothing to do */
153			break;
154		default:
155		bad:
156			if (p->p_emul->e_errno)
157				error = p->p_emul->e_errno[error];
158			tf->tf_fixreg[FIRSTARG] = error;
159			tf->tf_cr |= 0x10000000;
160			break;
161		}
162	}
163
164	userret(l, tf);
165}
166
167void EMULNAME(syscall_intern)(struct proc *);
168
169void
170EMULNAME(syscall_intern)(struct proc *p)
171{
172
173	p->p_md.md_syscall = EMULNAME(syscall);
174}
175