| @@ -1,424 +1,425 @@ | | | @@ -1,424 +1,425 @@ |
1 | /* $NetBSD: syscall.c,v 1.39 2009/12/14 00:46:07 matt Exp $ */ | | 1 | /* $NetBSD: syscall.c,v 1.40 2009/12/14 18:39:19 skrll Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe and by Charles M. Hannum. | | 8 | * by Jason R. Thorpe and by Charles M. Hannum. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1992, 1993 | | 33 | * Copyright (c) 1992, 1993 |
34 | * The Regents of the University of California. All rights reserved. | | 34 | * The Regents of the University of California. All rights reserved. |
35 | * | | 35 | * |
36 | * This code is derived from software contributed to Berkeley by | | 36 | * This code is derived from software contributed to Berkeley by |
37 | * the Systems Programming Group of the University of Utah Computer | | 37 | * the Systems Programming Group of the University of Utah Computer |
38 | * Science Department and Ralph Campbell. | | 38 | * Science Department and Ralph Campbell. |
39 | * | | 39 | * |
40 | * Redistribution and use in source and binary forms, with or without | | 40 | * Redistribution and use in source and binary forms, with or without |
41 | * modification, are permitted provided that the following conditions | | 41 | * modification, are permitted provided that the following conditions |
42 | * are met: | | 42 | * are met: |
43 | * 1. Redistributions of source code must retain the above copyright | | 43 | * 1. Redistributions of source code must retain the above copyright |
44 | * notice, this list of conditions and the following disclaimer. | | 44 | * notice, this list of conditions and the following disclaimer. |
45 | * 2. Redistributions in binary form must reproduce the above copyright | | 45 | * 2. Redistributions in binary form must reproduce the above copyright |
46 | * notice, this list of conditions and the following disclaimer in the | | 46 | * notice, this list of conditions and the following disclaimer in the |
47 | * documentation and/or other materials provided with the distribution. | | 47 | * documentation and/or other materials provided with the distribution. |
48 | * 3. Neither the name of the University nor the names of its contributors | | 48 | * 3. Neither the name of the University nor the names of its contributors |
49 | * may be used to endorse or promote products derived from this software | | 49 | * may be used to endorse or promote products derived from this software |
50 | * without specific prior written permission. | | 50 | * without specific prior written permission. |
51 | * | | 51 | * |
52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 52 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 53 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 54 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 55 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 56 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 57 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 58 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 59 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 60 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 61 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
62 | * SUCH DAMAGE. | | 62 | * SUCH DAMAGE. |
63 | * | | 63 | * |
64 | * from: Utah Hdr: trap.c 1.32 91/04/06 | | 64 | * from: Utah Hdr: trap.c 1.32 91/04/06 |
65 | * | | 65 | * |
66 | * @(#)trap.c 8.5 (Berkeley) 1/11/94 | | 66 | * @(#)trap.c 8.5 (Berkeley) 1/11/94 |
67 | */ | | 67 | */ |
68 | /* | | 68 | /* |
69 | * Copyright (c) 1988 University of Utah. | | 69 | * Copyright (c) 1988 University of Utah. |
70 | * | | 70 | * |
71 | * This code is derived from software contributed to Berkeley by | | 71 | * This code is derived from software contributed to Berkeley by |
72 | * the Systems Programming Group of the University of Utah Computer | | 72 | * the Systems Programming Group of the University of Utah Computer |
73 | * Science Department and Ralph Campbell. | | 73 | * Science Department and Ralph Campbell. |
74 | * | | 74 | * |
75 | * Redistribution and use in source and binary forms, with or without | | 75 | * Redistribution and use in source and binary forms, with or without |
76 | * modification, are permitted provided that the following conditions | | 76 | * modification, are permitted provided that the following conditions |
77 | * are met: | | 77 | * are met: |
78 | * 1. Redistributions of source code must retain the above copyright | | 78 | * 1. Redistributions of source code must retain the above copyright |
79 | * notice, this list of conditions and the following disclaimer. | | 79 | * notice, this list of conditions and the following disclaimer. |
80 | * 2. Redistributions in binary form must reproduce the above copyright | | 80 | * 2. Redistributions in binary form must reproduce the above copyright |
81 | * notice, this list of conditions and the following disclaimer in the | | 81 | * notice, this list of conditions and the following disclaimer in the |
82 | * documentation and/or other materials provided with the distribution. | | 82 | * documentation and/or other materials provided with the distribution. |
83 | * 3. All advertising materials mentioning features or use of this software | | 83 | * 3. All advertising materials mentioning features or use of this software |
84 | * must display the following acknowledgement: | | 84 | * must display the following acknowledgement: |
85 | * This product includes software developed by the University of | | 85 | * This product includes software developed by the University of |
86 | * California, Berkeley and its contributors. | | 86 | * California, Berkeley and its contributors. |
87 | * 4. Neither the name of the University nor the names of its contributors | | 87 | * 4. Neither the name of the University nor the names of its contributors |
88 | * may be used to endorse or promote products derived from this software | | 88 | * may be used to endorse or promote products derived from this software |
89 | * without specific prior written permission. | | 89 | * without specific prior written permission. |
90 | * | | 90 | * |
91 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 91 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
92 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 92 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
101 | * SUCH DAMAGE. | | 101 | * SUCH DAMAGE. |
102 | * | | 102 | * |
103 | * from: Utah Hdr: trap.c 1.32 91/04/06 | | 103 | * from: Utah Hdr: trap.c 1.32 91/04/06 |
104 | * | | 104 | * |
105 | * @(#)trap.c 8.5 (Berkeley) 1/11/94 | | 105 | * @(#)trap.c 8.5 (Berkeley) 1/11/94 |
106 | */ | | 106 | */ |
107 | | | 107 | |
108 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 108 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
109 | | | 109 | |
110 | __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.39 2009/12/14 00:46:07 matt Exp $"); | | 110 | __KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.40 2009/12/14 18:39:19 skrll Exp $"); |
111 | | | 111 | |
112 | #if defined(_KERNEL_OPT) | | 112 | #if defined(_KERNEL_OPT) |
113 | #include "opt_sa.h" | | 113 | #include "opt_sa.h" |
114 | #endif | | 114 | #endif |
115 | | | 115 | |
116 | #include <sys/param.h> | | 116 | #include <sys/param.h> |
117 | #include <sys/systm.h> | | 117 | #include <sys/systm.h> |
118 | #include <sys/endian.h> | | 118 | #include <sys/endian.h> |
119 | #include <sys/proc.h> | | 119 | #include <sys/proc.h> |
120 | #include <sys/signal.h> | | 120 | #include <sys/signal.h> |
121 | #include <sys/syscall.h> | | 121 | #include <sys/syscall.h> |
122 | #include <sys/syscallvar.h> | | 122 | #include <sys/syscallvar.h> |
123 | #include <sys/sa.h> | | 123 | #include <sys/sa.h> |
124 | #include <sys/savar.h> | | 124 | #include <sys/savar.h> |
125 | | | 125 | |
126 | #include <uvm/uvm_extern.h> | | 126 | #include <uvm/uvm_extern.h> |
127 | | | 127 | |
128 | #include <machine/cpu.h> | | 128 | #include <machine/cpu.h> |
129 | #include <mips/trap.h> | | 129 | #include <mips/trap.h> |
130 | #include <mips/reg.h> | | 130 | #include <mips/reg.h> |
131 | #include <mips/regnum.h> /* symbolic register indices */ | | 131 | #include <mips/regnum.h> /* symbolic register indices */ |
132 | #include <mips/userret.h> | | 132 | #include <mips/userret.h> |
133 | | | 133 | |
134 | #ifndef EMULNAME | | 134 | #ifndef EMULNAME |
135 | #define EMULNAME(x) (x) | | 135 | #define EMULNAME(x) (x) |
136 | #endif | | 136 | #endif |
137 | | | 137 | |
138 | #ifndef SYSCALL_SHIFT | | 138 | #ifndef SYSCALL_SHIFT |
139 | #define SYSCALL_SHIFT 0 | | 139 | #define SYSCALL_SHIFT 0 |
140 | #endif | | 140 | #endif |
141 | | | 141 | |
142 | void EMULNAME(syscall_intern)(struct proc *); | | 142 | void EMULNAME(syscall_intern)(struct proc *); |
143 | static void EMULNAME(syscall)(struct lwp *, uint32_t, uint32_t, vaddr_t); | | 143 | static void EMULNAME(syscall)(struct lwp *, uint32_t, uint32_t, vaddr_t); |
144 | | | 144 | |
145 | register_t MachEmulateBranch(struct frame *, register_t, u_int, int); | | 145 | register_t MachEmulateBranch(struct frame *, register_t, u_int, int); |
146 | | | 146 | |
147 | void | | 147 | void |
148 | EMULNAME(syscall_intern)(struct proc *p) | | 148 | EMULNAME(syscall_intern)(struct proc *p) |
149 | { | | 149 | { |
150 | p->p_md.md_syscall = EMULNAME(syscall); | | 150 | p->p_md.md_syscall = EMULNAME(syscall); |
151 | } | | 151 | } |
152 | | | 152 | |
153 | /* | | 153 | /* |
154 | * Process a system call. | | 154 | * Process a system call. |
155 | * | | 155 | * |
156 | * System calls are strange beasts. They are passed the syscall number | | 156 | * System calls are strange beasts. They are passed the syscall number |
157 | * in v0, and the arguments in the registers (as normal). They return | | 157 | * in v0, and the arguments in the registers (as normal). They return |
158 | * an error flag in a3 (if a3 != 0 on return, the syscall had an error), | | 158 | * an error flag in a3 (if a3 != 0 on return, the syscall had an error), |
159 | * and the return value (if any) in v0 and possibly v1. | | 159 | * and the return value (if any) in v0 and possibly v1. |
160 | */ | | 160 | */ |
161 | | | 161 | |
162 | void | | 162 | void |
163 | EMULNAME(syscall)(struct lwp *l, u_int status, u_int cause, vaddr_t opc) | | 163 | EMULNAME(syscall)(struct lwp *l, u_int status, u_int cause, vaddr_t opc) |
164 | { | | 164 | { |
165 | struct proc *p = l->l_proc; | | 165 | struct proc *p = l->l_proc; |
166 | struct frame *frame = l->l_md.md_regs; | | 166 | struct frame *frame = l->l_md.md_regs; |
167 | mips_reg_t *fargs = &frame->f_regs[_R_A0]; | | 167 | mips_reg_t *fargs = &frame->f_regs[_R_A0]; |
168 | register_t *args = NULL; | | 168 | register_t *args = NULL; |
169 | register_t copyargs[2+SYS_MAXSYSARGS]; | | 169 | register_t copyargs[2+SYS_MAXSYSARGS]; |
170 | mips_reg_t saved_v0; | | 170 | mips_reg_t saved_v0; |
171 | vaddr_t usp; | | 171 | vaddr_t usp; |
172 | size_t nargs; | | 172 | size_t nargs; |
173 | const struct sysent *callp; | | 173 | const struct sysent *callp; |
174 | int code, error; | | 174 | int code, error; |
175 | #if defined(__mips_o32) | | 175 | #if defined(__mips_o32) |
176 | const int abi = _MIPS_BSD_API_O32; | | 176 | const int abi = _MIPS_BSD_API_O32; |
177 | KASSERTMSG(p->p_md.md_abi != abi, ("pid %d(%p): md_abi(%d) != abi(%d)", p->p_pid, p, p->p_md.md_abi, abi)); | | 177 | KASSERTMSG(p->p_md.md_abi != abi, ("pid %d(%p): md_abi(%d) != abi(%d)", p->p_pid, p, p->p_md.md_abi, abi)); |
178 | size_t nregs = 4; | | 178 | size_t nregs = 4; |
179 | #else | | 179 | #else |
180 | const int abi = p->p_md.md_abi; | | 180 | const int abi = p->p_md.md_abi; |
181 | size_t nregs = _MIPS_SIM_NEWABI_P(abi) ? 8 : 4; | | 181 | size_t nregs = _MIPS_SIM_NEWABI_P(abi) ? 8 : 4; |
182 | size_t i; | | 182 | size_t i; |
183 | #endif | | 183 | #endif |
184 | | | 184 | |
185 | LWP_CACHE_CREDS(l, p); | | 185 | LWP_CACHE_CREDS(l, p); |
186 | | | 186 | |
187 | uvmexp.syscalls++; | | 187 | uvmexp.syscalls++; |
188 | | | 188 | |
189 | if (cause & MIPS_CR_BR_DELAY) | | 189 | if (cause & MIPS_CR_BR_DELAY) |
190 | frame->f_regs[_R_PC] = MachEmulateBranch(frame, opc, 0, 0); | | 190 | frame->f_regs[_R_PC] = MachEmulateBranch(frame, opc, 0, 0); |
191 | else | | 191 | else |
192 | frame->f_regs[_R_PC] = opc + sizeof(uint32_t); | | 192 | frame->f_regs[_R_PC] = opc + sizeof(uint32_t); |
193 | | | 193 | |
194 | callp = p->p_emul->e_sysent; | | 194 | callp = p->p_emul->e_sysent; |
195 | saved_v0 = code = frame->f_regs[_R_V0]; | | 195 | saved_v0 = code = frame->f_regs[_R_V0]; |
196 | | | 196 | |
197 | code -= SYSCALL_SHIFT; | | 197 | code -= SYSCALL_SHIFT; |
198 | | | 198 | |
199 | #ifdef KERN_SA | | 199 | #ifdef KERN_SA |
200 | if (__predict_false((l->l_savp) | | 200 | if (__predict_false((l->l_savp) |
201 | && (l->l_savp->savp_pflags & SAVP_FLAG_DELIVERING))) | | 201 | && (l->l_savp->savp_pflags & SAVP_FLAG_DELIVERING))) |
202 | l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING; | | 202 | l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING; |
203 | #endif | | 203 | #endif |
204 | | | 204 | |
205 | if (code == SYS_syscall | | 205 | if (code == SYS_syscall |
206 | || (code == SYS___syscall && abi != _MIPS_BSD_API_O32)) { | | 206 | || (code == SYS___syscall && abi != _MIPS_BSD_API_O32)) { |
207 | /* | | 207 | /* |
208 | * Code is first argument, followed by actual args. | | 208 | * Code is first argument, followed by actual args. |
209 | */ | | 209 | */ |
210 | code = *fargs++ - SYSCALL_SHIFT; | | 210 | code = *fargs++ - SYSCALL_SHIFT; |
211 | nregs--; | | 211 | nregs--; |
212 | } else if (code == SYS___syscall) { | | 212 | } else if (code == SYS___syscall) { |
213 | /* | | 213 | /* |
214 | * Like syscall, but code is a quad, so as to maintain | | 214 | * Like syscall, but code is a quad, so as to maintain |
215 | * quad alignment for the rest of the arguments. | | 215 | * quad alignment for the rest of the arguments. |
216 | */ | | 216 | */ |
217 | code = fargs[_QUAD_LOWWORD] - SYSCALL_SHIFT; | | 217 | code = fargs[_QUAD_LOWWORD] - SYSCALL_SHIFT; |
218 | fargs += 2; | | 218 | fargs += 2; |
219 | nregs -= 2; | | 219 | nregs -= 2; |
220 | } | | 220 | } |
221 | | | 221 | |
222 | if (code >= p->p_emul->e_nsysent) | | 222 | if (code >= p->p_emul->e_nsysent) |
223 | callp += p->p_emul->e_nosys; | | 223 | callp += p->p_emul->e_nosys; |
224 | else | | 224 | else |
225 | callp += code; | | 225 | callp += code; |
226 | | | 226 | |
227 | nargs = callp->sy_narg; | | 227 | nargs = callp->sy_narg; |
228 | frame->f_regs[_R_V0] = 0; | | 228 | frame->f_regs[_R_V0] = 0; |
229 | #if !defined(__mips_o32) | | 229 | #if !defined(__mips_o32) |
230 | if (abi != _MIPS_BSD_API_O32) { | | 230 | if (abi != _MIPS_BSD_API_O32) { |
231 | #endif | | 231 | #endif |
232 | CTASSERT(sizeof(copyargs[0]) == sizeof(fargs[0])); | | 232 | CTASSERT(sizeof(copyargs[0]) == sizeof(fargs[0])); |
233 | if (nargs <= nregs) { | | 233 | if (nargs <= nregs) { |
234 | /* | | 234 | /* |
235 | * Just use the frame for the source of arguments | | 235 | * Just use the frame for the source of arguments |
236 | */ | | 236 | */ |
237 | args = fargs; | | 237 | args = fargs; |
238 | } else { | | 238 | } else { |
239 | const size_t nsaved = _MIPS_SIM_NEWABI_P(abi) ? 0 : 4; | | 239 | const size_t nsaved = _MIPS_SIM_NEWABI_P(abi) ? 0 : 4; |
240 | KASSERT(nargs <= __arraycount(copyargs)); | | 240 | KASSERT(nargs <= __arraycount(copyargs)); |
241 | args = copyargs; | | 241 | args = copyargs; |
242 | /* | | 242 | /* |
243 | * Copy the arguments passed via register from the * trap frame to our argument array | | 243 | * Copy the arguments passed via register from the |
| | | 244 | * trap frame to our argument array |
244 | */ | | 245 | */ |
245 | memcpy(copyargs, fargs, nregs * sizeof(register_t)); | | 246 | memcpy(copyargs, fargs, nregs * sizeof(register_t)); |
246 | /* | | 247 | /* |
247 | * Start copying args skipping the register slots | | 248 | * Start copying args skipping the register slots |
248 | * slots on the stack. | | 249 | * slots on the stack. |
249 | */ | | 250 | */ |
250 | usp = frame->f_regs[_R_SP] + nsaved*sizeof(register_t); | | 251 | usp = frame->f_regs[_R_SP] + nsaved*sizeof(register_t); |
251 | error = copyin((register_t *)usp, ©args[nregs], | | 252 | error = copyin((register_t *)usp, ©args[nregs], |
252 | (nargs - nregs) * sizeof(copyargs[0])); | | 253 | (nargs - nregs) * sizeof(copyargs[0])); |
253 | if (error) | | 254 | if (error) |
254 | goto bad; | | 255 | goto bad; |
255 | } | | 256 | } |
256 | #if !defined(__mips_o32) | | 257 | #if !defined(__mips_o32) |
257 | } else do { | | 258 | } else do { |
258 | /* | | 259 | /* |
259 | * The only difference between O32 and N32 is the calling | | 260 | * The only difference between O32 and N32 is the calling |
260 | * sequence. If you make O32 | | 261 | * sequence. If you make O32 |
261 | */ | | 262 | */ |
262 | int32_t copy32args[SYS_MAXSYSARGS]; | | 263 | int32_t copy32args[SYS_MAXSYSARGS]; |
263 | int32_t *cargs = copy32args; | | 264 | int32_t *cargs = copy32args; |
264 | unsigned int arg64mask = SYCALL_ARG_64_MASK(callp); | | 265 | unsigned int arg64mask = SYCALL_ARG_64_MASK(callp); |
265 | bool doing_arg64; | | 266 | bool doing_arg64; |
266 | size_t narg64 = SYCALL_NARGS64(callp); | | 267 | size_t narg64 = SYCALL_NARGS64(callp); |
267 | /* | | 268 | /* |
268 | * All arguments are 32bits wide and 64bit arguments use | | 269 | * All arguments are 32bits wide and 64bit arguments use |
269 | * two 32bit registers or stack slots. We need to remarshall | | 270 | * two 32bit registers or stack slots. We need to remarshall |
270 | * them into 64bit slots | | 271 | * them into 64bit slots |
271 | */ | | 272 | */ |
272 | args = copyargs; | | 273 | args = copyargs; |
273 | CTASSERT(sizeof(copy32args[0]) != sizeof(fargs[0])); | | 274 | CTASSERT(sizeof(copy32args[0]) != sizeof(fargs[0])); |
274 | | | 275 | |
275 | /* | | 276 | /* |
276 | * If there are no 64bit arguments and all arguments were in | | 277 | * If there are no 64bit arguments and all arguments were in |
277 | * registers, just use the frame for the source of arguments | | 278 | * registers, just use the frame for the source of arguments |
278 | */ | | 279 | */ |
279 | if (nargs <= nregs && narg64 == 0) { | | 280 | if (nargs <= nregs && narg64 == 0) { |
280 | args = fargs; | | 281 | args = fargs; |
281 | break; | | 282 | break; |
282 | } | | 283 | } |
283 | | | 284 | |
284 | if (nregs <= nargs + narg64) { | | 285 | if (nregs <= nargs + narg64) { |
285 | /* | | 286 | /* |
286 | * Grab the non-register arguments from the stack | | 287 | * Grab the non-register arguments from the stack |
287 | * after skipping the slots for the 4 register passed | | 288 | * after skipping the slots for the 4 register passed |
288 | * arguments. | | 289 | * arguments. |
289 | */ | | 290 | */ |
290 | usp = frame->f_regs[_R_SP] + 4*sizeof(int32_t); | | 291 | usp = frame->f_regs[_R_SP] + 4*sizeof(int32_t); |
291 | error = copyin((int32_t *)usp, copy32args, | | 292 | error = copyin((int32_t *)usp, copy32args, |
292 | (nargs + narg64 - nregs) * sizeof(copy32args[0])); | | 293 | (nargs + narg64 - nregs) * sizeof(copy32args[0])); |
293 | if (error) | | 294 | if (error) |
294 | goto bad; | | 295 | goto bad; |
295 | } | | 296 | } |
296 | /* | | 297 | /* |
297 | * Copy all the arguments to copyargs, starting with the ones | | 298 | * Copy all the arguments to copyargs, starting with the ones |
298 | * in registers. Using the hints in the 64bit argmask, | | 299 | * in registers. Using the hints in the 64bit argmask, |
299 | * we marshall the passed 32bit values into 64bit slots. If we | | 300 | * we marshall the passed 32bit values into 64bit slots. If we |
300 | * encounter a 64 bit argument, we grab two adjacent 32bit | | 301 | * encounter a 64 bit argument, we grab two adjacent 32bit |
301 | * values and synthesize the 64bit argument. | | 302 | * values and synthesize the 64bit argument. |
302 | */ | | 303 | */ |
303 | for (i = 0, doing_arg64 = false; i < nargs + narg64;) { | | 304 | for (i = 0, doing_arg64 = false; i < nargs + narg64;) { |
304 | register_t arg; | | 305 | register_t arg; |
305 | if (nregs > 0) { | | 306 | if (nregs > 0) { |
306 | arg = (int32_t) *fargs++; | | 307 | arg = (int32_t) *fargs++; |
307 | nregs--; | | 308 | nregs--; |
308 | } else { | | 309 | } else { |
309 | arg = *cargs++; | | 310 | arg = *cargs++; |
310 | } | | 311 | } |
311 | if (__predict_true((arg64mask & 1) == 0)) { | | 312 | if (__predict_true((arg64mask & 1) == 0)) { |
312 | /* | | 313 | /* |
313 | * Just copy it with sign extension on | | 314 | * Just copy it with sign extension on |
314 | */ | | 315 | */ |
315 | copyargs[i++] = (int32_t) arg; | | 316 | copyargs[i++] = (int32_t) arg; |
316 | arg64mask >>= 1; | | 317 | arg64mask >>= 1; |
317 | continue; | | 318 | continue; |
318 | } | | 319 | } |
319 | /* | | 320 | /* |
320 | * 64bit arg. grab the low 32 bits, discard the high. | | 321 | * 64bit arg. grab the low 32 bits, discard the high. |
321 | */ | | 322 | */ |
322 | arg = (uint32_t)arg; | | 323 | arg = (uint32_t)arg; |
323 | if (!doing_arg64) { | | 324 | if (!doing_arg64) { |
324 | /* | | 325 | /* |
325 | * Pick up the 1st word of a 64bit arg. | | 326 | * Pick up the 1st word of a 64bit arg. |
326 | * If lowword == 1 then highword == 0, | | 327 | * If lowword == 1 then highword == 0, |
327 | * so this is the highword and thus | | 328 | * so this is the highword and thus |
328 | * shifted left by 32, otherwise | | 329 | * shifted left by 32, otherwise |
329 | * lowword == 0 and highword == 1 so | | 330 | * lowword == 0 and highword == 1 so |
330 | * it isn't shifted at all. Remember | | 331 | * it isn't shifted at all. Remember |
331 | * we still need another word. | | 332 | * we still need another word. |
332 | */ | | 333 | */ |
333 | doing_arg64 = true; | | 334 | doing_arg64 = true; |
334 | copyargs[i] = arg << (_QUAD_LOWWORD*32); | | 335 | copyargs[i] = arg << (_QUAD_LOWWORD*32); |
335 | narg64--; /* one less 64bit arg */ | | 336 | narg64--; /* one less 64bit arg */ |
336 | } else { | | 337 | } else { |
337 | /* | | 338 | /* |
338 | * Pick up the 2nd word of a 64bit arg. | | 339 | * Pick up the 2nd word of a 64bit arg. |
339 | * if highword == 1, it's shifted left | | 340 | * if highword == 1, it's shifted left |
340 | * by 32, otherwise lowword == 1 and | | 341 | * by 32, otherwise lowword == 1 and |
341 | * highword == 0 so it isn't shifted at | | 342 | * highword == 0 so it isn't shifted at |
342 | * all. And now head to the next argument. | | 343 | * all. And now head to the next argument. |
343 | */ | | 344 | */ |
344 | doing_arg64 = false; | | 345 | doing_arg64 = false; |
345 | copyargs[i++] |= arg << (_QUAD_HIGHWORD*32); | | 346 | copyargs[i++] |= arg << (_QUAD_HIGHWORD*32); |
346 | arg64mask >>= 1; | | 347 | arg64mask >>= 1; |
347 | } | | 348 | } |
348 | } | | 349 | } |
349 | } while (/*CONSTCOND*/ 0); /* avoid a goto */ | | 350 | } while (/*CONSTCOND*/ 0); /* avoid a goto */ |
350 | #endif | | 351 | #endif |
351 | | | 352 | |
352 | #ifdef MIPS_SYSCALL_DEBUG | | 353 | #ifdef MIPS_SYSCALL_DEBUG |
353 | if (p->p_emul->e_syscallnames) | | 354 | if (p->p_emul->e_syscallnames) |
354 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); | | 355 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); |
355 | else | | 356 | else |
356 | printf("syscall %u:", code); | | 357 | printf("syscall %u:", code); |
357 | if (nargs == 0) | | 358 | if (nargs == 0) |
358 | printf(" <no args>"); | | 359 | printf(" <no args>"); |
359 | else for (size_t j = 0; j < nargs; j++) { | | 360 | else for (size_t j = 0; j < nargs; j++) { |
360 | if (j == nregs) printf(" *"); | | 361 | if (j == nregs) printf(" *"); |
361 | printf(" [%s%zu]=%#"PRIxREGISTER, | | 362 | printf(" [%s%zu]=%#"PRIxREGISTER, |
362 | SYCALL_ARG_64_P(callp, j) ? "+" : "", | | 363 | SYCALL_ARG_64_P(callp, j) ? "+" : "", |
363 | j, args[j]); | | 364 | j, args[j]); |
364 | } | | 365 | } |
365 | printf("\n"); | | 366 | printf("\n"); |
366 | #endif | | 367 | #endif |
367 | | | 368 | |
368 | if (__predict_false(p->p_trace_enabled) | | 369 | if (__predict_false(p->p_trace_enabled) |
369 | && (error = trace_enter(code, args, nargs)) != 0) | | 370 | && (error = trace_enter(code, args, nargs)) != 0) |
370 | goto out; | | 371 | goto out; |
371 | | | 372 | |
372 | error = (*callp->sy_call)(l, args, &frame->f_regs[_R_V0]); | | 373 | error = (*callp->sy_call)(l, args, &frame->f_regs[_R_V0]); |
373 | | | 374 | |
374 | out: | | 375 | out: |
375 | switch (error) { | | 376 | switch (error) { |
376 | case 0: | | 377 | case 0: |
377 | #if !defined(__mips_o32) | | 378 | #if !defined(__mips_o32) |
378 | if (abi == _MIPS_BSD_API_O32 && SYCALL_RET_64_P(callp)) { | | 379 | if (abi == _MIPS_BSD_API_O32 && SYCALL_RET_64_P(callp)) { |
379 | /* | | 380 | /* |
380 | * If this is from O32 and it's a 64bit quantity, | | 381 | * If this is from O32 and it's a 64bit quantity, |
381 | * split it into 2 32bit values in adjacent registers. | | 382 | * split it into 2 32bit values in adjacent registers. |
382 | */ | | 383 | */ |
383 | mips_reg_t tmp = frame->f_regs[_R_V0]; | | 384 | mips_reg_t tmp = frame->f_regs[_R_V0]; |
384 | frame->f_regs[_R_V0 + _QUAD_LOWWORD] = (int32_t) tmp; | | 385 | frame->f_regs[_R_V0 + _QUAD_LOWWORD] = (int32_t) tmp; |
385 | frame->f_regs[_R_V0 + _QUAD_HIGHWORD] = tmp >> 32; | | 386 | frame->f_regs[_R_V0 + _QUAD_HIGHWORD] = tmp >> 32; |
386 | } | | 387 | } |
387 | #endif | | 388 | #endif |
388 | #ifdef MIPS_SYSCALL_DEBUG | | 389 | #ifdef MIPS_SYSCALL_DEBUG |
389 | if (p->p_emul->e_syscallnames) | | 390 | if (p->p_emul->e_syscallnames) |
390 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); | | 391 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); |
391 | else | | 392 | else |
392 | printf("syscall %u:", code); | | 393 | printf("syscall %u:", code); |
393 | printf(" return v0=%#"PRIxREGISTER" v1=%#"PRIxREGISTER"\n", | | 394 | printf(" return v0=%#"PRIxREGISTER" v1=%#"PRIxREGISTER"\n", |
394 | frame->f_regs[_R_V0], frame->f_regs[_R_V1]); | | 395 | frame->f_regs[_R_V0], frame->f_regs[_R_V1]); |
395 | #endif | | 396 | #endif |
396 | frame->f_regs[_R_A3] = 0; | | 397 | frame->f_regs[_R_A3] = 0; |
397 | break; | | 398 | break; |
398 | case ERESTART: | | 399 | case ERESTART: |
399 | frame->f_regs[_R_V0] = saved_v0; /* restore syscall code */ | | 400 | frame->f_regs[_R_V0] = saved_v0; /* restore syscall code */ |
400 | frame->f_regs[_R_PC] = opc; | | 401 | frame->f_regs[_R_PC] = opc; |
401 | break; | | 402 | break; |
402 | case EJUSTRETURN: | | 403 | case EJUSTRETURN: |
403 | break; /* nothing to do */ | | 404 | break; /* nothing to do */ |
404 | default: | | 405 | default: |
405 | bad: | | 406 | bad: |
406 | if (p->p_emul->e_errno) | | 407 | if (p->p_emul->e_errno) |
407 | error = p->p_emul->e_errno[error]; | | 408 | error = p->p_emul->e_errno[error]; |
408 | frame->f_regs[_R_V0] = error; | | 409 | frame->f_regs[_R_V0] = error; |
409 | frame->f_regs[_R_A3] = 1; | | 410 | frame->f_regs[_R_A3] = 1; |
410 | #ifdef MIPS_SYSCALL_DEBUG | | 411 | #ifdef MIPS_SYSCALL_DEBUG |
411 | if (p->p_emul->e_syscallnames) | | 412 | if (p->p_emul->e_syscallnames) |
412 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); | | 413 | printf("syscall %s:", p->p_emul->e_syscallnames[code]); |
413 | else | | 414 | else |
414 | printf("syscall %u:", code); | | 415 | printf("syscall %u:", code); |
415 | printf(" return error=%d\n", error); | | 416 | printf(" return error=%d\n", error); |
416 | #endif | | 417 | #endif |
417 | break; | | 418 | break; |
418 | } | | 419 | } |
419 | | | 420 | |
420 | if (__predict_false(p->p_trace_enabled)) | | 421 | if (__predict_false(p->p_trace_enabled)) |
421 | trace_exit(code, &frame->f_regs[_R_V0], error); | | 422 | trace_exit(code, &frame->f_regs[_R_V0], error); |
422 | | | 423 | |
423 | userret(l); | | 424 | userret(l); |
424 | } | | 425 | } |