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