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