| @@ -1,1336 +1,1339 @@ | | | @@ -1,1336 +1,1339 @@ |
1 | /* $NetBSD: netbsd32_machdep.c,v 1.105 2015/11/07 11:47:09 martin Exp $ */ | | 1 | /* $NetBSD: netbsd32_machdep.c,v 1.106 2015/11/07 21:07:18 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1998, 2001 Matthew R. Green | | 4 | * Copyright (c) 1998, 2001 Matthew R. Green |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 21 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 24 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.105 2015/11/07 11:47:09 martin Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.106 2015/11/07 21:07:18 martin Exp $"); |
31 | | | 31 | |
32 | #ifdef _KERNEL_OPT | | 32 | #ifdef _KERNEL_OPT |
33 | #include "opt_compat_netbsd.h" | | 33 | #include "opt_compat_netbsd.h" |
34 | #include "opt_compat_sunos.h" | | 34 | #include "opt_compat_sunos.h" |
35 | #include "opt_modular.h" | | 35 | #include "opt_modular.h" |
36 | #include "opt_execfmt.h" | | 36 | #include "opt_execfmt.h" |
37 | #include "firm_events.h" | | 37 | #include "firm_events.h" |
38 | #endif | | 38 | #endif |
39 | | | 39 | |
40 | #include <sys/param.h> | | 40 | #include <sys/param.h> |
41 | #include <sys/exec.h> | | 41 | #include <sys/exec.h> |
42 | #include <sys/exec_aout.h> | | 42 | #include <sys/exec_aout.h> |
43 | #include <sys/filedesc.h> | | 43 | #include <sys/filedesc.h> |
44 | #include <sys/file.h> | | 44 | #include <sys/file.h> |
45 | #include <sys/proc.h> | | 45 | #include <sys/proc.h> |
46 | #include <sys/signalvar.h> | | 46 | #include <sys/signalvar.h> |
47 | #include <sys/systm.h> | | 47 | #include <sys/systm.h> |
48 | #include <sys/core.h> | | 48 | #include <sys/core.h> |
49 | #include <sys/mount.h> | | 49 | #include <sys/mount.h> |
50 | #include <sys/buf.h> | | 50 | #include <sys/buf.h> |
51 | #include <sys/vnode.h> | | 51 | #include <sys/vnode.h> |
52 | #include <sys/select.h> | | 52 | #include <sys/select.h> |
53 | #include <sys/socketvar.h> | | 53 | #include <sys/socketvar.h> |
54 | #include <sys/ucontext.h> | | 54 | #include <sys/ucontext.h> |
55 | #include <sys/ioctl.h> | | 55 | #include <sys/ioctl.h> |
56 | #include <sys/kmem.h> | | 56 | #include <sys/kmem.h> |
57 | | | 57 | |
58 | #include <dev/sun/event_var.h> | | 58 | #include <dev/sun/event_var.h> |
59 | | | 59 | |
60 | #include <net/if.h> | | 60 | #include <net/if.h> |
61 | #include <net/route.h> | | 61 | #include <net/route.h> |
62 | | | 62 | |
63 | #include <netinet/in.h> | | 63 | #include <netinet/in.h> |
64 | #include <netinet/in_var.h> | | 64 | #include <netinet/in_var.h> |
65 | #include <netinet/igmp.h> | | 65 | #include <netinet/igmp.h> |
66 | #include <netinet/igmp_var.h> | | 66 | #include <netinet/igmp_var.h> |
67 | #include <netinet/ip_mroute.h> | | 67 | #include <netinet/ip_mroute.h> |
68 | | | 68 | |
69 | #include <compat/netbsd32/netbsd32.h> | | 69 | #include <compat/netbsd32/netbsd32.h> |
70 | #include <compat/netbsd32/netbsd32_ioctl.h> | | 70 | #include <compat/netbsd32/netbsd32_ioctl.h> |
71 | #include <compat/netbsd32/netbsd32_syscallargs.h> | | 71 | #include <compat/netbsd32/netbsd32_syscallargs.h> |
72 | #include <compat/netbsd32/netbsd32_exec.h> | | 72 | #include <compat/netbsd32/netbsd32_exec.h> |
73 | | | 73 | |
74 | #include <compat/sys/signal.h> | | 74 | #include <compat/sys/signal.h> |
75 | #include <compat/sys/signalvar.h> | | 75 | #include <compat/sys/signalvar.h> |
76 | #include <compat/sys/siginfo.h> | | 76 | #include <compat/sys/siginfo.h> |
77 | #include <compat/sys/ucontext.h> | | 77 | #include <compat/sys/ucontext.h> |
78 | | | 78 | |
79 | #include <machine/frame.h> | | 79 | #include <machine/frame.h> |
80 | #include <machine/pcb.h> | | 80 | #include <machine/pcb.h> |
81 | #include <machine/reg.h> | | 81 | #include <machine/reg.h> |
82 | #include <machine/vmparam.h> | | 82 | #include <machine/vmparam.h> |
83 | #include <machine/vuid_event.h> | | 83 | #include <machine/vuid_event.h> |
84 | #include <machine/netbsd32_machdep.h> | | 84 | #include <machine/netbsd32_machdep.h> |
85 | #include <machine/userret.h> | | 85 | #include <machine/userret.h> |
86 | | | 86 | |
87 | /* Provide a the name of the architecture we're emulating */ | | 87 | /* Provide a the name of the architecture we're emulating */ |
88 | const char machine32[] = "sparc"; | | 88 | const char machine32[] = "sparc"; |
89 | const char machine_arch32[] = "sparc"; | | 89 | const char machine_arch32[] = "sparc"; |
90 | | | 90 | |
91 | #if NFIRM_EVENTS > 0 | | 91 | #if NFIRM_EVENTS > 0 |
92 | static int ev_out32(struct firm_event *, int, struct uio *); | | 92 | static int ev_out32(struct firm_event *, int, struct uio *); |
93 | #endif | | 93 | #endif |
94 | | | 94 | |
95 | /* | | 95 | /* |
96 | * Set up registers on exec. | | 96 | * Set up registers on exec. |
97 | * | | 97 | * |
98 | * XXX this entire mess must be fixed | | 98 | * XXX this entire mess must be fixed |
99 | */ | | 99 | */ |
100 | /* ARGSUSED */ | | 100 | /* ARGSUSED */ |
101 | void | | 101 | void |
102 | netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) | | 102 | netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) |
103 | { | | 103 | { |
104 | struct proc *p = l->l_proc; | | 104 | struct proc *p = l->l_proc; |
105 | struct trapframe64 *tf = l->l_md.md_tf; | | 105 | struct trapframe64 *tf = l->l_md.md_tf; |
106 | struct fpstate64 *fs; | | 106 | struct fpstate64 *fs; |
107 | int64_t tstate; | | 107 | int64_t tstate; |
108 | | | 108 | |
109 | /* Don't allow misaligned code by default */ | | 109 | /* Don't allow misaligned code by default */ |
110 | p->p_md.md_flags &= ~MDP_FIXALIGN; | | 110 | p->p_md.md_flags &= ~MDP_FIXALIGN; |
111 | | | 111 | |
112 | /* Mark this as a 32-bit emulation */ | | 112 | /* Mark this as a 32-bit emulation */ |
113 | p->p_flag |= PK_32; | | 113 | p->p_flag |= PK_32; |
114 | | | 114 | |
115 | netbsd32_adjust_limits(p); | | 115 | netbsd32_adjust_limits(p); |
116 | | | 116 | |
117 | /* Setup the ev_out32 hook */ | | 117 | /* Setup the ev_out32 hook */ |
118 | #if NFIRM_EVENTS > 0 | | 118 | #if NFIRM_EVENTS > 0 |
119 | if (ev_out32_hook == NULL) | | 119 | if (ev_out32_hook == NULL) |
120 | ev_out32_hook = ev_out32; | | 120 | ev_out32_hook = ev_out32; |
121 | #endif | | 121 | #endif |
122 | | | 122 | |
123 | /* | | 123 | /* |
124 | * Set the registers to 0 except for: | | 124 | * Set the registers to 0 except for: |
125 | * %o6: stack pointer, built in exec()) | | 125 | * %o6: stack pointer, built in exec()) |
126 | * %tstate: (retain icc and xcc and cwp bits) | | 126 | * %tstate: (retain icc and xcc and cwp bits) |
127 | * %g1: p->p_psstrp (used by crt0) | | 127 | * %g1: p->p_psstrp (used by crt0) |
128 | * %tpc,%tnpc: entry point of program | | 128 | * %tpc,%tnpc: entry point of program |
129 | */ | | 129 | */ |
130 | tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT) | | 130 | tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT) |
131 | | (tf->tf_tstate & TSTATE_CWP); | | 131 | | (tf->tf_tstate & TSTATE_CWP); |
132 | if ((fs = l->l_md.md_fpstate) != NULL) { | | 132 | if ((fs = l->l_md.md_fpstate) != NULL) { |
133 | /* | | 133 | /* |
134 | * We hold an FPU state. If we own *the* FPU chip state | | 134 | * We hold an FPU state. If we own *the* FPU chip state |
135 | * we must get rid of it, and the only way to do that is | | 135 | * we must get rid of it, and the only way to do that is |
136 | * to save it. In any case, get rid of our FPU state. | | 136 | * to save it. In any case, get rid of our FPU state. |
137 | */ | | 137 | */ |
138 | fpusave_lwp(l, false); | | 138 | fpusave_lwp(l, false); |
139 | pool_cache_put(fpstate_cache, fs); | | 139 | pool_cache_put(fpstate_cache, fs); |
140 | l->l_md.md_fpstate = NULL; | | 140 | l->l_md.md_fpstate = NULL; |
141 | } | | 141 | } |
142 | memset(tf, 0, sizeof *tf); | | 142 | memset(tf, 0, sizeof *tf); |
143 | tf->tf_tstate = tstate; | | 143 | tf->tf_tstate = tstate; |
144 | tf->tf_global[1] = p->p_psstrp; | | 144 | tf->tf_global[1] = p->p_psstrp; |
145 | tf->tf_pc = pack->ep_entry & ~3; | | 145 | tf->tf_pc = pack->ep_entry & ~3; |
146 | tf->tf_npc = tf->tf_pc + 4; | | 146 | tf->tf_npc = tf->tf_pc + 4; |
147 | | | 147 | |
148 | stack -= sizeof(struct rwindow32); | | 148 | stack -= sizeof(struct rwindow32); |
149 | tf->tf_out[6] = stack; | | 149 | tf->tf_out[6] = stack; |
150 | tf->tf_out[7] = 0; | | 150 | tf->tf_out[7] = 0; |
151 | } | | 151 | } |
152 | | | 152 | |
153 | #ifdef COMPAT_16 | | 153 | #ifdef COMPAT_16 |
154 | /* | | 154 | /* |
155 | * NB: since this is a 32-bit address world, sf_scp and sf_sc | | 155 | * NB: since this is a 32-bit address world, sf_scp and sf_sc |
156 | * can't be a pointer since those are 64-bits wide. | | 156 | * can't be a pointer since those are 64-bits wide. |
157 | */ | | 157 | */ |
158 | struct sparc32_sigframe { | | 158 | struct sparc32_sigframe { |
159 | int sf_signo; /* signal number */ | | 159 | int sf_signo; /* signal number */ |
160 | int sf_code; /* code */ | | 160 | int sf_code; /* code */ |
161 | u_int sf_scp; /* SunOS user addr of sigcontext */ | | 161 | u_int sf_scp; /* SunOS user addr of sigcontext */ |
162 | int sf_addr; /* SunOS compat, always 0 for now */ | | 162 | int sf_addr; /* SunOS compat, always 0 for now */ |
163 | struct netbsd32_sigcontext sf_sc; /* actual sigcontext */ | | 163 | struct netbsd32_sigcontext sf_sc; /* actual sigcontext */ |
164 | }; | | 164 | }; |
165 | | | 165 | |
166 | #undef DEBUG | | 166 | #undef DEBUG |
167 | #ifdef DEBUG | | 167 | #ifdef DEBUG |
168 | extern int sigdebug; | | 168 | extern int sigdebug; |
169 | #endif | | 169 | #endif |
170 | | | 170 | |
171 | static void | | 171 | static void |
172 | netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) | | 172 | netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) |
173 | { | | 173 | { |
174 | int sig = ksi->ksi_signo; | | 174 | int sig = ksi->ksi_signo; |
175 | struct lwp *l = curlwp; | | 175 | struct lwp *l = curlwp; |
176 | struct proc *p = l->l_proc; | | 176 | struct proc *p = l->l_proc; |
177 | struct sparc32_sigframe *fp; | | 177 | struct sparc32_sigframe *fp; |
178 | struct trapframe64 *tf; | | 178 | struct trapframe64 *tf; |
179 | int addr, onstack, error; | | 179 | int addr, onstack, error; |
180 | struct rwindow32 *oldsp, *newsp; | | 180 | struct rwindow32 *oldsp, *newsp; |
181 | sig_t catcher = SIGACTION(p, sig).sa_handler; | | 181 | sig_t catcher = SIGACTION(p, sig).sa_handler; |
182 | struct sparc32_sigframe sf; | | 182 | struct sparc32_sigframe sf; |
183 | extern char netbsd32_sigcode[], netbsd32_esigcode[]; | | 183 | extern char netbsd32_sigcode[], netbsd32_esigcode[]; |
184 | #define szsigcode (netbsd32_esigcode - netbsd32_sigcode) | | 184 | #define szsigcode (netbsd32_esigcode - netbsd32_sigcode) |
185 | | | 185 | |
186 | tf = l->l_md.md_tf; | | 186 | tf = l->l_md.md_tf; |
187 | /* Need to attempt to zero extend this 32-bit pointer */ | | 187 | /* Need to attempt to zero extend this 32-bit pointer */ |
188 | oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; | | 188 | oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6]; |
189 | /* Do we need to jump onto the signal stack? */ | | 189 | /* Do we need to jump onto the signal stack? */ |
190 | onstack = | | 190 | onstack = |
191 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | | 191 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && |
192 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; | | 192 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; |
193 | if (onstack) { | | 193 | if (onstack) { |
194 | fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp + | | 194 | fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp + |
195 | l->l_sigstk.ss_size); | | 195 | l->l_sigstk.ss_size); |
196 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 196 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
197 | } else | | 197 | } else |
198 | fp = (struct sparc32_sigframe *)oldsp; | | 198 | fp = (struct sparc32_sigframe *)oldsp; |
199 | fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7); | | 199 | fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7); |
200 | | | 200 | |
201 | #ifdef DEBUG | | 201 | #ifdef DEBUG |
202 | sigpid = p->p_pid; | | 202 | sigpid = p->p_pid; |
203 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { | | 203 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { |
204 | printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", | | 204 | printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n", |
205 | p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); | | 205 | p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp); |
206 | if (sigdebug & SDB_DDB) Debugger(); | | 206 | if (sigdebug & SDB_DDB) Debugger(); |
207 | } | | 207 | } |
208 | #endif | | 208 | #endif |
209 | /* | | 209 | /* |
210 | * Now set up the signal frame. We build it in kernel space | | 210 | * Now set up the signal frame. We build it in kernel space |
211 | * and then copy it out. We probably ought to just build it | | 211 | * and then copy it out. We probably ought to just build it |
212 | * directly in user space.... | | 212 | * directly in user space.... |
213 | */ | | 213 | */ |
214 | sf.sf_signo = sig; | | 214 | sf.sf_signo = sig; |
215 | sf.sf_code = (u_int)ksi->ksi_trap; | | 215 | sf.sf_code = (u_int)ksi->ksi_trap; |
216 | #if defined(COMPAT_SUNOS) || defined(MODULAR) | | 216 | #if defined(COMPAT_SUNOS) || defined(MODULAR) |
217 | sf.sf_scp = (u_long)&fp->sf_sc; | | 217 | sf.sf_scp = (u_long)&fp->sf_sc; |
218 | #endif | | 218 | #endif |
219 | sf.sf_addr = 0; /* XXX */ | | 219 | sf.sf_addr = 0; /* XXX */ |
220 | | | 220 | |
221 | /* | | 221 | /* |
222 | * Build the signal context to be used by sigreturn. | | 222 | * Build the signal context to be used by sigreturn. |
223 | */ | | 223 | */ |
224 | sf.sf_sc.sc_onstack = onstack; | | 224 | sf.sf_sc.sc_onstack = onstack; |
225 | sf.sf_sc.sc_mask = *mask; | | 225 | sf.sf_sc.sc_mask = *mask; |
226 | sf.sf_sc.sc_sp = (u_long)oldsp; | | 226 | sf.sf_sc.sc_sp = (u_long)oldsp; |
227 | sf.sf_sc.sc_pc = tf->tf_pc; | | 227 | sf.sf_sc.sc_pc = tf->tf_pc; |
228 | sf.sf_sc.sc_npc = tf->tf_npc; | | 228 | sf.sf_sc.sc_npc = tf->tf_npc; |
229 | sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ | | 229 | sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */ |
230 | sf.sf_sc.sc_g1 = tf->tf_global[1]; | | 230 | sf.sf_sc.sc_g1 = tf->tf_global[1]; |
231 | sf.sf_sc.sc_o0 = tf->tf_out[0]; | | 231 | sf.sf_sc.sc_o0 = tf->tf_out[0]; |
232 | | | 232 | |
233 | /* | | 233 | /* |
234 | * Put the stack in a consistent state before we whack away | | 234 | * Put the stack in a consistent state before we whack away |
235 | * at it. Note that write_user_windows may just dump the | | 235 | * at it. Note that write_user_windows may just dump the |
236 | * registers into the pcb; we need them in the process's memory. | | 236 | * registers into the pcb; we need them in the process's memory. |
237 | * We also need to make sure that when we start the signal handler, | | 237 | * We also need to make sure that when we start the signal handler, |
238 | * its %i6 (%fp), which is loaded from the newly allocated stack area, | | 238 | * its %i6 (%fp), which is loaded from the newly allocated stack area, |
239 | * joins seamlessly with the frame it was in when the signal occurred, | | 239 | * joins seamlessly with the frame it was in when the signal occurred, |
240 | * so that the debugger and _longjmp code can back up through it. | | 240 | * so that the debugger and _longjmp code can back up through it. |
241 | */ | | 241 | */ |
242 | sendsig_reset(l, sig); | | 242 | sendsig_reset(l, sig); |
243 | mutex_exit(p->p_lock); | | 243 | mutex_exit(p->p_lock); |
244 | newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); | | 244 | newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32)); |
245 | write_user_windows(); | | 245 | write_user_windows(); |
246 | #ifdef DEBUG | | 246 | #ifdef DEBUG |
247 | if ((sigdebug & SDB_KSTACK)) | | 247 | if ((sigdebug & SDB_KSTACK)) |
248 | printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", | | 248 | printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n", |
249 | fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); | | 249 | fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp); |
250 | #endif | | 250 | #endif |
251 | error = (rwindow_save(l) || | | 251 | error = (rwindow_save(l) || |
252 | copyout((void *)&sf, (void *)fp, sizeof sf) || | | 252 | copyout((void *)&sf, (void *)fp, sizeof sf) || |
253 | suword(&(((struct rwindow32 *)newsp)->rw_in[6]), (u_long)oldsp)); | | 253 | suword(&(((struct rwindow32 *)newsp)->rw_in[6]), (u_long)oldsp)); |
254 | mutex_enter(p->p_lock); | | 254 | mutex_enter(p->p_lock); |
255 | if (error) { | | 255 | if (error) { |
256 | /* | | 256 | /* |
257 | * Process has trashed its stack; give it an illegal | | 257 | * Process has trashed its stack; give it an illegal |
258 | * instruction to halt it in its tracks. | | 258 | * instruction to halt it in its tracks. |
259 | */ | | 259 | */ |
260 | #ifdef DEBUG | | 260 | #ifdef DEBUG |
261 | mutex_exit(p->p_lock); | | 261 | mutex_exit(p->p_lock); |
262 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) | | 262 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) |
263 | printf("sendsig: window save or copyout error\n"); | | 263 | printf("sendsig: window save or copyout error\n"); |
264 | printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); | | 264 | printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig); |
265 | if (sigdebug & SDB_DDB) Debugger(); | | 265 | if (sigdebug & SDB_DDB) Debugger(); |
266 | mutex_enter(p->p_lock); | | 266 | mutex_enter(p->p_lock); |
267 | #endif | | 267 | #endif |
268 | sigexit(l, SIGILL); | | 268 | sigexit(l, SIGILL); |
269 | /* NOTREACHED */ | | 269 | /* NOTREACHED */ |
270 | } | | 270 | } |
271 | | | 271 | |
272 | #ifdef DEBUG | | 272 | #ifdef DEBUG |
273 | if (sigdebug & SDB_FOLLOW) { | | 273 | if (sigdebug & SDB_FOLLOW) { |
274 | printf("sendsig: %s[%d] sig %d scp %p\n", | | 274 | printf("sendsig: %s[%d] sig %d scp %p\n", |
275 | p->p_comm, p->p_pid, sig, &fp->sf_sc); | | 275 | p->p_comm, p->p_pid, sig, &fp->sf_sc); |
276 | } | | 276 | } |
277 | #endif | | 277 | #endif |
278 | /* | | 278 | /* |
279 | * Arrange to continue execution at the code copied out in exec(). | | 279 | * Arrange to continue execution at the code copied out in exec(). |
280 | * It needs the function to call in %g1, and a new stack pointer. | | 280 | * It needs the function to call in %g1, and a new stack pointer. |
281 | */ | | 281 | */ |
282 | addr = p->p_psstrp - szsigcode; | | 282 | addr = p->p_psstrp - szsigcode; |
283 | tf->tf_global[1] = (long)catcher; | | 283 | tf->tf_global[1] = (long)catcher; |
284 | tf->tf_pc = addr; | | 284 | tf->tf_pc = addr; |
285 | tf->tf_npc = addr + 4; | | 285 | tf->tf_npc = addr + 4; |
286 | tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; | | 286 | tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp; |
287 | | | 287 | |
288 | /* Remember that we're now on the signal stack. */ | | 288 | /* Remember that we're now on the signal stack. */ |
289 | if (onstack) | | 289 | if (onstack) |
290 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 290 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
291 | | | 291 | |
292 | #ifdef DEBUG | | 292 | #ifdef DEBUG |
293 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { | | 293 | if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) { |
294 | mutex_exit(p->p_lock); | | 294 | mutex_exit(p->p_lock); |
295 | printf("sendsig: about to return to catcher %p thru %p\n", | | 295 | printf("sendsig: about to return to catcher %p thru %p\n", |
296 | catcher, addr); | | 296 | catcher, addr); |
297 | if (sigdebug & SDB_DDB) Debugger(); | | 297 | if (sigdebug & SDB_DDB) Debugger(); |
298 | mutex_enter(p->p_lock); | | 298 | mutex_enter(p->p_lock); |
299 | } | | 299 | } |
300 | #endif | | 300 | #endif |
301 | } | | 301 | } |
302 | #endif | | 302 | #endif |
303 | | | 303 | |
304 | struct sparc32_sigframe_siginfo { | | 304 | struct sparc32_sigframe_siginfo { |
305 | siginfo32_t sf_si; | | 305 | siginfo32_t sf_si; |
306 | ucontext32_t sf_uc; | | 306 | ucontext32_t sf_uc; |
307 | }; | | 307 | }; |
308 | | | 308 | |
309 | static void | | 309 | static void |
310 | netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | | 310 | netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) |
311 | { | | 311 | { |
312 | struct lwp *l = curlwp; | | 312 | struct lwp *l = curlwp; |
313 | struct proc *p = l->l_proc; | | 313 | struct proc *p = l->l_proc; |
314 | struct sigacts *ps = p->p_sigacts; | | 314 | struct sigacts *ps = p->p_sigacts; |
315 | int onstack; | | 315 | int onstack; |
316 | int sig = ksi->ksi_signo; | | 316 | int sig = ksi->ksi_signo; |
317 | ucontext32_t uc; | | 317 | ucontext32_t uc; |
318 | struct sparc32_sigframe_siginfo *fp; | | 318 | struct sparc32_sigframe_siginfo *fp; |
| | | 319 | siginfo32_t si32; |
319 | netbsd32_intptr_t catcher; | | 320 | netbsd32_intptr_t catcher; |
320 | struct trapframe64 *tf = l->l_md.md_tf; | | 321 | struct trapframe64 *tf = l->l_md.md_tf; |
321 | struct rwindow32 *oldsp, *newsp; | | 322 | struct rwindow32 *oldsp, *newsp; |
322 | int ucsz, error; | | 323 | int ucsz, error; |
323 | | | 324 | |
324 | /* Need to attempt to zero extend this 32-bit pointer */ | | 325 | /* Need to attempt to zero extend this 32-bit pointer */ |
325 | oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6]; | | 326 | oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6]; |
326 | /* Do we need to jump onto the signal stack? */ | | 327 | /* Do we need to jump onto the signal stack? */ |
327 | onstack = | | 328 | onstack = |
328 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | | 329 | (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && |
329 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; | | 330 | (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; |
330 | | | 331 | |
331 | /* Allocate space for the signal handler context. */ | | 332 | /* Allocate space for the signal handler context. */ |
332 | if (onstack) | | 333 | if (onstack) |
333 | fp = (struct sparc32_sigframe_siginfo *) | | 334 | fp = (struct sparc32_sigframe_siginfo *) |
334 | ((char *)l->l_sigstk.ss_sp + | | 335 | ((char *)l->l_sigstk.ss_sp + |
335 | l->l_sigstk.ss_size); | | 336 | l->l_sigstk.ss_size); |
336 | else | | 337 | else |
337 | fp = (struct sparc32_sigframe_siginfo *)oldsp; | | 338 | fp = (struct sparc32_sigframe_siginfo *)oldsp; |
338 | fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7); | | 339 | fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7); |
| | | 340 | |
339 | /* | | 341 | /* |
340 | * Build the signal context to be used by sigreturn. | | 342 | * Build the signal context to be used by sigreturn. |
341 | */ | | 343 | */ |
| | | 344 | memset(&uc, 0, sizeof uc); |
342 | uc.uc_flags = _UC_SIGMASK | | | 345 | uc.uc_flags = _UC_SIGMASK | |
343 | ((l->l_sigstk.ss_flags & SS_ONSTACK) | | 346 | ((l->l_sigstk.ss_flags & SS_ONSTACK) |
344 | ? _UC_SETSTACK : _UC_CLRSTACK); | | 347 | ? _UC_SETSTACK : _UC_CLRSTACK); |
345 | uc.uc_sigmask = *mask; | | 348 | uc.uc_sigmask = *mask; |
346 | uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; | | 349 | uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; |
347 | memset(&uc.uc_stack, 0, sizeof(uc.uc_stack)); | | | |
348 | | | 350 | |
349 | sendsig_reset(l, sig); | | 351 | sendsig_reset(l, sig); |
350 | | | 352 | |
351 | /* | | 353 | /* |
352 | * Now copy the stack contents out to user space. | | 354 | * Now copy the stack contents out to user space. |
353 | * We need to make sure that when we start the signal handler, | | 355 | * We need to make sure that when we start the signal handler, |
354 | * its %i6 (%fp), which is loaded from the newly allocated stack area, | | 356 | * its %i6 (%fp), which is loaded from the newly allocated stack area, |
355 | * joins seamlessly with the frame it was in when the signal occurred, | | 357 | * joins seamlessly with the frame it was in when the signal occurred, |
356 | * so that the debugger and _longjmp code can back up through it. | | 358 | * so that the debugger and _longjmp code can back up through it. |
357 | * Since we're calling the handler directly, allocate a full size | | 359 | * Since we're calling the handler directly, allocate a full size |
358 | * C stack frame. | | 360 | * C stack frame. |
359 | */ | | 361 | */ |
360 | mutex_exit(p->p_lock); | | 362 | mutex_exit(p->p_lock); |
361 | cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags); | | 363 | cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags); |
| | | 364 | netbsd32_si_to_si32(&si32, (const siginfo_t *)&ksi->ksi_info); |
362 | ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc; | | 365 | ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc; |
363 | newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32)); | | 366 | newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32)); |
364 | error = (copyout(&ksi->ksi_info, &fp->sf_si, sizeof ksi->ksi_info) || | | 367 | error = (copyout(&si32, &fp->sf_si, sizeof si32) || |
365 | copyout(&uc, &fp->sf_uc, ucsz) || | | 368 | copyout(&uc, &fp->sf_uc, ucsz) || |
366 | suword(&newsp->rw_in[6], (intptr_t)oldsp)); | | 369 | suword(&newsp->rw_in[6], (intptr_t)oldsp)); |
367 | mutex_enter(p->p_lock); | | 370 | mutex_enter(p->p_lock); |
368 | | | 371 | |
369 | if (error) { | | 372 | if (error) { |
370 | /* | | 373 | /* |
371 | * Process has trashed its stack; give it an illegal | | 374 | * Process has trashed its stack; give it an illegal |
372 | * instruction to halt it in its tracks. | | 375 | * instruction to halt it in its tracks. |
373 | */ | | 376 | */ |
374 | sigexit(l, SIGILL); | | 377 | sigexit(l, SIGILL); |
375 | /* NOTREACHED */ | | 378 | /* NOTREACHED */ |
376 | } | | 379 | } |
377 | | | 380 | |
378 | switch (ps->sa_sigdesc[sig].sd_vers) { | | 381 | switch (ps->sa_sigdesc[sig].sd_vers) { |
379 | default: | | 382 | default: |
380 | /* Unsupported trampoline version; kill the process. */ | | 383 | /* Unsupported trampoline version; kill the process. */ |
381 | sigexit(l, SIGILL); | | 384 | sigexit(l, SIGILL); |
382 | case 2: | | 385 | case 2: |
383 | /* | | 386 | /* |
384 | * Arrange to continue execution at the user's handler. | | 387 | * Arrange to continue execution at the user's handler. |
385 | * It needs a new stack pointer, a return address and | | 388 | * It needs a new stack pointer, a return address and |
386 | * three arguments: (signo, siginfo *, ucontext *). | | 389 | * three arguments: (signo, siginfo *, ucontext *). |
387 | */ | | 390 | */ |
388 | catcher = (intptr_t)SIGACTION(p, sig).sa_handler; | | 391 | catcher = (intptr_t)SIGACTION(p, sig).sa_handler; |
389 | tf->tf_pc = catcher; | | 392 | tf->tf_pc = catcher; |
390 | tf->tf_npc = catcher + 4; | | 393 | tf->tf_npc = catcher + 4; |
391 | tf->tf_out[0] = sig; | | 394 | tf->tf_out[0] = sig; |
392 | tf->tf_out[1] = (intptr_t)&fp->sf_si; | | 395 | tf->tf_out[1] = (intptr_t)&fp->sf_si; |
393 | tf->tf_out[2] = (intptr_t)&fp->sf_uc; | | 396 | tf->tf_out[2] = (intptr_t)&fp->sf_uc; |
394 | tf->tf_out[6] = (intptr_t)newsp; | | 397 | tf->tf_out[6] = (intptr_t)newsp; |
395 | tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8; | | 398 | tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8; |
396 | break; | | 399 | break; |
397 | } | | 400 | } |
398 | | | 401 | |
399 | /* Remember that we're now on the signal stack. */ | | 402 | /* Remember that we're now on the signal stack. */ |
400 | if (onstack) | | 403 | if (onstack) |
401 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 404 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
402 | } | | 405 | } |
403 | | | 406 | |
404 | void | | 407 | void |
405 | netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) | | 408 | netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) |
406 | { | | 409 | { |
407 | #ifdef COMPAT_16 | | 410 | #ifdef COMPAT_16 |
408 | if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) | | 411 | if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) |
409 | netbsd32_sendsig_sigcontext(ksi, mask); | | 412 | netbsd32_sendsig_sigcontext(ksi, mask); |
410 | else | | 413 | else |
411 | #endif | | 414 | #endif |
412 | netbsd32_sendsig_siginfo(ksi, mask); | | 415 | netbsd32_sendsig_siginfo(ksi, mask); |
413 | } | | 416 | } |
414 | | | 417 | |
415 | #undef DEBUG | | 418 | #undef DEBUG |
416 | | | 419 | |
417 | #ifdef COMPAT_13 | | 420 | #ifdef COMPAT_13 |
418 | int | | 421 | int |
419 | compat_13_netbsd32_sigreturn(struct lwp *l, const struct compat_13_netbsd32_sigreturn_args *uap, register_t *retval) | | 422 | compat_13_netbsd32_sigreturn(struct lwp *l, const struct compat_13_netbsd32_sigreturn_args *uap, register_t *retval) |
420 | { | | 423 | { |
421 | /* { | | 424 | /* { |
422 | syscallarg(struct netbsd32_sigcontext13 *) sigcntxp; | | 425 | syscallarg(struct netbsd32_sigcontext13 *) sigcntxp; |
423 | } */ | | 426 | } */ |
424 | struct netbsd32_sigcontext13 *scp; | | 427 | struct netbsd32_sigcontext13 *scp; |
425 | struct netbsd32_sigcontext13 sc; | | 428 | struct netbsd32_sigcontext13 sc; |
426 | struct trapframe64 *tf; | | 429 | struct trapframe64 *tf; |
427 | struct proc *p = l->l_proc; | | 430 | struct proc *p = l->l_proc; |
428 | sigset_t mask; | | 431 | sigset_t mask; |
429 | | | 432 | |
430 | /* First ensure consistent stack state (see sendsig). */ | | 433 | /* First ensure consistent stack state (see sendsig). */ |
431 | write_user_windows(); | | 434 | write_user_windows(); |
432 | if (rwindow_save(l)) { | | 435 | if (rwindow_save(l)) { |
433 | #ifdef DEBUG | | 436 | #ifdef DEBUG |
434 | printf("compat_13_netbsd32_sigreturn: rwindow_save(%p) failed, sending SIGILL\n", p); | | 437 | printf("compat_13_netbsd32_sigreturn: rwindow_save(%p) failed, sending SIGILL\n", p); |
435 | Debugger(); | | 438 | Debugger(); |
436 | #endif | | 439 | #endif |
437 | mutex_enter(p->p_lock); | | 440 | mutex_enter(p->p_lock); |
438 | sigexit(l, SIGILL); | | 441 | sigexit(l, SIGILL); |
439 | } | | 442 | } |
440 | #ifdef DEBUG | | 443 | #ifdef DEBUG |
441 | if (sigdebug & SDB_FOLLOW) { | | 444 | if (sigdebug & SDB_FOLLOW) { |
442 | printf("compat_13_netbsd32_sigreturn: %s[%d], sigcntxp %p\n", | | 445 | printf("compat_13_netbsd32_sigreturn: %s[%d], sigcntxp %p\n", |
443 | p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); | | 446 | p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); |
444 | if (sigdebug & SDB_DDB) Debugger(); | | 447 | if (sigdebug & SDB_DDB) Debugger(); |
445 | } | | 448 | } |
446 | #endif | | 449 | #endif |
447 | scp = (struct netbsd32_sigcontext13 *)(u_long)SCARG(uap, sigcntxp); | | 450 | scp = (struct netbsd32_sigcontext13 *)(u_long)SCARG(uap, sigcntxp); |
448 | if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) | | 451 | if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) |
449 | { | | 452 | { |
450 | #ifdef DEBUG | | 453 | #ifdef DEBUG |
451 | printf("compat_13_netbsd32_sigreturn: copyin failed\n"); | | 454 | printf("compat_13_netbsd32_sigreturn: copyin failed\n"); |
452 | Debugger(); | | 455 | Debugger(); |
453 | #endif | | 456 | #endif |
454 | return (EINVAL); | | 457 | return (EINVAL); |
455 | } | | 458 | } |
456 | scp = ≻ | | 459 | scp = ≻ |
457 | | | 460 | |
458 | tf = l->l_md.md_tf; | | 461 | tf = l->l_md.md_tf; |
459 | /* | | 462 | /* |
460 | * Only the icc bits in the psr are used, so it need not be | | 463 | * Only the icc bits in the psr are used, so it need not be |
461 | * verified. pc and npc must be multiples of 4. This is all | | 464 | * verified. pc and npc must be multiples of 4. This is all |
462 | * that is required; if it holds, just do it. | | 465 | * that is required; if it holds, just do it. |
463 | */ | | 466 | */ |
464 | if (((sc.sc_pc | sc.sc_npc) & 3) != 0) | | 467 | if (((sc.sc_pc | sc.sc_npc) & 3) != 0) |
465 | #ifdef DEBUG | | 468 | #ifdef DEBUG |
466 | { | | 469 | { |
467 | printf("compat_13_netbsd32_sigreturn: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); | | 470 | printf("compat_13_netbsd32_sigreturn: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); |
468 | Debugger(); | | 471 | Debugger(); |
469 | return (EINVAL); | | 472 | return (EINVAL); |
470 | } | | 473 | } |
471 | #else | | 474 | #else |
472 | return (EINVAL); | | 475 | return (EINVAL); |
473 | #endif | | 476 | #endif |
474 | /* take only psr ICC field */ | | 477 | /* take only psr ICC field */ |
475 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); | | 478 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); |
476 | tf->tf_pc = (int64_t)sc.sc_pc; | | 479 | tf->tf_pc = (int64_t)sc.sc_pc; |
477 | tf->tf_npc = (int64_t)sc.sc_npc; | | 480 | tf->tf_npc = (int64_t)sc.sc_npc; |
478 | tf->tf_global[1] = (int64_t)sc.sc_g1; | | 481 | tf->tf_global[1] = (int64_t)sc.sc_g1; |
479 | tf->tf_out[0] = (int64_t)sc.sc_o0; | | 482 | tf->tf_out[0] = (int64_t)sc.sc_o0; |
480 | tf->tf_out[6] = (int64_t)sc.sc_sp; | | 483 | tf->tf_out[6] = (int64_t)sc.sc_sp; |
481 | #ifdef DEBUG | | 484 | #ifdef DEBUG |
482 | if (sigdebug & SDB_FOLLOW) { | | 485 | if (sigdebug & SDB_FOLLOW) { |
483 | printf("compat_13_netbsd32_sys_sigreturn: return trapframe pc=%p sp=%p tstate=%x\n", | | 486 | printf("compat_13_netbsd32_sys_sigreturn: return trapframe pc=%p sp=%p tstate=%x\n", |
484 | (int)tf->tf_pc, (int)tf->tf_out[6], (int)tf->tf_tstate); | | 487 | (int)tf->tf_pc, (int)tf->tf_out[6], (int)tf->tf_tstate); |
485 | if (sigdebug & SDB_DDB) Debugger(); | | 488 | if (sigdebug & SDB_DDB) Debugger(); |
486 | } | | 489 | } |
487 | #endif | | 490 | #endif |
488 | mutex_enter(p->p_lock); | | 491 | mutex_enter(p->p_lock); |
489 | if (scp->sc_onstack & SS_ONSTACK) | | 492 | if (scp->sc_onstack & SS_ONSTACK) |
490 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 493 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
491 | else | | 494 | else |
492 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | | 495 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
493 | /* Restore signal mask */ | | 496 | /* Restore signal mask */ |
494 | native_sigset13_to_sigset((sigset13_t *)&scp->sc_mask, &mask); | | 497 | native_sigset13_to_sigset((sigset13_t *)&scp->sc_mask, &mask); |
495 | (void) sigprocmask1(l, SIG_SETMASK, &mask, 0); | | 498 | (void) sigprocmask1(l, SIG_SETMASK, &mask, 0); |
496 | mutex_exit(p->p_lock); | | 499 | mutex_exit(p->p_lock); |
497 | | | 500 | |
498 | return (EJUSTRETURN); | | 501 | return (EJUSTRETURN); |
499 | } | | 502 | } |
500 | #endif | | 503 | #endif |
501 | | | 504 | |
502 | /* | | 505 | /* |
503 | * System call to cleanup state after a signal | | 506 | * System call to cleanup state after a signal |
504 | * has been taken. Reset signal mask and | | 507 | * has been taken. Reset signal mask and |
505 | * stack state from context left by sendsig (above), | | 508 | * stack state from context left by sendsig (above), |
506 | * and return to the given trap frame (if there is one). | | 509 | * and return to the given trap frame (if there is one). |
507 | * Check carefully to make sure that the user has not | | 510 | * Check carefully to make sure that the user has not |
508 | * modified the state to gain improper privileges or to cause | | 511 | * modified the state to gain improper privileges or to cause |
509 | * a machine fault. | | 512 | * a machine fault. |
510 | */ | | 513 | */ |
511 | /* ARGSUSED */ | | 514 | /* ARGSUSED */ |
512 | int | | 515 | int |
513 | compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) | | 516 | compat_16_netbsd32___sigreturn14(struct lwp *l, const struct compat_16_netbsd32___sigreturn14_args *uap, register_t *retval) |
514 | { | | 517 | { |
515 | /* { | | 518 | /* { |
516 | syscallarg(struct sigcontext *) sigcntxp; | | 519 | syscallarg(struct sigcontext *) sigcntxp; |
517 | } */ | | 520 | } */ |
518 | struct netbsd32_sigcontext sc, *scp; | | 521 | struct netbsd32_sigcontext sc, *scp; |
519 | struct trapframe64 *tf; | | 522 | struct trapframe64 *tf; |
520 | struct proc *p = l->l_proc; | | 523 | struct proc *p = l->l_proc; |
521 | | | 524 | |
522 | /* First ensure consistent stack state (see sendsig). */ | | 525 | /* First ensure consistent stack state (see sendsig). */ |
523 | write_user_windows(); | | 526 | write_user_windows(); |
524 | if (rwindow_save(l)) { | | 527 | if (rwindow_save(l)) { |
525 | #ifdef DEBUG | | 528 | #ifdef DEBUG |
526 | printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); | | 529 | printf("netbsd32_sigreturn14: rwindow_save(%p) failed, sending SIGILL\n", p); |
527 | Debugger(); | | 530 | Debugger(); |
528 | #endif | | 531 | #endif |
529 | mutex_enter(p->p_lock); | | 532 | mutex_enter(p->p_lock); |
530 | sigexit(l, SIGILL); | | 533 | sigexit(l, SIGILL); |
531 | } | | 534 | } |
532 | #ifdef DEBUG | | 535 | #ifdef DEBUG |
533 | if (sigdebug & SDB_FOLLOW) { | | 536 | if (sigdebug & SDB_FOLLOW) { |
534 | printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n", | | 537 | printf("netbsd32_sigreturn14: %s[%d], sigcntxp %p\n", |
535 | p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); | | 538 | p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); |
536 | if (sigdebug & SDB_DDB) Debugger(); | | 539 | if (sigdebug & SDB_DDB) Debugger(); |
537 | } | | 540 | } |
538 | #endif | | 541 | #endif |
539 | scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp); | | 542 | scp = (struct netbsd32_sigcontext *)(u_long)SCARG(uap, sigcntxp); |
540 | if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) | | 543 | if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0)) |
541 | { | | 544 | { |
542 | #ifdef DEBUG | | 545 | #ifdef DEBUG |
543 | printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp); | | 546 | printf("netbsd32_sigreturn14: copyin failed: scp=%p\n", scp); |
544 | Debugger(); | | 547 | Debugger(); |
545 | #endif | | 548 | #endif |
546 | return (EINVAL); | | 549 | return (EINVAL); |
547 | } | | 550 | } |
548 | scp = ≻ | | 551 | scp = ≻ |
549 | | | 552 | |
550 | tf = l->l_md.md_tf; | | 553 | tf = l->l_md.md_tf; |
551 | /* | | 554 | /* |
552 | * Only the icc bits in the psr are used, so it need not be | | 555 | * Only the icc bits in the psr are used, so it need not be |
553 | * verified. pc and npc must be multiples of 4. This is all | | 556 | * verified. pc and npc must be multiples of 4. This is all |
554 | * that is required; if it holds, just do it. | | 557 | * that is required; if it holds, just do it. |
555 | */ | | 558 | */ |
556 | if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) | | 559 | if (((sc.sc_pc | sc.sc_npc) & 3) != 0 || (sc.sc_pc == 0) || (sc.sc_npc == 0)) |
557 | #ifdef DEBUG | | 560 | #ifdef DEBUG |
558 | { | | 561 | { |
559 | printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); | | 562 | printf("netbsd32_sigreturn14: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); |
560 | Debugger(); | | 563 | Debugger(); |
561 | return (EINVAL); | | 564 | return (EINVAL); |
562 | } | | 565 | } |
563 | #else | | 566 | #else |
564 | return (EINVAL); | | 567 | return (EINVAL); |
565 | #endif | | 568 | #endif |
566 | /* take only psr ICC field */ | | 569 | /* take only psr ICC field */ |
567 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); | | 570 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); |
568 | tf->tf_pc = (int64_t)sc.sc_pc; | | 571 | tf->tf_pc = (int64_t)sc.sc_pc; |
569 | tf->tf_npc = (int64_t)sc.sc_npc; | | 572 | tf->tf_npc = (int64_t)sc.sc_npc; |
570 | tf->tf_global[1] = (int64_t)sc.sc_g1; | | 573 | tf->tf_global[1] = (int64_t)sc.sc_g1; |
571 | tf->tf_out[0] = (int64_t)sc.sc_o0; | | 574 | tf->tf_out[0] = (int64_t)sc.sc_o0; |
572 | tf->tf_out[6] = (int64_t)sc.sc_sp; | | 575 | tf->tf_out[6] = (int64_t)sc.sc_sp; |
573 | #ifdef DEBUG | | 576 | #ifdef DEBUG |
574 | if (sigdebug & SDB_FOLLOW) { | | 577 | if (sigdebug & SDB_FOLLOW) { |
575 | printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", | | 578 | printf("netbsd32_sigreturn14: return trapframe pc=%p sp=%p tstate=%llx\n", |
576 | (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate); | | 579 | (vaddr_t)tf->tf_pc, (vaddr_t)tf->tf_out[6], tf->tf_tstate); |
577 | if (sigdebug & SDB_DDB) Debugger(); | | 580 | if (sigdebug & SDB_DDB) Debugger(); |
578 | } | | 581 | } |
579 | #endif | | 582 | #endif |
580 | | | 583 | |
581 | /* Restore signal stack. */ | | 584 | /* Restore signal stack. */ |
582 | mutex_enter(p->p_lock); | | 585 | mutex_enter(p->p_lock); |
583 | if (sc.sc_onstack & SS_ONSTACK) | | 586 | if (sc.sc_onstack & SS_ONSTACK) |
584 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 587 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
585 | else | | 588 | else |
586 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | | 589 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
587 | /* Restore signal mask. */ | | 590 | /* Restore signal mask. */ |
588 | (void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0); | | 591 | (void) sigprocmask1(l, SIG_SETMASK, &sc.sc_mask, 0); |
589 | mutex_exit(p->p_lock); | | 592 | mutex_exit(p->p_lock); |
590 | | | 593 | |
591 | return (EJUSTRETURN); | | 594 | return (EJUSTRETURN); |
592 | } | | 595 | } |
593 | | | 596 | |
594 | /* Unfortunately we need to convert v9 trapframe to v8 regs */ | | 597 | /* Unfortunately we need to convert v9 trapframe to v8 regs */ |
595 | int | | 598 | int |
596 | netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) | | 599 | netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) |
597 | { | | 600 | { |
598 | struct trapframe64* tf = l->l_md.md_tf; | | 601 | struct trapframe64* tf = l->l_md.md_tf; |
599 | int i; | | 602 | int i; |
600 | | | 603 | |
601 | /* | | 604 | /* |
602 | * Um, we should only do this conversion for 32-bit emulation | | 605 | * Um, we should only do this conversion for 32-bit emulation |
603 | * or when running 32-bit mode. We really need to pass in a | | 606 | * or when running 32-bit mode. We really need to pass in a |
604 | * 32-bit emulation flag! | | 607 | * 32-bit emulation flag! |
605 | */ | | 608 | */ |
606 | | | 609 | |
607 | regs->r_psr = TSTATECCR_TO_PSR(tf->tf_tstate); | | 610 | regs->r_psr = TSTATECCR_TO_PSR(tf->tf_tstate); |
608 | regs->r_pc = tf->tf_pc; | | 611 | regs->r_pc = tf->tf_pc; |
609 | regs->r_npc = tf->tf_npc; | | 612 | regs->r_npc = tf->tf_npc; |
610 | regs->r_y = tf->tf_y; | | 613 | regs->r_y = tf->tf_y; |
611 | for (i = 0; i < 8; i++) { | | 614 | for (i = 0; i < 8; i++) { |
612 | regs->r_global[i] = tf->tf_global[i]; | | 615 | regs->r_global[i] = tf->tf_global[i]; |
613 | regs->r_out[i] = tf->tf_out[i]; | | 616 | regs->r_out[i] = tf->tf_out[i]; |
614 | } | | 617 | } |
615 | /* We should also write out the ins and locals. See signal stuff */ | | 618 | /* We should also write out the ins and locals. See signal stuff */ |
616 | return (0); | | 619 | return (0); |
617 | } | | 620 | } |
618 | | | 621 | |
619 | #if 0 | | 622 | #if 0 |
620 | int | | 623 | int |
621 | netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) | | 624 | netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) |
622 | { | | 625 | { |
623 | struct trapframe64* tf = p->p_md.md_tf; | | 626 | struct trapframe64* tf = p->p_md.md_tf; |
624 | int i; | | 627 | int i; |
625 | | | 628 | |
626 | tf->tf_pc = regs->r_pc; | | 629 | tf->tf_pc = regs->r_pc; |
627 | tf->tf_npc = regs->r_npc; | | 630 | tf->tf_npc = regs->r_npc; |
628 | tf->tf_y = regs->r_pc; | | 631 | tf->tf_y = regs->r_pc; |
629 | for (i = 0; i < 8; i++) { | | 632 | for (i = 0; i < 8; i++) { |
630 | tf->tf_global[i] = regs->r_global[i]; | | 633 | tf->tf_global[i] = regs->r_global[i]; |
631 | tf->tf_out[i] = regs->r_out[i]; | | 634 | tf->tf_out[i] = regs->r_out[i]; |
632 | } | | 635 | } |
633 | /* We should also read in the ins and locals. See signal stuff */ | | 636 | /* We should also read in the ins and locals. See signal stuff */ |
634 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | | | 637 | tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | |
635 | PSRCC_TO_TSTATE(regs->r_psr); | | 638 | PSRCC_TO_TSTATE(regs->r_psr); |
636 | return (0); | | 639 | return (0); |
637 | } | | 640 | } |
638 | #endif | | 641 | #endif |
639 | | | 642 | |
640 | int | | 643 | int |
641 | netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz) | | 644 | netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz) |
642 | { | | 645 | { |
643 | extern const struct fpstate64 initfpstate; | | 646 | extern const struct fpstate64 initfpstate; |
644 | const struct fpstate64 *statep = &initfpstate; | | 647 | const struct fpstate64 *statep = &initfpstate; |
645 | int i; | | 648 | int i; |
646 | | | 649 | |
647 | if (l->l_md.md_fpstate) | | 650 | if (l->l_md.md_fpstate) |
648 | statep = l->l_md.md_fpstate; | | 651 | statep = l->l_md.md_fpstate; |
649 | for (i = 0; i < 32; i++) | | 652 | for (i = 0; i < 32; i++) |
650 | regs->fr_regs[i] = statep->fs_regs[i]; | | 653 | regs->fr_regs[i] = statep->fs_regs[i]; |
651 | regs->fr_fsr = statep->fs_fsr; | | 654 | regs->fr_fsr = statep->fs_fsr; |
652 | | | 655 | |
653 | return 0; | | 656 | return 0; |
654 | } | | 657 | } |
655 | | | 658 | |
656 | #if 0 | | 659 | #if 0 |
657 | int | | 660 | int |
658 | netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs) | | 661 | netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs) |
659 | { | | 662 | { |
660 | struct fpstate64 *statep; | | 663 | struct fpstate64 *statep; |
661 | int i; | | 664 | int i; |
662 | | | 665 | |
663 | statep = l->l_md.md_fpstate; | | 666 | statep = l->l_md.md_fpstate; |
664 | if (statep == NULL) | | 667 | if (statep == NULL) |
665 | return EINVAL; | | 668 | return EINVAL; |
666 | for (i = 0; i < 32; i++) | | 669 | for (i = 0; i < 32; i++) |
667 | statep->fs_regs[i] = regs->fr_regs[i]; | | 670 | statep->fs_regs[i] = regs->fr_regs[i]; |
668 | statep->fs_fsr = regs->fr_fsr; | | 671 | statep->fs_fsr = regs->fr_fsr; |
669 | statep->fs_qsize = 0; | | 672 | statep->fs_qsize = 0; |
670 | | | 673 | |
671 | return 0; | | 674 | return 0; |
672 | } | | 675 | } |
673 | #endif | | 676 | #endif |
674 | | | 677 | |
675 | /* | | 678 | /* |
676 | * 32-bit version of cpu_coredump. | | 679 | * 32-bit version of cpu_coredump. |
677 | */ | | 680 | */ |
678 | int | | 681 | int |
679 | cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, | | 682 | cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, |
680 | struct core32 *chdr) | | 683 | struct core32 *chdr) |
681 | { | | 684 | { |
682 | int i, error; | | 685 | int i, error; |
683 | struct md_coredump32 md_core; | | 686 | struct md_coredump32 md_core; |
684 | struct coreseg32 cseg; | | 687 | struct coreseg32 cseg; |
685 | | | 688 | |
686 | if (iocookie == NULL) { | | 689 | if (iocookie == NULL) { |
687 | CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); | | 690 | CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); |
688 | chdr->c_hdrsize = ALIGN(sizeof(*chdr)); | | 691 | chdr->c_hdrsize = ALIGN(sizeof(*chdr)); |
689 | chdr->c_seghdrsize = ALIGN(sizeof(cseg)); | | 692 | chdr->c_seghdrsize = ALIGN(sizeof(cseg)); |
690 | chdr->c_cpusize = sizeof(md_core); | | 693 | chdr->c_cpusize = sizeof(md_core); |
691 | chdr->c_nseg++; | | 694 | chdr->c_nseg++; |
692 | return 0; | | 695 | return 0; |
693 | } | | 696 | } |
694 | | | 697 | |
695 | /* Fake a v8 trapframe */ | | 698 | /* Fake a v8 trapframe */ |
696 | md_core.md_tf.tf_psr = TSTATECCR_TO_PSR(l->l_md.md_tf->tf_tstate); | | 699 | md_core.md_tf.tf_psr = TSTATECCR_TO_PSR(l->l_md.md_tf->tf_tstate); |
697 | md_core.md_tf.tf_pc = l->l_md.md_tf->tf_pc; | | 700 | md_core.md_tf.tf_pc = l->l_md.md_tf->tf_pc; |
698 | md_core.md_tf.tf_npc = l->l_md.md_tf->tf_npc; | | 701 | md_core.md_tf.tf_npc = l->l_md.md_tf->tf_npc; |
699 | md_core.md_tf.tf_y = l->l_md.md_tf->tf_y; | | 702 | md_core.md_tf.tf_y = l->l_md.md_tf->tf_y; |
700 | for (i=0; i<8; i++) { | | 703 | for (i=0; i<8; i++) { |
701 | md_core.md_tf.tf_global[i] = l->l_md.md_tf->tf_global[i]; | | 704 | md_core.md_tf.tf_global[i] = l->l_md.md_tf->tf_global[i]; |
702 | md_core.md_tf.tf_out[i] = l->l_md.md_tf->tf_out[i]; | | 705 | md_core.md_tf.tf_out[i] = l->l_md.md_tf->tf_out[i]; |
703 | } | | 706 | } |
704 | | | 707 | |
705 | if (l->l_md.md_fpstate) { | | 708 | if (l->l_md.md_fpstate) { |
706 | fpusave_lwp(l, true); | | 709 | fpusave_lwp(l, true); |
707 | /* Copy individual fields */ | | 710 | /* Copy individual fields */ |
708 | for (i=0; i<32; i++) | | 711 | for (i=0; i<32; i++) |
709 | md_core.md_fpstate.fs_regs[i] = | | 712 | md_core.md_fpstate.fs_regs[i] = |
710 | l->l_md.md_fpstate->fs_regs[i]; | | 713 | l->l_md.md_fpstate->fs_regs[i]; |
711 | md_core.md_fpstate.fs_fsr = l->l_md.md_fpstate->fs_fsr; | | 714 | md_core.md_fpstate.fs_fsr = l->l_md.md_fpstate->fs_fsr; |
712 | i = md_core.md_fpstate.fs_qsize = l->l_md.md_fpstate->fs_qsize; | | 715 | i = md_core.md_fpstate.fs_qsize = l->l_md.md_fpstate->fs_qsize; |
713 | /* Should always be zero */ | | 716 | /* Should always be zero */ |
714 | while (i--) | | 717 | while (i--) |
715 | md_core.md_fpstate.fs_queue[i] = | | 718 | md_core.md_fpstate.fs_queue[i] = |
716 | l->l_md.md_fpstate->fs_queue[i]; | | 719 | l->l_md.md_fpstate->fs_queue[i]; |
717 | } else | | 720 | } else |
718 | memset(&md_core.md_fpstate, 0, | | 721 | memset(&md_core.md_fpstate, 0, |
719 | sizeof(md_core.md_fpstate)); | | 722 | sizeof(md_core.md_fpstate)); |
720 | | | 723 | |
721 | CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); | | 724 | CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); |
722 | cseg.c_addr = 0; | | 725 | cseg.c_addr = 0; |
723 | cseg.c_size = chdr->c_cpusize; | | 726 | cseg.c_size = chdr->c_cpusize; |
724 | | | 727 | |
725 | error = coredump_write(iocookie, UIO_SYSSPACE, &cseg, | | 728 | error = coredump_write(iocookie, UIO_SYSSPACE, &cseg, |
726 | chdr->c_seghdrsize); | | 729 | chdr->c_seghdrsize); |
727 | if (error) | | 730 | if (error) |
728 | return error; | | 731 | return error; |
729 | | | 732 | |
730 | return coredump_write(iocookie, UIO_SYSSPACE, &md_core, | | 733 | return coredump_write(iocookie, UIO_SYSSPACE, &md_core, |
731 | sizeof(md_core)); | | 734 | sizeof(md_core)); |
732 | } | | 735 | } |
733 | | | 736 | |
734 | void netbsd32_cpu_getmcontext(struct lwp *, mcontext_t *, unsigned int *); | | 737 | void netbsd32_cpu_getmcontext(struct lwp *, mcontext_t *, unsigned int *); |
735 | | | 738 | |
736 | void | | 739 | void |
737 | netbsd32_cpu_getmcontext( | | 740 | netbsd32_cpu_getmcontext( |
738 | struct lwp *l, | | 741 | struct lwp *l, |
739 | /* netbsd32_mcontext_t XXX */mcontext_t *mcp, | | 742 | /* netbsd32_mcontext_t XXX */mcontext_t *mcp, |
740 | unsigned int *flags) | | 743 | unsigned int *flags) |
741 | { | | 744 | { |
742 | #if 0 | | 745 | #if 0 |
743 | /* XXX */ | | 746 | /* XXX */ |
744 | greg32_t *gr = mcp->__gregs; | | 747 | greg32_t *gr = mcp->__gregs; |
745 | const struct trapframe64 *tf = l->l_md.md_tf; | | 748 | const struct trapframe64 *tf = l->l_md.md_tf; |
746 | | | 749 | |
747 | /* First ensure consistent stack state (see sendsig). */ /* XXX? */ | | 750 | /* First ensure consistent stack state (see sendsig). */ /* XXX? */ |
748 | write_user_windows(); | | 751 | write_user_windows(); |
749 | if (rwindow_save(l)) { | | 752 | if (rwindow_save(l)) { |
750 | mutex_enter(l->l_proc->p_lock); | | 753 | mutex_enter(l->l_proc->p_lock); |
751 | sigexit(l, SIGILL); | | 754 | sigexit(l, SIGILL); |
752 | } | | 755 | } |
753 | | | 756 | |
754 | /* For now: Erase any random indicators for optional state. */ | | 757 | /* For now: Erase any random indicators for optional state. */ |
755 | (void)memset(mcp, 0, sizeof (*mcp)); | | 758 | (void)memset(mcp, 0, sizeof (*mcp)); |
756 | | | 759 | |
757 | /* Save general register context. */ | | 760 | /* Save general register context. */ |
758 | gr[_REG_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); | | 761 | gr[_REG_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); |
759 | gr[_REG_PC] = tf->tf_pc; | | 762 | gr[_REG_PC] = tf->tf_pc; |
760 | gr[_REG_nPC] = tf->tf_npc; | | 763 | gr[_REG_nPC] = tf->tf_npc; |
761 | gr[_REG_Y] = tf->tf_y; | | 764 | gr[_REG_Y] = tf->tf_y; |
762 | gr[_REG_G1] = tf->tf_global[1]; | | 765 | gr[_REG_G1] = tf->tf_global[1]; |
763 | gr[_REG_G2] = tf->tf_global[2]; | | 766 | gr[_REG_G2] = tf->tf_global[2]; |
764 | gr[_REG_G3] = tf->tf_global[3]; | | 767 | gr[_REG_G3] = tf->tf_global[3]; |
765 | gr[_REG_G4] = tf->tf_global[4]; | | 768 | gr[_REG_G4] = tf->tf_global[4]; |
766 | gr[_REG_G5] = tf->tf_global[5]; | | 769 | gr[_REG_G5] = tf->tf_global[5]; |
767 | gr[_REG_G6] = tf->tf_global[6]; | | 770 | gr[_REG_G6] = tf->tf_global[6]; |
768 | gr[_REG_G7] = tf->tf_global[7]; | | 771 | gr[_REG_G7] = tf->tf_global[7]; |
769 | gr[_REG_O0] = tf->tf_out[0]; | | 772 | gr[_REG_O0] = tf->tf_out[0]; |
770 | gr[_REG_O1] = tf->tf_out[1]; | | 773 | gr[_REG_O1] = tf->tf_out[1]; |
771 | gr[_REG_O2] = tf->tf_out[2]; | | 774 | gr[_REG_O2] = tf->tf_out[2]; |
772 | gr[_REG_O3] = tf->tf_out[3]; | | 775 | gr[_REG_O3] = tf->tf_out[3]; |
773 | gr[_REG_O4] = tf->tf_out[4]; | | 776 | gr[_REG_O4] = tf->tf_out[4]; |
774 | gr[_REG_O5] = tf->tf_out[5]; | | 777 | gr[_REG_O5] = tf->tf_out[5]; |
775 | gr[_REG_O6] = tf->tf_out[6]; | | 778 | gr[_REG_O6] = tf->tf_out[6]; |
776 | gr[_REG_O7] = tf->tf_out[7]; | | 779 | gr[_REG_O7] = tf->tf_out[7]; |
777 | *flags |= (_UC_CPU|_UC_TLSBASE); | | 780 | *flags |= (_UC_CPU|_UC_TLSBASE); |
778 | | | 781 | |
779 | mcp->__gwins = 0; | | 782 | mcp->__gwins = 0; |
780 | | | 783 | |
781 | | | 784 | |
782 | /* Save FP register context, if any. */ | | 785 | /* Save FP register context, if any. */ |
783 | if (l->l_md.md_fpstate != NULL) { | | 786 | if (l->l_md.md_fpstate != NULL) { |
784 | struct fpstate *fsp; | | 787 | struct fpstate *fsp; |
785 | netbsd32_fpregset_t *fpr = &mcp->__fpregs; | | 788 | netbsd32_fpregset_t *fpr = &mcp->__fpregs; |
786 | | | 789 | |
787 | /* | | 790 | /* |
788 | * If our FP context is currently held in the FPU, take a | | 791 | * If our FP context is currently held in the FPU, take a |
789 | * private snapshot - lazy FPU context switching can deal | | 792 | * private snapshot - lazy FPU context switching can deal |
790 | * with it later when it becomes necessary. | | 793 | * with it later when it becomes necessary. |
791 | * Otherwise, get it from the process's save area. | | 794 | * Otherwise, get it from the process's save area. |
792 | */ | | 795 | */ |
793 | fpusave_lwp(l, true); | | 796 | fpusave_lwp(l, true); |
794 | fsp = l->l_md.md_fpstate; | | 797 | fsp = l->l_md.md_fpstate; |
795 | memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); | | 798 | memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); |
796 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ | | 799 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ |
797 | mcp->__fpregs.__fpu_fsr = fs.fs_fsr; | | 800 | mcp->__fpregs.__fpu_fsr = fs.fs_fsr; |
798 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ | | 801 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ |
799 | mcp->__fpregs.__fpu_q_entrysize = | | 802 | mcp->__fpregs.__fpu_q_entrysize = |
800 | sizeof (struct netbsd32_fq); | | 803 | sizeof (struct netbsd32_fq); |
801 | mcp->__fpregs.__fpu_en = 1; | | 804 | mcp->__fpregs.__fpu_en = 1; |
802 | *flags |= _UC_FPU; | | 805 | *flags |= _UC_FPU; |
803 | } else { | | 806 | } else { |
804 | mcp->__fpregs.__fpu_en = 0; | | 807 | mcp->__fpregs.__fpu_en = 0; |
805 | } | | 808 | } |
806 | | | 809 | |
807 | mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ | | 810 | mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ |
808 | #endif | | 811 | #endif |
809 | } | | 812 | } |
810 | | | 813 | |
811 | int netbsd32_cpu_setmcontext(struct lwp *, mcontext_t *, unsigned int); | | 814 | int netbsd32_cpu_setmcontext(struct lwp *, mcontext_t *, unsigned int); |
812 | | | 815 | |
813 | int | | 816 | int |
814 | netbsd32_cpu_setmcontext( | | 817 | netbsd32_cpu_setmcontext( |
815 | struct lwp *l, | | 818 | struct lwp *l, |
816 | /* XXX const netbsd32_*/mcontext_t *mcp, | | 819 | /* XXX const netbsd32_*/mcontext_t *mcp, |
817 | unsigned int flags) | | 820 | unsigned int flags) |
818 | { | | 821 | { |
819 | #ifdef NOT_YET | | 822 | #ifdef NOT_YET |
820 | /* XXX */ | | 823 | /* XXX */ |
821 | greg32_t *gr = mcp->__gregs; | | 824 | greg32_t *gr = mcp->__gregs; |
822 | struct trapframe64 *tf = l->l_md.md_tf; | | 825 | struct trapframe64 *tf = l->l_md.md_tf; |
823 | | | 826 | |
824 | /* First ensure consistent stack state (see sendsig). */ | | 827 | /* First ensure consistent stack state (see sendsig). */ |
825 | write_user_windows(); | | 828 | write_user_windows(); |
826 | if (rwindow_save(p)) { | | 829 | if (rwindow_save(p)) { |
827 | mutex_enter(l->l_proc->p_lock); | | 830 | mutex_enter(l->l_proc->p_lock); |
828 | sigexit(p, SIGILL); | | 831 | sigexit(p, SIGILL); |
829 | } | | 832 | } |
830 | | | 833 | |
831 | if ((flags & _UC_CPU) != 0) { | | 834 | if ((flags & _UC_CPU) != 0) { |
832 | /* | | 835 | /* |
833 | * Only the icc bits in the psr are used, so it need not be | | 836 | * Only the icc bits in the psr are used, so it need not be |
834 | * verified. pc and npc must be multiples of 4. This is all | | 837 | * verified. pc and npc must be multiples of 4. This is all |
835 | * that is required; if it holds, just do it. | | 838 | * that is required; if it holds, just do it. |
836 | */ | | 839 | */ |
837 | if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 || | | 840 | if (((gr[_REG_PC] | gr[_REG_nPC]) & 3) != 0 || |
838 | gr[_REG_PC] == 0 || gr[_REG_nPC] == 0) | | 841 | gr[_REG_PC] == 0 || gr[_REG_nPC] == 0) |
839 | return (EINVAL); | | 842 | return (EINVAL); |
840 | | | 843 | |
841 | /* Restore general register context. */ | | 844 | /* Restore general register context. */ |
842 | /* take only tstate CCR (and ASI) fields */ | | 845 | /* take only tstate CCR (and ASI) fields */ |
843 | tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | | | 846 | tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | |
844 | PSRCC_TO_TSTATE(gr[_REG_PSR]); | | 847 | PSRCC_TO_TSTATE(gr[_REG_PSR]); |
845 | tf->tf_pc = (uint64_t)gr[_REG_PC]; | | 848 | tf->tf_pc = (uint64_t)gr[_REG_PC]; |
846 | tf->tf_npc = (uint64_t)gr[_REG_nPC]; | | 849 | tf->tf_npc = (uint64_t)gr[_REG_nPC]; |
847 | tf->tf_y = (uint64_t)gr[_REG_Y]; | | 850 | tf->tf_y = (uint64_t)gr[_REG_Y]; |
848 | tf->tf_global[1] = (uint64_t)gr[_REG_G1]; | | 851 | tf->tf_global[1] = (uint64_t)gr[_REG_G1]; |
849 | tf->tf_global[2] = (uint64_t)gr[_REG_G2]; | | 852 | tf->tf_global[2] = (uint64_t)gr[_REG_G2]; |
850 | tf->tf_global[3] = (uint64_t)gr[_REG_G3]; | | 853 | tf->tf_global[3] = (uint64_t)gr[_REG_G3]; |
851 | tf->tf_global[4] = (uint64_t)gr[_REG_G4]; | | 854 | tf->tf_global[4] = (uint64_t)gr[_REG_G4]; |
852 | tf->tf_global[5] = (uint64_t)gr[_REG_G5]; | | 855 | tf->tf_global[5] = (uint64_t)gr[_REG_G5]; |
853 | tf->tf_global[6] = (uint64_t)gr[_REG_G6]; | | 856 | tf->tf_global[6] = (uint64_t)gr[_REG_G6]; |
854 | tf->tf_global[7] = (uint64_t)gr[_REG_G7]; | | 857 | tf->tf_global[7] = (uint64_t)gr[_REG_G7]; |
855 | tf->tf_out[0] = (uint64_t)gr[_REG_O0]; | | 858 | tf->tf_out[0] = (uint64_t)gr[_REG_O0]; |
856 | tf->tf_out[1] = (uint64_t)gr[_REG_O1]; | | 859 | tf->tf_out[1] = (uint64_t)gr[_REG_O1]; |
857 | tf->tf_out[2] = (uint64_t)gr[_REG_O2]; | | 860 | tf->tf_out[2] = (uint64_t)gr[_REG_O2]; |
858 | tf->tf_out[3] = (uint64_t)gr[_REG_O3]; | | 861 | tf->tf_out[3] = (uint64_t)gr[_REG_O3]; |
859 | tf->tf_out[4] = (uint64_t)gr[_REG_O4]; | | 862 | tf->tf_out[4] = (uint64_t)gr[_REG_O4]; |
860 | tf->tf_out[5] = (uint64_t)gr[_REG_O5]; | | 863 | tf->tf_out[5] = (uint64_t)gr[_REG_O5]; |
861 | tf->tf_out[6] = (uint64_t)gr[_REG_O6]; | | 864 | tf->tf_out[6] = (uint64_t)gr[_REG_O6]; |
862 | tf->tf_out[7] = (uint64_t)gr[_REG_O7]; | | 865 | tf->tf_out[7] = (uint64_t)gr[_REG_O7]; |
863 | /* %asi restored above; %fprs not yet supported. */ | | 866 | /* %asi restored above; %fprs not yet supported. */ |
864 | | | 867 | |
865 | /* XXX mcp->__gwins */ | | 868 | /* XXX mcp->__gwins */ |
866 | } | | 869 | } |
867 | | | 870 | |
868 | /* Restore FP register context, if any. */ | | 871 | /* Restore FP register context, if any. */ |
869 | if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) { | | 872 | if ((flags & _UC_FPU) != 0 && mcp->__fpregs.__fpu_en != 0) { |
870 | struct fpstate *fsp; | | 873 | struct fpstate *fsp; |
871 | const netbsd32_fpregset_t *fpr = &mcp->__fpregs; | | 874 | const netbsd32_fpregset_t *fpr = &mcp->__fpregs; |
872 | int reload = 0; | | 875 | int reload = 0; |
873 | | | 876 | |
874 | /* | | 877 | /* |
875 | * If we're the current FPU owner, simply reload it from | | 878 | * If we're the current FPU owner, simply reload it from |
876 | * the supplied context. Otherwise, store it into the | | 879 | * the supplied context. Otherwise, store it into the |
877 | * process' FPU save area (which is used to restore from | | 880 | * process' FPU save area (which is used to restore from |
878 | * by lazy FPU context switching); allocate it if necessary. | | 881 | * by lazy FPU context switching); allocate it if necessary. |
879 | */ | | 882 | */ |
880 | /* | | 883 | /* |
881 | * XXX Should we really activate the supplied FPU context | | 884 | * XXX Should we really activate the supplied FPU context |
882 | * XXX immediately or just fault it in later? | | 885 | * XXX immediately or just fault it in later? |
883 | */ | | 886 | */ |
884 | if ((fsp = l->l_md.md_fpstate) == NULL) { | | 887 | if ((fsp = l->l_md.md_fpstate) == NULL) { |
885 | fsp = pool_cache_get(fpstate_cache, PR_WAITOK); | | 888 | fsp = pool_cache_get(fpstate_cache, PR_WAITOK); |
886 | l->l_md.md_fpstate = fsp; | | 889 | l->l_md.md_fpstate = fsp; |
887 | } else { | | 890 | } else { |
888 | /* Drop the live context on the floor. */ | | 891 | /* Drop the live context on the floor. */ |
889 | fpusave_lwp(l, false); | | 892 | fpusave_lwp(l, false); |
890 | reload = 1; | | 893 | reload = 1; |
891 | } | | 894 | } |
892 | /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ | | 895 | /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ |
893 | memcpy(fsp->fs_regs, fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); | | 896 | memcpy(fsp->fs_regs, fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); |
894 | fsp->fs_fsr = fpr->__fpu_fsr; /* don't care about fcc1-3 */ | | 897 | fsp->fs_fsr = fpr->__fpu_fsr; /* don't care about fcc1-3 */ |
895 | fsp->fs_qsize = 0; | | 898 | fsp->fs_qsize = 0; |
896 | | | 899 | |
897 | #if 0 | | 900 | #if 0 |
898 | /* Need more info! */ | | 901 | /* Need more info! */ |
899 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ | | 902 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ |
900 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ | | 903 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ |
901 | #endif | | 904 | #endif |
902 | | | 905 | |
903 | /* Reload context again, if necessary. */ | | 906 | /* Reload context again, if necessary. */ |
904 | if (reload) | | 907 | if (reload) |
905 | loadfpstate(fsp); | | 908 | loadfpstate(fsp); |
906 | } | | 909 | } |
907 | | | 910 | |
908 | /* XXX mcp->__xrs */ | | 911 | /* XXX mcp->__xrs */ |
909 | /* XXX mcp->__asrs */ | | 912 | /* XXX mcp->__asrs */ |
910 | #endif | | 913 | #endif |
911 | return (0); | | 914 | return (0); |
912 | } | | 915 | } |
913 | | | 916 | |
914 | #if NFIRM_EVENTS > 0 | | 917 | #if NFIRM_EVENTS > 0 |
915 | /* | | 918 | /* |
916 | * Write out a series of 32-bit firm_events. | | 919 | * Write out a series of 32-bit firm_events. |
917 | */ | | 920 | */ |
918 | int | | 921 | int |
919 | ev_out32(struct firm_event *e, int n, struct uio *uio) | | 922 | ev_out32(struct firm_event *e, int n, struct uio *uio) |
920 | { | | 923 | { |
921 | struct firm_event32 e32; | | 924 | struct firm_event32 e32; |
922 | int error = 0; | | 925 | int error = 0; |
923 | | | 926 | |
924 | while (n-- && error == 0) { | | 927 | while (n-- && error == 0) { |
925 | e32.id = e->id; | | 928 | e32.id = e->id; |
926 | e32.value = e->value; | | 929 | e32.value = e->value; |
927 | e32.time.tv_sec = e->time.tv_sec; | | 930 | e32.time.tv_sec = e->time.tv_sec; |
928 | e32.time.tv_usec = e->time.tv_usec; | | 931 | e32.time.tv_usec = e->time.tv_usec; |
929 | error = uiomove((void *)&e32, sizeof(e32), uio); | | 932 | error = uiomove((void *)&e32, sizeof(e32), uio); |
930 | e++; | | 933 | e++; |
931 | } | | 934 | } |
932 | return (error); | | 935 | return (error); |
933 | } | | 936 | } |
934 | #endif | | 937 | #endif |
935 | | | 938 | |
936 | /* | | 939 | /* |
937 | * ioctl code | | 940 | * ioctl code |
938 | */ | | 941 | */ |
939 | | | 942 | |
940 | #include <dev/sun/fbio.h> | | 943 | #include <dev/sun/fbio.h> |
941 | #include <machine/openpromio.h> | | 944 | #include <machine/openpromio.h> |
942 | | | 945 | |
943 | /* from arch/sparc/include/fbio.h */ | | 946 | /* from arch/sparc/include/fbio.h */ |
944 | #if 0 | | 947 | #if 0 |
945 | /* unused */ | | 948 | /* unused */ |
946 | #define FBIOGINFO _IOR('F', 2, struct fbinfo) | | 949 | #define FBIOGINFO _IOR('F', 2, struct fbinfo) |
947 | #endif | | 950 | #endif |
948 | | | 951 | |
949 | struct netbsd32_fbcmap { | | 952 | struct netbsd32_fbcmap { |
950 | int index; /* first element (0 origin) */ | | 953 | int index; /* first element (0 origin) */ |
951 | int count; /* number of elements */ | | 954 | int count; /* number of elements */ |
952 | netbsd32_u_charp red; /* red color map elements */ | | 955 | netbsd32_u_charp red; /* red color map elements */ |
953 | netbsd32_u_charp green; /* green color map elements */ | | 956 | netbsd32_u_charp green; /* green color map elements */ |
954 | netbsd32_u_charp blue; /* blue color map elements */ | | 957 | netbsd32_u_charp blue; /* blue color map elements */ |
955 | }; | | 958 | }; |
956 | #if 1 | | 959 | #if 1 |
957 | #define FBIOPUTCMAP32 _IOW('F', 3, struct netbsd32_fbcmap) | | 960 | #define FBIOPUTCMAP32 _IOW('F', 3, struct netbsd32_fbcmap) |
958 | #define FBIOGETCMAP32 _IOW('F', 4, struct netbsd32_fbcmap) | | 961 | #define FBIOGETCMAP32 _IOW('F', 4, struct netbsd32_fbcmap) |
959 | #endif | | 962 | #endif |
960 | | | 963 | |
961 | struct netbsd32_fbcursor { | | 964 | struct netbsd32_fbcursor { |
962 | short set; /* what to set */ | | 965 | short set; /* what to set */ |
963 | short enable; /* enable/disable cursor */ | | 966 | short enable; /* enable/disable cursor */ |
964 | struct fbcurpos pos; /* cursor's position */ | | 967 | struct fbcurpos pos; /* cursor's position */ |
965 | struct fbcurpos hot; /* cursor's hot spot */ | | 968 | struct fbcurpos hot; /* cursor's hot spot */ |
966 | struct netbsd32_fbcmap cmap; /* color map info */ | | 969 | struct netbsd32_fbcmap cmap; /* color map info */ |
967 | struct fbcurpos size; /* cursor's bit map size */ | | 970 | struct fbcurpos size; /* cursor's bit map size */ |
968 | netbsd32_charp image; /* cursor's image bits */ | | 971 | netbsd32_charp image; /* cursor's image bits */ |
969 | netbsd32_charp mask; /* cursor's mask bits */ | | 972 | netbsd32_charp mask; /* cursor's mask bits */ |
970 | }; | | 973 | }; |
971 | #if 1 | | 974 | #if 1 |
972 | #define FBIOSCURSOR32 _IOW('F', 24, struct netbsd32_fbcursor) | | 975 | #define FBIOSCURSOR32 _IOW('F', 24, struct netbsd32_fbcursor) |
973 | #define FBIOGCURSOR32 _IOWR('F', 25, struct netbsd32_fbcursor) | | 976 | #define FBIOGCURSOR32 _IOWR('F', 25, struct netbsd32_fbcursor) |
974 | #endif | | 977 | #endif |
975 | | | 978 | |
976 | /* from arch/sparc/include/openpromio.h */ | | 979 | /* from arch/sparc/include/openpromio.h */ |
977 | struct netbsd32_opiocdesc { | | 980 | struct netbsd32_opiocdesc { |
978 | int op_nodeid; /* passed or returned node id */ | | 981 | int op_nodeid; /* passed or returned node id */ |
979 | int op_namelen; /* length of op_name */ | | 982 | int op_namelen; /* length of op_name */ |
980 | netbsd32_charp op_name; /* pointer to field name */ | | 983 | netbsd32_charp op_name; /* pointer to field name */ |
981 | int op_buflen; /* length of op_buf (value-result) */ | | 984 | int op_buflen; /* length of op_buf (value-result) */ |
982 | netbsd32_charp op_buf; /* pointer to field value */ | | 985 | netbsd32_charp op_buf; /* pointer to field value */ |
983 | }; | | 986 | }; |
984 | #if 1 | | 987 | #if 1 |
985 | #define OPIOCGET32 _IOWR('O', 1, struct netbsd32_opiocdesc) /* get openprom field */ | | 988 | #define OPIOCGET32 _IOWR('O', 1, struct netbsd32_opiocdesc) /* get openprom field */ |
986 | #define OPIOCSET32 _IOW('O', 2, struct netbsd32_opiocdesc) /* set openprom field */ | | 989 | #define OPIOCSET32 _IOW('O', 2, struct netbsd32_opiocdesc) /* set openprom field */ |
987 | #define OPIOCNEXTPROP32 _IOWR('O', 3, struct netbsd32_opiocdesc) /* get next property */ | | 990 | #define OPIOCNEXTPROP32 _IOWR('O', 3, struct netbsd32_opiocdesc) /* get next property */ |
988 | #endif | | 991 | #endif |
989 | | | 992 | |
990 | /* prototypes for the converters */ | | 993 | /* prototypes for the converters */ |
991 | static inline void netbsd32_to_fbcmap(struct netbsd32_fbcmap *, | | 994 | static inline void netbsd32_to_fbcmap(struct netbsd32_fbcmap *, |
992 | struct fbcmap *, u_long); | | 995 | struct fbcmap *, u_long); |
993 | static inline void netbsd32_to_fbcursor(struct netbsd32_fbcursor *, | | 996 | static inline void netbsd32_to_fbcursor(struct netbsd32_fbcursor *, |
994 | struct fbcursor *, u_long); | | 997 | struct fbcursor *, u_long); |
995 | static inline void netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *, | | 998 | static inline void netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *, |
996 | struct opiocdesc *, u_long); | | 999 | struct opiocdesc *, u_long); |
997 | | | 1000 | |
998 | static inline void netbsd32_from_fbcmap(struct fbcmap *, | | 1001 | static inline void netbsd32_from_fbcmap(struct fbcmap *, |
999 | struct netbsd32_fbcmap *, u_long); | | 1002 | struct netbsd32_fbcmap *, u_long); |
1000 | static inline void netbsd32_from_fbcursor(struct fbcursor *, | | 1003 | static inline void netbsd32_from_fbcursor(struct fbcursor *, |
1001 | struct netbsd32_fbcursor *, u_long); | | 1004 | struct netbsd32_fbcursor *, u_long); |
1002 | static inline void netbsd32_from_opiocdesc(struct opiocdesc *, | | 1005 | static inline void netbsd32_from_opiocdesc(struct opiocdesc *, |
1003 | struct netbsd32_opiocdesc *, | | 1006 | struct netbsd32_opiocdesc *, |
1004 | u_long); | | 1007 | u_long); |
1005 | | | 1008 | |
1006 | /* convert to/from different structures */ | | 1009 | /* convert to/from different structures */ |
1007 | static inline void | | 1010 | static inline void |
1008 | netbsd32_to_fbcmap(struct netbsd32_fbcmap *s32p, struct fbcmap *p, u_long cmd) | | 1011 | netbsd32_to_fbcmap(struct netbsd32_fbcmap *s32p, struct fbcmap *p, u_long cmd) |
1009 | { | | 1012 | { |
1010 | | | 1013 | |
1011 | p->index = s32p->index; | | 1014 | p->index = s32p->index; |
1012 | p->count = s32p->count; | | 1015 | p->count = s32p->count; |
1013 | p->red = NETBSD32PTR64(s32p->red); | | 1016 | p->red = NETBSD32PTR64(s32p->red); |
1014 | p->green = NETBSD32PTR64(s32p->green); | | 1017 | p->green = NETBSD32PTR64(s32p->green); |
1015 | p->blue = NETBSD32PTR64(s32p->blue); | | 1018 | p->blue = NETBSD32PTR64(s32p->blue); |
1016 | } | | 1019 | } |
1017 | | | 1020 | |
1018 | static inline void | | 1021 | static inline void |
1019 | netbsd32_to_fbcursor(struct netbsd32_fbcursor *s32p, struct fbcursor *p, u_long cmd) | | 1022 | netbsd32_to_fbcursor(struct netbsd32_fbcursor *s32p, struct fbcursor *p, u_long cmd) |
1020 | { | | 1023 | { |
1021 | | | 1024 | |
1022 | p->set = s32p->set; | | 1025 | p->set = s32p->set; |
1023 | p->enable = s32p->enable; | | 1026 | p->enable = s32p->enable; |
1024 | p->pos = s32p->pos; | | 1027 | p->pos = s32p->pos; |
1025 | p->hot = s32p->hot; | | 1028 | p->hot = s32p->hot; |
1026 | netbsd32_to_fbcmap(&s32p->cmap, &p->cmap, cmd); | | 1029 | netbsd32_to_fbcmap(&s32p->cmap, &p->cmap, cmd); |
1027 | p->size = s32p->size; | | 1030 | p->size = s32p->size; |
1028 | p->image = NETBSD32PTR64(s32p->image); | | 1031 | p->image = NETBSD32PTR64(s32p->image); |
1029 | p->mask = NETBSD32PTR64(s32p->mask); | | 1032 | p->mask = NETBSD32PTR64(s32p->mask); |
1030 | } | | 1033 | } |
1031 | | | 1034 | |
1032 | static inline void | | 1035 | static inline void |
1033 | netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *s32p, struct opiocdesc *p, u_long cmd) | | 1036 | netbsd32_to_opiocdesc(struct netbsd32_opiocdesc *s32p, struct opiocdesc *p, u_long cmd) |
1034 | { | | 1037 | { |
1035 | | | 1038 | |
1036 | p->op_nodeid = s32p->op_nodeid; | | 1039 | p->op_nodeid = s32p->op_nodeid; |
1037 | p->op_namelen = s32p->op_namelen; | | 1040 | p->op_namelen = s32p->op_namelen; |
1038 | p->op_name = NETBSD32PTR64(s32p->op_name); | | 1041 | p->op_name = NETBSD32PTR64(s32p->op_name); |
1039 | p->op_buflen = s32p->op_buflen; | | 1042 | p->op_buflen = s32p->op_buflen; |
1040 | p->op_buf = NETBSD32PTR64(s32p->op_buf); | | 1043 | p->op_buf = NETBSD32PTR64(s32p->op_buf); |
1041 | } | | 1044 | } |
1042 | | | 1045 | |
1043 | static inline void | | 1046 | static inline void |
1044 | netbsd32_from_fbcmap(struct fbcmap *p, struct netbsd32_fbcmap *s32p, u_long cmd) | | 1047 | netbsd32_from_fbcmap(struct fbcmap *p, struct netbsd32_fbcmap *s32p, u_long cmd) |
1045 | { | | 1048 | { |
1046 | | | 1049 | |
1047 | s32p->index = p->index; | | 1050 | s32p->index = p->index; |
1048 | s32p->count = p->count; | | 1051 | s32p->count = p->count; |
1049 | /* filled in */ | | 1052 | /* filled in */ |
1050 | #if 0 | | 1053 | #if 0 |
1051 | s32p->red = (netbsd32_u_charp)p->red; | | 1054 | s32p->red = (netbsd32_u_charp)p->red; |
1052 | s32p->green = (netbsd32_u_charp)p->green; | | 1055 | s32p->green = (netbsd32_u_charp)p->green; |
1053 | s32p->blue = (netbsd32_u_charp)p->blue; | | 1056 | s32p->blue = (netbsd32_u_charp)p->blue; |
1054 | #endif | | 1057 | #endif |
1055 | } | | 1058 | } |
1056 | | | 1059 | |
1057 | static inline void | | 1060 | static inline void |
1058 | netbsd32_from_fbcursor(struct fbcursor *p, struct netbsd32_fbcursor *s32p, u_long cmd) | | 1061 | netbsd32_from_fbcursor(struct fbcursor *p, struct netbsd32_fbcursor *s32p, u_long cmd) |
1059 | { | | 1062 | { |
1060 | | | 1063 | |
1061 | s32p->set = p->set; | | 1064 | s32p->set = p->set; |
1062 | s32p->enable = p->enable; | | 1065 | s32p->enable = p->enable; |
1063 | s32p->pos = p->pos; | | 1066 | s32p->pos = p->pos; |
1064 | s32p->hot = p->hot; | | 1067 | s32p->hot = p->hot; |
1065 | netbsd32_from_fbcmap(&p->cmap, &s32p->cmap, cmd); | | 1068 | netbsd32_from_fbcmap(&p->cmap, &s32p->cmap, cmd); |
1066 | s32p->size = p->size; | | 1069 | s32p->size = p->size; |
1067 | /* filled in */ | | 1070 | /* filled in */ |
1068 | #if 0 | | 1071 | #if 0 |
1069 | s32p->image = (netbsd32_charp)p->image; | | 1072 | s32p->image = (netbsd32_charp)p->image; |
1070 | s32p->mask = (netbsd32_charp)p->mask; | | 1073 | s32p->mask = (netbsd32_charp)p->mask; |
1071 | #endif | | 1074 | #endif |
1072 | } | | 1075 | } |
1073 | | | 1076 | |
1074 | static inline void | | 1077 | static inline void |
1075 | netbsd32_from_opiocdesc(struct opiocdesc *p, struct netbsd32_opiocdesc *s32p, u_long cmd) | | 1078 | netbsd32_from_opiocdesc(struct opiocdesc *p, struct netbsd32_opiocdesc *s32p, u_long cmd) |
1076 | { | | 1079 | { |
1077 | | | 1080 | |
1078 | s32p->op_nodeid = p->op_nodeid; | | 1081 | s32p->op_nodeid = p->op_nodeid; |
1079 | s32p->op_namelen = p->op_namelen; | | 1082 | s32p->op_namelen = p->op_namelen; |
1080 | NETBSD32PTR32(s32p->op_name, p->op_name); | | 1083 | NETBSD32PTR32(s32p->op_name, p->op_name); |
1081 | s32p->op_buflen = p->op_buflen; | | 1084 | s32p->op_buflen = p->op_buflen; |
1082 | NETBSD32PTR32(s32p->op_buf, p->op_buf); | | 1085 | NETBSD32PTR32(s32p->op_buf, p->op_buf); |
1083 | } | | 1086 | } |
1084 | | | 1087 | |
1085 | int | | 1088 | int |
1086 | netbsd32_md_ioctl(struct file *fp, netbsd32_u_long cmd, void *data32, struct lwp *l) | | 1089 | netbsd32_md_ioctl(struct file *fp, netbsd32_u_long cmd, void *data32, struct lwp *l) |
1087 | { | | 1090 | { |
1088 | u_int size; | | 1091 | u_int size; |
1089 | void *data, *memp = NULL; | | 1092 | void *data, *memp = NULL; |
1090 | #define STK_PARAMS 128 | | 1093 | #define STK_PARAMS 128 |
1091 | u_long stkbuf[STK_PARAMS/sizeof(u_long)]; | | 1094 | u_long stkbuf[STK_PARAMS/sizeof(u_long)]; |
1092 | int error; | | 1095 | int error; |
1093 | | | 1096 | |
1094 | switch (cmd) { | | 1097 | switch (cmd) { |
1095 | case FBIOPUTCMAP32: | | 1098 | case FBIOPUTCMAP32: |
1096 | IOCTL_STRUCT_CONV_TO(FBIOPUTCMAP, fbcmap); | | 1099 | IOCTL_STRUCT_CONV_TO(FBIOPUTCMAP, fbcmap); |
1097 | case FBIOGETCMAP32: | | 1100 | case FBIOGETCMAP32: |
1098 | IOCTL_STRUCT_CONV_TO(FBIOGETCMAP, fbcmap); | | 1101 | IOCTL_STRUCT_CONV_TO(FBIOGETCMAP, fbcmap); |
1099 | | | 1102 | |
1100 | case FBIOSCURSOR32: | | 1103 | case FBIOSCURSOR32: |
1101 | IOCTL_STRUCT_CONV_TO(FBIOSCURSOR, fbcursor); | | 1104 | IOCTL_STRUCT_CONV_TO(FBIOSCURSOR, fbcursor); |
1102 | case FBIOGCURSOR32: | | 1105 | case FBIOGCURSOR32: |
1103 | IOCTL_STRUCT_CONV_TO(FBIOGCURSOR, fbcursor); | | 1106 | IOCTL_STRUCT_CONV_TO(FBIOGCURSOR, fbcursor); |
1104 | | | 1107 | |
1105 | case OPIOCGET32: | | 1108 | case OPIOCGET32: |
1106 | IOCTL_STRUCT_CONV_TO(OPIOCGET, opiocdesc); | | 1109 | IOCTL_STRUCT_CONV_TO(OPIOCGET, opiocdesc); |
1107 | case OPIOCSET32: | | 1110 | case OPIOCSET32: |
1108 | IOCTL_STRUCT_CONV_TO(OPIOCSET, opiocdesc); | | 1111 | IOCTL_STRUCT_CONV_TO(OPIOCSET, opiocdesc); |
1109 | case OPIOCNEXTPROP32: | | 1112 | case OPIOCNEXTPROP32: |
1110 | IOCTL_STRUCT_CONV_TO(OPIOCNEXTPROP, opiocdesc); | | 1113 | IOCTL_STRUCT_CONV_TO(OPIOCNEXTPROP, opiocdesc); |
1111 | default: | | 1114 | default: |
1112 | error = (*fp->f_ops->fo_ioctl)(fp, cmd, data32); | | 1115 | error = (*fp->f_ops->fo_ioctl)(fp, cmd, data32); |
1113 | } | | 1116 | } |
1114 | if (memp) | | 1117 | if (memp) |
1115 | kmem_free(memp, size); | | 1118 | kmem_free(memp, size); |
1116 | return (error); | | 1119 | return (error); |
1117 | } | | 1120 | } |
1118 | | | 1121 | |
1119 | | | 1122 | |
1120 | int | | 1123 | int |
1121 | netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) | | 1124 | netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) |
1122 | { | | 1125 | { |
1123 | /* { | | 1126 | /* { |
1124 | syscallarg(int) op; | | 1127 | syscallarg(int) op; |
1125 | syscallarg(netbsd32_voidp) parms; | | 1128 | syscallarg(netbsd32_voidp) parms; |
1126 | } */ | | 1129 | } */ |
1127 | | | 1130 | |
1128 | switch (SCARG(uap, op)) { | | 1131 | switch (SCARG(uap, op)) { |
1129 | default: | | 1132 | default: |
1130 | printf("(%s) netbsd32_sysarch(%d)\n", MACHINE, SCARG(uap, op)); | | 1133 | printf("(%s) netbsd32_sysarch(%d)\n", MACHINE, SCARG(uap, op)); |
1131 | return EINVAL; | | 1134 | return EINVAL; |
1132 | } | | 1135 | } |
1133 | } | | 1136 | } |
1134 | | | 1137 | |
1135 | int | | 1138 | int |
1136 | cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc) | | 1139 | cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc) |
1137 | { | | 1140 | { |
1138 | const __greg32_t *gr = mc->__gregs; | | 1141 | const __greg32_t *gr = mc->__gregs; |
1139 | | | 1142 | |
1140 | /* | | 1143 | /* |
1141 | * Only the icc bits in the psr are used, so it need not be | | 1144 | * Only the icc bits in the psr are used, so it need not be |
1142 | * verified. pc and npc must be multiples of 4. This is all | | 1145 | * verified. pc and npc must be multiples of 4. This is all |
1143 | * that is required; if it holds, just do it. | | 1146 | * that is required; if it holds, just do it. |
1144 | */ | | 1147 | */ |
1145 | if (((gr[_REG32_PC] | gr[_REG32_nPC]) & 3) != 0 || | | 1148 | if (((gr[_REG32_PC] | gr[_REG32_nPC]) & 3) != 0 || |
1146 | gr[_REG32_PC] == 0 || gr[_REG32_nPC] == 0) | | 1149 | gr[_REG32_PC] == 0 || gr[_REG32_nPC] == 0) |
1147 | return EINVAL; | | 1150 | return EINVAL; |
1148 | | | 1151 | |
1149 | return 0; | | 1152 | return 0; |
1150 | } | | 1153 | } |
1151 | | | 1154 | |
1152 | int | | 1155 | int |
1153 | cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) | | 1156 | cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) |
1154 | { | | 1157 | { |
1155 | struct trapframe *tf = l->l_md.md_tf; | | 1158 | struct trapframe *tf = l->l_md.md_tf; |
1156 | const __greg32_t *gr = mcp->__gregs; | | 1159 | const __greg32_t *gr = mcp->__gregs; |
1157 | struct proc *p = l->l_proc; | | 1160 | struct proc *p = l->l_proc; |
1158 | int error; | | 1161 | int error; |
1159 | | | 1162 | |
1160 | /* First ensure consistent stack state (see sendsig). */ | | 1163 | /* First ensure consistent stack state (see sendsig). */ |
1161 | write_user_windows(); | | 1164 | write_user_windows(); |
1162 | if (rwindow_save(l)) { | | 1165 | if (rwindow_save(l)) { |
1163 | mutex_enter(p->p_lock); | | 1166 | mutex_enter(p->p_lock); |
1164 | sigexit(l, SIGILL); | | 1167 | sigexit(l, SIGILL); |
1165 | } | | 1168 | } |
1166 | | | 1169 | |
1167 | /* Restore register context, if any. */ | | 1170 | /* Restore register context, if any. */ |
1168 | if ((flags & _UC_CPU) != 0) { | | 1171 | if ((flags & _UC_CPU) != 0) { |
1169 | error = cpu_mcontext32_validate(l, mcp); | | 1172 | error = cpu_mcontext32_validate(l, mcp); |
1170 | if (error) | | 1173 | if (error) |
1171 | return error; | | 1174 | return error; |
1172 | | | 1175 | |
1173 | /* Restore general register context. */ | | 1176 | /* Restore general register context. */ |
1174 | /* take only tstate CCR (and ASI) fields */ | | 1177 | /* take only tstate CCR (and ASI) fields */ |
1175 | tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | | | 1178 | tf->tf_tstate = (tf->tf_tstate & ~TSTATE_CCR) | |
1176 | PSRCC_TO_TSTATE(gr[_REG32_PSR]); | | 1179 | PSRCC_TO_TSTATE(gr[_REG32_PSR]); |
1177 | tf->tf_pc = (uint64_t)gr[_REG32_PC]; | | 1180 | tf->tf_pc = (uint64_t)gr[_REG32_PC]; |
1178 | tf->tf_npc = (uint64_t)gr[_REG32_nPC]; | | 1181 | tf->tf_npc = (uint64_t)gr[_REG32_nPC]; |
1179 | tf->tf_y = (uint64_t)gr[_REG32_Y]; | | 1182 | tf->tf_y = (uint64_t)gr[_REG32_Y]; |
1180 | tf->tf_global[1] = (uint64_t)gr[_REG32_G1]; | | 1183 | tf->tf_global[1] = (uint64_t)gr[_REG32_G1]; |
1181 | tf->tf_global[2] = (uint64_t)gr[_REG32_G2]; | | 1184 | tf->tf_global[2] = (uint64_t)gr[_REG32_G2]; |
1182 | tf->tf_global[3] = (uint64_t)gr[_REG32_G3]; | | 1185 | tf->tf_global[3] = (uint64_t)gr[_REG32_G3]; |
1183 | tf->tf_global[4] = (uint64_t)gr[_REG32_G4]; | | 1186 | tf->tf_global[4] = (uint64_t)gr[_REG32_G4]; |
1184 | tf->tf_global[5] = (uint64_t)gr[_REG32_G5]; | | 1187 | tf->tf_global[5] = (uint64_t)gr[_REG32_G5]; |
1185 | tf->tf_global[6] = (uint64_t)gr[_REG32_G6]; | | 1188 | tf->tf_global[6] = (uint64_t)gr[_REG32_G6]; |
1186 | /* done in lwp_setprivate */ | | 1189 | /* done in lwp_setprivate */ |
1187 | /* tf->tf_global[7] = (uint64_t)gr[_REG32_G7]; */ | | 1190 | /* tf->tf_global[7] = (uint64_t)gr[_REG32_G7]; */ |
1188 | tf->tf_out[0] = (uint64_t)gr[_REG32_O0]; | | 1191 | tf->tf_out[0] = (uint64_t)gr[_REG32_O0]; |
1189 | tf->tf_out[1] = (uint64_t)gr[_REG32_O1]; | | 1192 | tf->tf_out[1] = (uint64_t)gr[_REG32_O1]; |
1190 | tf->tf_out[2] = (uint64_t)gr[_REG32_O2]; | | 1193 | tf->tf_out[2] = (uint64_t)gr[_REG32_O2]; |
1191 | tf->tf_out[3] = (uint64_t)gr[_REG32_O3]; | | 1194 | tf->tf_out[3] = (uint64_t)gr[_REG32_O3]; |
1192 | tf->tf_out[4] = (uint64_t)gr[_REG32_O4]; | | 1195 | tf->tf_out[4] = (uint64_t)gr[_REG32_O4]; |
1193 | tf->tf_out[5] = (uint64_t)gr[_REG32_O5]; | | 1196 | tf->tf_out[5] = (uint64_t)gr[_REG32_O5]; |
1194 | tf->tf_out[6] = (uint64_t)gr[_REG32_O6]; | | 1197 | tf->tf_out[6] = (uint64_t)gr[_REG32_O6]; |
1195 | tf->tf_out[7] = (uint64_t)gr[_REG32_O7]; | | 1198 | tf->tf_out[7] = (uint64_t)gr[_REG32_O7]; |
1196 | /* %asi restored above; %fprs not yet supported. */ | | 1199 | /* %asi restored above; %fprs not yet supported. */ |
1197 | | | 1200 | |
1198 | if (flags & _UC_TLSBASE) | | 1201 | if (flags & _UC_TLSBASE) |
1199 | lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]); | | 1202 | lwp_setprivate(l, (void *)(uintptr_t)gr[_REG32_G7]); |
1200 | | | 1203 | |
1201 | /* XXX mcp->__gwins */ | | 1204 | /* XXX mcp->__gwins */ |
1202 | } | | 1205 | } |
1203 | | | 1206 | |
1204 | /* Restore floating point register context, if any. */ | | 1207 | /* Restore floating point register context, if any. */ |
1205 | if ((flags & _UC_FPU) != 0) { | | 1208 | if ((flags & _UC_FPU) != 0) { |
1206 | #ifdef notyet | | 1209 | #ifdef notyet |
1207 | struct fpstate64 *fsp; | | 1210 | struct fpstate64 *fsp; |
1208 | const __fpregset_t *fpr = &mcp->__fpregs; | | 1211 | const __fpregset_t *fpr = &mcp->__fpregs; |
1209 | | | 1212 | |
1210 | /* | | 1213 | /* |
1211 | * If we're the current FPU owner, simply reload it from | | 1214 | * If we're the current FPU owner, simply reload it from |
1212 | * the supplied context. Otherwise, store it into the | | 1215 | * the supplied context. Otherwise, store it into the |
1213 | * process' FPU save area (which is used to restore from | | 1216 | * process' FPU save area (which is used to restore from |
1214 | * by lazy FPU context switching); allocate it if necessary. | | 1217 | * by lazy FPU context switching); allocate it if necessary. |
1215 | */ | | 1218 | */ |
1216 | if ((fsp = l->l_md.md_fpstate) == NULL) { | | 1219 | if ((fsp = l->l_md.md_fpstate) == NULL) { |
1217 | fsp = pool_cache_get(fpstate_cache, PR_WAITOK); | | 1220 | fsp = pool_cache_get(fpstate_cache, PR_WAITOK); |
1218 | l->l_md.md_fpstate = fsp; | | 1221 | l->l_md.md_fpstate = fsp; |
1219 | } else { | | 1222 | } else { |
1220 | /* Drop the live context on the floor. */ | | 1223 | /* Drop the live context on the floor. */ |
1221 | fpusave_lwp(l, false); | | 1224 | fpusave_lwp(l, false); |
1222 | } | | 1225 | } |
1223 | /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ | | 1226 | /* Note: sizeof fpr->__fpu_fr <= sizeof fsp->fs_regs. */ |
1224 | memcpy(fsp->fs_regs, &fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); | | 1227 | memcpy(fsp->fs_regs, &fpr->__fpu_fr, sizeof (fpr->__fpu_fr)); |
1225 | fsp->fs_fsr = mcp->__fpregs.__fpu_fsr; | | 1228 | fsp->fs_fsr = mcp->__fpregs.__fpu_fsr; |
1226 | fsp->fs_qsize = 0; | | 1229 | fsp->fs_qsize = 0; |
1227 | | | 1230 | |
1228 | #if 0 | | 1231 | #if 0 |
1229 | /* Need more info! */ | | 1232 | /* Need more info! */ |
1230 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ | | 1233 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ |
1231 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ | | 1234 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ |
1232 | #endif | | 1235 | #endif |
1233 | #endif | | 1236 | #endif |
1234 | } | | 1237 | } |
1235 | #ifdef _UC_SETSTACK | | 1238 | #ifdef _UC_SETSTACK |
1236 | mutex_enter(p->p_lock); | | 1239 | mutex_enter(p->p_lock); |
1237 | if (flags & _UC_SETSTACK) | | 1240 | if (flags & _UC_SETSTACK) |
1238 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 1241 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
1239 | if (flags & _UC_CLRSTACK) | | 1242 | if (flags & _UC_CLRSTACK) |
1240 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | | 1243 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
1241 | mutex_exit(p->p_lock); | | 1244 | mutex_exit(p->p_lock); |
1242 | #endif | | 1245 | #endif |
1243 | return (0); | | 1246 | return (0); |
1244 | } | | 1247 | } |
1245 | | | 1248 | |
1246 | | | 1249 | |
1247 | void | | 1250 | void |
1248 | cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flags) | | 1251 | cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flags) |
1249 | { | | 1252 | { |
1250 | const struct trapframe *tf = l->l_md.md_tf; | | 1253 | const struct trapframe *tf = l->l_md.md_tf; |
1251 | __greg32_t *gr = mcp->__gregs; | | 1254 | __greg32_t *gr = mcp->__gregs; |
1252 | | | 1255 | |
1253 | /* First ensure consistent stack state (see sendsig). */ /* XXX? */ | | 1256 | /* First ensure consistent stack state (see sendsig). */ /* XXX? */ |
1254 | write_user_windows(); | | 1257 | write_user_windows(); |
1255 | if (rwindow_save(l)) { | | 1258 | if (rwindow_save(l)) { |
1256 | mutex_enter(l->l_proc->p_lock); | | 1259 | mutex_enter(l->l_proc->p_lock); |
1257 | sigexit(l, SIGILL); | | 1260 | sigexit(l, SIGILL); |
1258 | } | | 1261 | } |
1259 | | | 1262 | |
1260 | /* For now: Erase any random indicators for optional state. */ | | 1263 | /* For now: Erase any random indicators for optional state. */ |
1261 | (void)memset(mcp, '0', sizeof (*mcp)); | | 1264 | (void)memset(mcp, '0', sizeof (*mcp)); |
1262 | | | 1265 | |
1263 | /* Save general register context. */ | | 1266 | /* Save general register context. */ |
1264 | gr[_REG32_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); | | 1267 | gr[_REG32_PSR] = TSTATECCR_TO_PSR(tf->tf_tstate); |
1265 | gr[_REG32_PC] = tf->tf_pc; | | 1268 | gr[_REG32_PC] = tf->tf_pc; |
1266 | gr[_REG32_nPC] = tf->tf_npc; | | 1269 | gr[_REG32_nPC] = tf->tf_npc; |
1267 | gr[_REG32_Y] = tf->tf_y; | | 1270 | gr[_REG32_Y] = tf->tf_y; |
1268 | gr[_REG32_G1] = tf->tf_global[1]; | | 1271 | gr[_REG32_G1] = tf->tf_global[1]; |
1269 | gr[_REG32_G2] = tf->tf_global[2]; | | 1272 | gr[_REG32_G2] = tf->tf_global[2]; |
1270 | gr[_REG32_G3] = tf->tf_global[3]; | | 1273 | gr[_REG32_G3] = tf->tf_global[3]; |
1271 | gr[_REG32_G4] = tf->tf_global[4]; | | 1274 | gr[_REG32_G4] = tf->tf_global[4]; |
1272 | gr[_REG32_G5] = tf->tf_global[5]; | | 1275 | gr[_REG32_G5] = tf->tf_global[5]; |
1273 | gr[_REG32_G6] = tf->tf_global[6]; | | 1276 | gr[_REG32_G6] = tf->tf_global[6]; |
1274 | gr[_REG32_G7] = tf->tf_global[7]; | | 1277 | gr[_REG32_G7] = tf->tf_global[7]; |
1275 | gr[_REG32_O0] = tf->tf_out[0]; | | 1278 | gr[_REG32_O0] = tf->tf_out[0]; |
1276 | gr[_REG32_O1] = tf->tf_out[1]; | | 1279 | gr[_REG32_O1] = tf->tf_out[1]; |
1277 | gr[_REG32_O2] = tf->tf_out[2]; | | 1280 | gr[_REG32_O2] = tf->tf_out[2]; |
1278 | gr[_REG32_O3] = tf->tf_out[3]; | | 1281 | gr[_REG32_O3] = tf->tf_out[3]; |
1279 | gr[_REG32_O4] = tf->tf_out[4]; | | 1282 | gr[_REG32_O4] = tf->tf_out[4]; |
1280 | gr[_REG32_O5] = tf->tf_out[5]; | | 1283 | gr[_REG32_O5] = tf->tf_out[5]; |
1281 | gr[_REG32_O6] = tf->tf_out[6]; | | 1284 | gr[_REG32_O6] = tf->tf_out[6]; |
1282 | gr[_REG32_O7] = tf->tf_out[7]; | | 1285 | gr[_REG32_O7] = tf->tf_out[7]; |
1283 | *flags |= (_UC_CPU|_UC_TLSBASE); | | 1286 | *flags |= (_UC_CPU|_UC_TLSBASE); |
1284 | | | 1287 | |
1285 | mcp->__gwins = 0; | | 1288 | mcp->__gwins = 0; |
1286 | mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ | | 1289 | mcp->__xrs.__xrs_id = 0; /* Solaris extension? */ |
1287 | *flags |= (_UC_CPU|_UC_TLSBASE); | | 1290 | *flags |= (_UC_CPU|_UC_TLSBASE); |
1288 | | | 1291 | |
1289 | /* Save FP register context, if any. */ | | 1292 | /* Save FP register context, if any. */ |
1290 | if (l->l_md.md_fpstate != NULL) { | | 1293 | if (l->l_md.md_fpstate != NULL) { |
1291 | #ifdef notyet | | 1294 | #ifdef notyet |
1292 | struct fpstate64 *fsp; | | 1295 | struct fpstate64 *fsp; |
1293 | __fpregset_t *fpr = &mcp->__fpregs; | | 1296 | __fpregset_t *fpr = &mcp->__fpregs; |
1294 | | | 1297 | |
1295 | /* | | 1298 | /* |
1296 | * If our FP context is currently held in the FPU, take a | | 1299 | * If our FP context is currently held in the FPU, take a |
1297 | * private snapshot - lazy FPU context switching can deal | | 1300 | * private snapshot - lazy FPU context switching can deal |
1298 | * with it later when it becomes necessary. | | 1301 | * with it later when it becomes necessary. |
1299 | * Otherwise, get it from the process's save area. | | 1302 | * Otherwise, get it from the process's save area. |
1300 | */ | | 1303 | */ |
1301 | fpusave_lwp(l, true); | | 1304 | fpusave_lwp(l, true); |
1302 | fsp = l->l_md.md_fpstate; | | 1305 | fsp = l->l_md.md_fpstate; |
1303 | memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); | | 1306 | memcpy(&fpr->__fpu_fr, fsp->fs_regs, sizeof (fpr->__fpu_fr)); |
1304 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ | | 1307 | mcp->__fpregs.__fpu_q = NULL; /* `Need more info.' */ |
1305 | mcp->__fpregs.__fpu_fsr = fs.fs_fsr; | | 1308 | mcp->__fpregs.__fpu_fsr = fs.fs_fsr; |
1306 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ | | 1309 | mcp->__fpregs.__fpu_qcnt = 0 /*fs.fs_qsize*/; /* See above */ |
1307 | mcp->__fpregs.__fpu_q_entrysize = | | 1310 | mcp->__fpregs.__fpu_q_entrysize = |
1308 | (unsigned char) sizeof (*mcp->__fpregs.__fpu_q); | | 1311 | (unsigned char) sizeof (*mcp->__fpregs.__fpu_q); |
1309 | mcp->__fpregs.__fpu_en = 1; | | 1312 | mcp->__fpregs.__fpu_en = 1; |
1310 | *flags |= _UC_FPU; | | 1313 | *flags |= _UC_FPU; |
1311 | #endif | | 1314 | #endif |
1312 | } else { | | 1315 | } else { |
1313 | mcp->__fpregs.__fpu_en = 0; | | 1316 | mcp->__fpregs.__fpu_en = 0; |
1314 | } | | 1317 | } |
1315 | } | | 1318 | } |
1316 | | | 1319 | |
1317 | void | | 1320 | void |
1318 | startlwp32(void *arg) | | 1321 | startlwp32(void *arg) |
1319 | { | | 1322 | { |
1320 | ucontext32_t *uc = arg; | | 1323 | ucontext32_t *uc = arg; |
1321 | lwp_t *l = curlwp; | | 1324 | lwp_t *l = curlwp; |
1322 | int error __diagused; | | 1325 | int error __diagused; |
1323 | | | 1326 | |
1324 | error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); | | 1327 | error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); |
1325 | KASSERT(error == 0); | | 1328 | KASSERT(error == 0); |
1326 | | | 1329 | |
1327 | /* Note: we are freeing ucontext_t, not ucontext32_t. */ | | 1330 | /* Note: we are freeing ucontext_t, not ucontext32_t. */ |
1328 | kmem_free(arg, sizeof(ucontext_t)); | | 1331 | kmem_free(arg, sizeof(ucontext_t)); |
1329 | userret(l, 0, 0); | | 1332 | userret(l, 0, 0); |
1330 | } | | 1333 | } |
1331 | | | 1334 | |
1332 | vaddr_t | | 1335 | vaddr_t |
1333 | netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size) | | 1336 | netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size) |
1334 | { | | 1337 | { |
1335 | return round_page((vaddr_t)(base) + (vsize_t)MAXDSIZ32); | | 1338 | return round_page((vaddr_t)(base) + (vsize_t)MAXDSIZ32); |
1336 | } | | 1339 | } |