Home | History | Annotate | Line # | Download | only in powerpc
      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 
     64 void
     65 md_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 
     79 static void EMULNAME(syscall)(struct trapframe *);
     80 
     81 void
     82 EMULNAME(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 
    167 void EMULNAME(syscall_intern)(struct proc *);
    168 
    169 void
    170 EMULNAME(syscall_intern)(struct proc *p)
    171 {
    172 
    173 	p->p_md.md_syscall = EMULNAME(syscall);
    174 }
    175