Tue Jan 17 19:46:55 2012 UTC ()
Clean up userret/ast handling. Now called ONLY when its 100% clear that it is
returning to userland.


(reinoud)
diff -r1.57 -r1.58 src/sys/arch/usermode/usermode/trap.c

cvs diff -r1.57 -r1.58 src/sys/arch/usermode/usermode/trap.c (switch to unified diff)

--- src/sys/arch/usermode/usermode/trap.c 2012/01/14 21:45:28 1.57
+++ src/sys/arch/usermode/usermode/trap.c 2012/01/17 19:46:55 1.58
@@ -1,480 +1,478 @@ @@ -1,480 +1,478 @@
1/* $NetBSD: trap.c,v 1.57 2012/01/14 21:45:28 reinoud Exp $ */ 1/* $NetBSD: trap.c,v 1.58 2012/01/17 19:46:55 reinoud Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 Reinoud Zandijk <reinoud@netbsd.org> 4 * Copyright (c) 2011 Reinoud Zandijk <reinoud@netbsd.org>
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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.57 2012/01/14 21:45:28 reinoud Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.58 2012/01/17 19:46:55 reinoud Exp $");
31 31
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/param.h> 33#include <sys/param.h>
34#include <sys/systm.h> 34#include <sys/systm.h>
35#include <sys/proc.h> 35#include <sys/proc.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/userret.h> 37#include <sys/userret.h>
38#include <sys/kauth.h> 38#include <sys/kauth.h>
39#include <sys/errno.h> 39#include <sys/errno.h>
40 40
41#include <uvm/uvm_extern.h> 41#include <uvm/uvm_extern.h>
42#include <machine/cpu.h> 42#include <machine/cpu.h>
43#include <machine/pcb.h> 43#include <machine/pcb.h>
44#include <machine/pmap.h> 44#include <machine/pmap.h>
45#include <machine/machdep.h> 45#include <machine/machdep.h>
46#include <machine/intr.h> 46#include <machine/intr.h>
47#include <machine/thunk.h> 47#include <machine/thunk.h>
48 48
49 49
50/* forwards and externals */ 50/* forwards and externals */
51void setup_signal_handlers(void); 51void setup_signal_handlers(void);
52void stop_all_signal_handlers(void); 52void stop_all_signal_handlers(void);
53void userret(struct lwp *l); 
54 53
55static void mem_access_handler(int sig, siginfo_t *info, void *ctx); 54static void mem_access_handler(int sig, siginfo_t *info, void *ctx);
56static void illegal_instruction_handler(int sig, siginfo_t *info, void *ctx); 55static void illegal_instruction_handler(int sig, siginfo_t *info, void *ctx);
57extern int errno; 56extern int errno;
58 57
59static void pagefault(vaddr_t pc, vaddr_t va); 58static void pagefault(vaddr_t from_userland, vaddr_t pc, vaddr_t va);
60static void illegal_instruction(void); 59static void illegal_instruction(vaddr_t from_userland);
61 60
62bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype); 61bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype);
63 62
64static stack_t sigstk; 63static stack_t sigstk;
65 64
66int astpending; 65int astpending;
67 66
68void 67void
69startlwp(void *arg) 68startlwp(void *arg)
70{ 69{
71 /* nothing here */ 70 /* nothing here */
72} 71}
73 72
74 73
75void 74void
76setup_signal_handlers(void) 75setup_signal_handlers(void)
77{ 76{
78 static struct sigaction sa; 77 static struct sigaction sa;
79 78
80 if ((sigstk.ss_sp = thunk_malloc(SIGSTKSZ)) == NULL) 79 if ((sigstk.ss_sp = thunk_malloc(SIGSTKSZ)) == NULL)
81 panic("can't allocate signal stack space\n"); 80 panic("can't allocate signal stack space\n");
82 sigstk.ss_size = SIGSTKSZ; 81 sigstk.ss_size = SIGSTKSZ;
83 sigstk.ss_flags = 0; 82 sigstk.ss_flags = 0;
84 if (thunk_sigaltstack(&sigstk, 0) < 0) 83 if (thunk_sigaltstack(&sigstk, 0) < 0)
85 panic("can't set alternate stacksize: %d", 84 panic("can't set alternate stacksize: %d",
86 thunk_geterrno()); 85 thunk_geterrno());
87 86
88 /* SIGBUS and SIGSEGV need to be reentrant hence the SA_NODEFER */ 87 /* SIGBUS and SIGSEGV need to be reentrant hence the SA_NODEFER */
89 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK | SA_NODEFER; 88 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK | SA_NODEFER;
90 sa.sa_sigaction = mem_access_handler; 89 sa.sa_sigaction = mem_access_handler;
91 thunk_sigemptyset(&sa.sa_mask); 90 thunk_sigemptyset(&sa.sa_mask);
92 if (thunk_sigaction(SIGSEGV, &sa, NULL) == -1) 91 if (thunk_sigaction(SIGSEGV, &sa, NULL) == -1)
93 panic("couldn't register SIGSEGV handler: %d", 92 panic("couldn't register SIGSEGV handler: %d",
94 thunk_geterrno()); 93 thunk_geterrno());
95 if (thunk_sigaction(SIGBUS, &sa, NULL) == -1) 94 if (thunk_sigaction(SIGBUS, &sa, NULL) == -1)
96 panic("couldn't register SIGBUS handler: %d", thunk_geterrno()); 95 panic("couldn't register SIGBUS handler: %d", thunk_geterrno());
97 96
98 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 97 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
99 sa.sa_sigaction = illegal_instruction_handler; 98 sa.sa_sigaction = illegal_instruction_handler;
100 thunk_sigemptyset(&sa.sa_mask); 99 thunk_sigemptyset(&sa.sa_mask);
101 if (thunk_sigaction(SIGILL, &sa, NULL) == -1) 100 if (thunk_sigaction(SIGILL, &sa, NULL) == -1)
102 panic("couldn't register SIGILL handler: %d", thunk_geterrno()); 101 panic("couldn't register SIGILL handler: %d", thunk_geterrno());
103 102
104 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 103 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
105 sa.sa_sigaction = sigio_signal_handler; 104 sa.sa_sigaction = sigio_signal_handler;
106 thunk_sigemptyset(&sa.sa_mask); 105 thunk_sigemptyset(&sa.sa_mask);
107 if (thunk_sigaction(SIGIO, &sa, NULL) == -1) 106 if (thunk_sigaction(SIGIO, &sa, NULL) == -1)
108 panic("couldn't register SIGIO handler: %d", thunk_geterrno()); 107 panic("couldn't register SIGIO handler: %d", thunk_geterrno());
109} 108}
110 109
111 110
112void 111void
113stop_all_signal_handlers(void) 112stop_all_signal_handlers(void)
114{ 113{
115 thunk_sigblock(SIGALRM); 114 thunk_sigblock(SIGALRM);
116 thunk_sigblock(SIGIO); 115 thunk_sigblock(SIGIO);
117 thunk_sigblock(SIGILL); 116 thunk_sigblock(SIGILL);
118 thunk_sigblock(SIGSEGV); 117 thunk_sigblock(SIGSEGV);
119 thunk_sigblock(SIGBUS); 118 thunk_sigblock(SIGBUS);
120} 119}
121 120
122 121
 122/* ast and userret */
 123void
 124userret(struct lwp *l)
 125{
 126 /* invoke MI userret code */
 127 mi_userret(l);
 128
 129 while (astpending) {
 130 astpending = 0;
 131
 132 curcpu()->ci_data.cpu_ntrap++;
 133#if 0
 134 /* profiling */
 135 if (l->l_pflag & LP_OWEUPC) {
 136 l->l_pflag &= ~LP_OWEUPC;
 137 ADDUPROF(l);
 138 }
 139#endif
 140 /* allow a forced task switch */
 141 if (l->l_cpu->ci_want_resched)
 142 preempt();
 143
 144 mi_userret(l);
 145 }
 146}
 147
 148
123/* signal handler switching to a pagefault context */ 149/* signal handler switching to a pagefault context */
124static void 150static void
125mem_access_handler(int sig, siginfo_t *info, void *ctx) 151mem_access_handler(int sig, siginfo_t *info, void *ctx)
126{ 152{
127 ucontext_t *ucp = ctx; 153 ucontext_t *ucp = ctx;
128 struct lwp *l; 154 struct lwp *l;
129 struct pcb *pcb; 155 struct pcb *pcb;
130 vaddr_t va, sp, pc, fp; 156 vaddr_t va, sp, pc, fp;
 157 int from_userland;
131 158
132 assert((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS)); 159 assert((info->si_signo == SIGSEGV) || (info->si_signo == SIGBUS));
133 160
134 if (info->si_code == SI_NOINFO) 161 if (info->si_code == SI_NOINFO)
135 panic("received signal %d with no info", 162 panic("received signal %d with no info",
136 info->si_signo); 163 info->si_signo);
137 164
138#if 0 165#if 0
139 thunk_printf_debug("SIGSEGV or SIGBUS!\n"); 166 thunk_printf_debug("SIGSEGV or SIGBUS!\n");
140 thunk_printf_debug("\tsi_signo = %d\n", info->si_signo); 167 thunk_printf_debug("\tsi_signo = %d\n", info->si_signo);
141 thunk_printf_debug("\tsi_errno = %d\n", info->si_errno); 168 thunk_printf_debug("\tsi_errno = %d\n", info->si_errno);
142 thunk_printf_debug("\tsi_code = %d\n", info->si_code); 169 thunk_printf_debug("\tsi_code = %d\n", info->si_code);
143 if (info->si_code == SEGV_MAPERR) 170 if (info->si_code == SEGV_MAPERR)
144 thunk_printf_debug("\t\tSEGV_MAPERR\n"); 171 thunk_printf_debug("\t\tSEGV_MAPERR\n");
145 if (info->si_code == SEGV_ACCERR) 172 if (info->si_code == SEGV_ACCERR)
146 thunk_printf_debug("\t\tSEGV_ACCERR\n"); 173 thunk_printf_debug("\t\tSEGV_ACCERR\n");
147 if (info->si_code == BUS_ADRALN) 174 if (info->si_code == BUS_ADRALN)
148 thunk_printf_debug("\t\tBUS_ADRALN\n"); 175 thunk_printf_debug("\t\tBUS_ADRALN\n");
149 if (info->si_code == BUS_ADRERR) 176 if (info->si_code == BUS_ADRERR)
150 thunk_printf_debug("\t\tBUS_ADRERR\n"); 177 thunk_printf_debug("\t\tBUS_ADRERR\n");
151 if (info->si_code == BUS_OBJERR) 178 if (info->si_code == BUS_OBJERR)
152 thunk_printf_debug("\t\tBUS_OBJERR\n"); 179 thunk_printf_debug("\t\tBUS_OBJERR\n");
153 thunk_printf_debug("\tsi_addr = %p\n", info->si_addr); 180 thunk_printf_debug("\tsi_addr = %p\n", info->si_addr);
154 thunk_printf_debug("\tsi_trap = %d\n", info->si_trap); 181 thunk_printf_debug("\tsi_trap = %d\n", info->si_trap);
155#endif 182#endif
156 183
157 l = curlwp; 184 l = curlwp;
158 pcb = lwp_getpcb(l); 185 pcb = lwp_getpcb(l);
159 186
160 /* get address of faulted memory access and make it page aligned */ 187 /* get address of faulted memory access and make it page aligned */
161 va = (vaddr_t) info->si_addr; 188 va = (vaddr_t) info->si_addr;
162 va = trunc_page(va); 189 va = trunc_page(va);
163 190
164 /* get PC address of faulted memory instruction */ 191 /* get PC address of faulted memory instruction */
165 pc = md_get_pc(ctx); 192 pc = md_get_pc(ctx);
166 193
167 /* setup for pagefault context */ 194 /* setup for pagefault context */
168 sp = md_get_sp(ctx); 195 sp = md_get_sp(ctx);
169 196
170#if 0 197#if 0
171 printf("memaccess error, pc %p, va %p, " 198 printf("memaccess error, pc %p, va %p, "
172 "sys_stack %p, sp %p, stack top %p\n", 199 "sys_stack %p, sp %p, stack top %p\n",
173 (void *) pc, (void *) va, 200 (void *) pc, (void *) va,
174 (void *) pcb->sys_stack, (void *) sp, 201 (void *) pcb->sys_stack, (void *) sp,
175 (void *) pcb->sys_stack_top); 202 (void *) pcb->sys_stack_top);
176#endif 203#endif
177 204
178 /* if we're running on a stack of our own, use the system stack */ 205 /* if we're running on a stack of our own, use the system stack */
 206 from_userland = 0;
179 if ((sp < (vaddr_t) pcb->sys_stack) || (sp > (vaddr_t) pcb->sys_stack_top)) { 207 if ((sp < (vaddr_t) pcb->sys_stack) || (sp > (vaddr_t) pcb->sys_stack_top)) {
180 sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t); 208 sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t);
181 fp = (vaddr_t) &pcb->pcb_userret_ucp; 209 fp = (vaddr_t) &pcb->pcb_userret_ucp;
 210 if (pc < kmem_user_end)
 211 from_userland = 1;
182 } else { 212 } else {
183 /* stack grows down */ 213 /* stack grows down */
184 fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */ 214 fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */
185 sp = fp - sizeof(register_t); /* slack */ 215 sp = fp - sizeof(register_t); /* slack */
186 216
187 /* sanity check before copying */ 217 /* sanity check before copying */
188 if (fp - 2*PAGE_SIZE < (vaddr_t) pcb->sys_stack) 218 if (fp - 2*PAGE_SIZE < (vaddr_t) pcb->sys_stack)
189 panic("%s: out of system stack", __func__); 219 panic("%s: out of system stack", __func__);
190 } 220 }
191 221
192 memcpy((void *) fp, ucp, sizeof(ucontext_t)); 222 memcpy((void *) fp, ucp, sizeof(ucontext_t));
193 223
194 /* create context for pagefault */ 224 /* create context for pagefault */
195 pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack; 225 pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack;
196 pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack; 226 pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack;
197 pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */ 227 pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */
198 228
199 pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU; 229 pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
200 thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) pagefault, 230 thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) pagefault,
201 2, (void *) pc, (void *) va, NULL); 231 3, (void *) from_userland, (void *) pc, (void *) va);
202 232
203 /* switch to the new pagefault entry on return from signal */ 233 /* switch to the new pagefault entry on return from signal */
204 memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t)); 234 memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t));
205} 235}
206 236
207 237
208/* ast and userret */ 
209void 
210userret(struct lwp *l) 
211{ 
212 struct pcb *pcb; 
213 ucontext_t ucp, *nucp; 
214 vaddr_t pc; 
215  
216 KASSERT(l); 
217 
218 /* are we going back to userland? */ 
219 pcb = lwp_getpcb(l); 
220 KASSERT(pcb); 
221 
222 /* where are we going back to ? */ 
223 thunk_getcontext(&ucp); 
224 nucp = (ucontext_t *) ucp.uc_link; 
225 pc = md_get_pc(nucp); 
226 
227 if (pc >= kmem_k_start) 
228 return; 
229 
230 /* ok, going to userland, proceed! */ 
231 if (astpending) { 
232 astpending = 0; 
233 
234 curcpu()->ci_data.cpu_ntrap++; 
235#if 0 
236 /* profiling */ 
237 if (l->l_pflag & LP_OWEUPC) { 
238 l->l_pflag &= ~LP_OWEUPC; 
239 ADDUPROF(l); 
240 } 
241#endif 
242 /* allow a forced task switch */ 
243 if (l->l_cpu->ci_want_resched) 
244 preempt(); 
245 } 
246 
247 /* invoke MI userret code */ 
248 mi_userret(l); 
249} 
250 
251/* signal handler switching to a illegal instruction context */ 238/* signal handler switching to a illegal instruction context */
252static void 239static void
253illegal_instruction_handler(int sig, siginfo_t *info, void *ctx) 240illegal_instruction_handler(int sig, siginfo_t *info, void *ctx)
254{ 241{
255 ucontext_t *ucp = ctx; 242 ucontext_t *ucp = ctx;
256 struct lwp *l; 243 struct lwp *l;
257 struct pcb *pcb; 244 struct pcb *pcb;
258 vaddr_t sp, fp; 245 vaddr_t sp, pc, fp;
 246 int from_userland;
259 247
260 assert(info->si_signo == SIGILL); 248 assert(info->si_signo == SIGILL);
261#if 0 249#if 0
262 thunk_printf("SIGILL!\n"); 250 thunk_printf("SIGILL!\n");
263 thunk_printf("\tsi_signo = %d\n", info->si_signo); 251 thunk_printf("\tsi_signo = %d\n", info->si_signo);
264 thunk_printf("\tsi_errno = %d\n", info->si_errno); 252 thunk_printf("\tsi_errno = %d\n", info->si_errno);
265 thunk_printf("\tsi_code = %d\n", info->si_code); 253 thunk_printf("\tsi_code = %d\n", info->si_code);
266 if (info->si_code == ILL_ILLOPC) 254 if (info->si_code == ILL_ILLOPC)
267 thunk_printf("\t\tIllegal opcode"); 255 thunk_printf("\t\tIllegal opcode");
268 if (info->si_code == ILL_ILLOPN) 256 if (info->si_code == ILL_ILLOPN)
269 thunk_printf("\t\tIllegal operand"); 257 thunk_printf("\t\tIllegal operand");
270 if (info->si_code == ILL_ILLADR) 258 if (info->si_code == ILL_ILLADR)
271 thunk_printf("\t\tIllegal addressing mode"); 259 thunk_printf("\t\tIllegal addressing mode");
272 if (info->si_code == ILL_ILLTRP) 260 if (info->si_code == ILL_ILLTRP)
273 thunk_printf("\t\tIllegal trap"); 261 thunk_printf("\t\tIllegal trap");
274 if (info->si_code == ILL_PRVOPC) 262 if (info->si_code == ILL_PRVOPC)
275 thunk_printf("\t\tPrivileged opcode"); 263 thunk_printf("\t\tPrivileged opcode");
276 if (info->si_code == ILL_PRVREG) 264 if (info->si_code == ILL_PRVREG)
277 thunk_printf("\t\tPrivileged register"); 265 thunk_printf("\t\tPrivileged register");
278 if (info->si_code == ILL_COPROC) 266 if (info->si_code == ILL_COPROC)
279 thunk_printf("\t\tCoprocessor error"); 267 thunk_printf("\t\tCoprocessor error");
280 if (info->si_code == ILL_BADSTK) 268 if (info->si_code == ILL_BADSTK)
281 thunk_printf("\t\tInternal stack error"); 269 thunk_printf("\t\tInternal stack error");
282 thunk_printf("\tsi_addr = %p\n", info->si_addr); 270 thunk_printf("\tsi_addr = %p\n", info->si_addr);
283 thunk_printf("\tsi_trap = %d\n", info->si_trap); 271 thunk_printf("\tsi_trap = %d\n", info->si_trap);
284 272
285 thunk_printf("%p : ", info->si_addr); 273 thunk_printf("%p : ", info->si_addr);
286 for (int i = 0; i < 10; i++) 274 for (int i = 0; i < 10; i++)
287 thunk_printf("%02x ", *((uint8_t *) info->si_addr + i)); 275 thunk_printf("%02x ", *((uint8_t *) info->si_addr + i));
288 thunk_printf("\n"); 276 thunk_printf("\n");
289#endif 277#endif
290 278
291 l = curlwp; 279 l = curlwp;
292 pcb = lwp_getpcb(l); 280 pcb = lwp_getpcb(l);
293 281
 282 /* get PC address of faulted instruction */
 283 pc = md_get_pc(ctx);
 284
294 /* setup for illegal_instruction context */ 285 /* setup for illegal_instruction context */
295 sp = md_get_sp(ctx); 286 sp = md_get_sp(ctx);
296 287
297 /* if we're running on a stack of our own, use the system stack */ 288 /* if we're running on a stack of our own, use the system stack */
 289 from_userland = 0;
298 if ((sp < (vaddr_t) pcb->sys_stack) || 290 if ((sp < (vaddr_t) pcb->sys_stack) ||
299 (sp > (vaddr_t) pcb->sys_stack_top)) { 291 (sp > (vaddr_t) pcb->sys_stack_top)) {
300 sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t); 292 sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t);
301 fp = (vaddr_t) &pcb->pcb_userret_ucp; 293 fp = (vaddr_t) &pcb->pcb_userret_ucp;
 294
 295 KASSERT(pc < kmem_user_end);
 296 from_userland = 1;
302 } else { 297 } else {
303 panic("illegal instruction inside kernel?"); 298 panic("illegal instruction inside kernel?");
304#if 0 299#if 0
305 /* stack grows down */ 300 /* stack grows down */
306 fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */ 301 fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */
307 sp = fp - sizeof(register_t); /* slack */ 302 sp = fp - sizeof(register_t); /* slack */
308 303
309 /* sanity check before copying */ 304 /* sanity check before copying */
310 if (fp - 2*PAGE_SIZE < (vaddr_t) pcb->sys_stack) 305 if (fp - 2*PAGE_SIZE < (vaddr_t) pcb->sys_stack)
311 panic("%s: out of system stack", __func__); 306 panic("%s: out of system stack", __func__);
312#endif 307#endif
313 } 308 }
314 309
315 memcpy((void *) fp, ucp, sizeof(ucontext_t)); 310 memcpy((void *) fp, ucp, sizeof(ucontext_t));
316 311
317 /* create context for illegal instruction */ 312 /* create context for illegal instruction */
318 pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack; 313 pcb->pcb_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack;
319 pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack; 314 pcb->pcb_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack;
320 pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */ 315 pcb->pcb_ucp.uc_link = (void *) fp; /* link to old frame on stack */
321 316
322 pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU; 317 pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
323 thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) illegal_instruction, 318 thunk_makecontext(&pcb->pcb_ucp, (void (*)(void)) illegal_instruction,
324 0, NULL, NULL, NULL); 319 1, (void *) from_userland, NULL, NULL);
325 320
326 /* switch to the new illegal instruction entry on return from signal */ 321 /* switch to the new illegal instruction entry on return from signal */
327 memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t)); 322 memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t));
328} 323}
329 324
330 325
331/* 326/*
332 * Context for handing page faults from the sigsegv handler; check if its a 327 * Context for handing page faults from the sigsegv handler; check if its a
333 * pmap reference fault or let uvm handle it. 328 * pmap reference fault or let uvm handle it.
334 */ 329 */
335static void 330static void
336pagefault(vaddr_t pc, vaddr_t va) 331pagefault(vaddr_t from_userland, vaddr_t pc, vaddr_t va)
337{ 332{
338 struct proc *p; 333 struct proc *p;
339 struct lwp *l; 334 struct lwp *l;
340 struct pcb *pcb; 335 struct pcb *pcb;
341 struct vmspace *vm; 336 struct vmspace *vm;
342 struct vm_map *vm_map; 337 struct vm_map *vm_map;
343 vm_prot_t atype; 338 vm_prot_t atype;
344 void *onfault; 339 void *onfault;
345 int from_kernel, lwp_errno, error; 340 int from_kernel, lwp_errno, error;
346 ksiginfo_t ksi; 341 ksiginfo_t ksi;
347 342
348 l = curlwp; KASSERT(l); 343 l = curlwp; KASSERT(l);
349 pcb = lwp_getpcb(l); 344 pcb = lwp_getpcb(l);
350 p = l->l_proc; 345 p = l->l_proc;
351 vm = p->p_vmspace; 346 vm = p->p_vmspace;
352 347
353 lwp_errno = thunk_geterrno(); 348 lwp_errno = thunk_geterrno();
354 349
355 vm_map = &vm->vm_map; 350 vm_map = &vm->vm_map;
356 from_kernel = (pc >= kmem_k_start); 351 from_kernel = (pc >= kmem_k_start);
357 if (from_kernel && (va >= VM_MIN_KERNEL_ADDRESS)) 352 if (from_kernel && (va >= VM_MIN_KERNEL_ADDRESS))
358 vm_map = kernel_map; 353 vm_map = kernel_map;
359 354
360#if 0 355#if 0
361 thunk_printf("pagefault : pc %p, va %p\n", 356 thunk_printf("pagefault : pc %p, va %p\n",
362 (void *) pc, (void *) va); 357 (void *) pc, (void *) va);
363#endif 358#endif
364 359
365 /* can pmap handle it? on its own? (r/m) emulation */ 360 /* can pmap handle it? on its own? (r/m) emulation */
366 if (pmap_fault(vm_map->pmap, va, &atype)) { 361 if (pmap_fault(vm_map->pmap, va, &atype)) {
367// thunk_printf("pagefault leave (pmap)\n"); 362// thunk_printf("pagefault leave (pmap)\n");
368 /* no use doing anything else here */ 363 /* no use doing anything else here */
369 goto out_quick; 364 goto out_quick;
370 } 365 }
371 366
372 /* ask UVM */ 367 /* ask UVM */
373 thunk_printf_debug("pmap fault couldn't handle it! : " 368 thunk_printf_debug("pmap fault couldn't handle it! : "
374 "derived atype %d\n", atype); 369 "derived atype %d\n", atype);
375 370
376 onfault = pcb->pcb_onfault; 371 onfault = pcb->pcb_onfault;
377 pcb->pcb_onfault = NULL; 372 pcb->pcb_onfault = NULL;
378 error = uvm_fault(vm_map, va, atype); 373 error = uvm_fault(vm_map, va, atype);
379 pcb->pcb_onfault = onfault; 374 pcb->pcb_onfault = onfault;
380 375
381 if (vm_map != kernel_map) { 376 if (vm_map != kernel_map) {
382 if (error == 0) 377 if (error == 0)
383 uvm_grow(l->l_proc, va); 378 uvm_grow(l->l_proc, va);
384 } 379 }
385 if (error == EACCES) 380 if (error == EACCES)
386 error = EFAULT; 381 error = EFAULT;
387 382
388 /* if uvm handled it, return */ 383 /* if uvm handled it, return */
389 if (error == 0) { 384 if (error == 0) {
390// thunk_printf("pagefault leave (uvm)\n"); 385// thunk_printf("pagefault leave (uvm)\n");
391 goto out; 386 goto out;
392 } 387 }
393 388
394 /* something got wrong */ 389 /* something got wrong */
395 thunk_printf("%s: uvm fault %d, pc %p, from_kernel %d\n", 390 thunk_printf("%s: uvm fault %d, pc %p, from_kernel %d\n",
396 __func__, error, (void *) pc, from_kernel); 391 __func__, error, (void *) pc, from_kernel);
397 392
398 /* check if its from copyin/copyout */ 393 /* check if its from copyin/copyout */
399 if (onfault) { 394 if (onfault) {
400 panic("%s: can't call onfault yet\n", __func__); 395 panic("%s: can't call onfault yet\n", __func__);
401 /* XXX implement me ? */ 396 /* XXX implement me ? */
402 /* jump to given onfault */ 397 /* jump to given onfault */
403 // tf = &kernel_tf; 398 // tf = &kernel_tf;
404 // memset(tf, 0, sizeof(struct trapframe)); 399 // memset(tf, 0, sizeof(struct trapframe));
405 // tf->tf_pc = onfault; 400 // tf->tf_pc = onfault;
406 // tf->tf_io[0] = (rv == EACCES) ? EFAULT : rv; 401 // tf->tf_io[0] = (rv == EACCES) ? EFAULT : rv;
407 goto out; 402 goto out;
408 } 403 }
409 404
410 if (from_kernel) 405 if (from_kernel)
411 panic("Unhandled page fault in kernel mode"); 406 panic("Unhandled page fault in kernel mode");
412 407
413 /* send signal */ 408 /* send signal */
414 thunk_printf("giving signal to userland\n"); 409 thunk_printf("giving signal to userland\n");
415 410
416 KSI_INIT_TRAP(&ksi); 411 KSI_INIT_TRAP(&ksi);
417 ksi.ksi_signo = SIGSEGV; 412 ksi.ksi_signo = SIGSEGV;
418 ksi.ksi_trap = 0; /* XXX */ 413 ksi.ksi_trap = 0; /* XXX */
419 ksi.ksi_code = (error == EPERM) ? SEGV_ACCERR : SEGV_MAPERR; 414 ksi.ksi_code = (error == EPERM) ? SEGV_ACCERR : SEGV_MAPERR;
420 ksi.ksi_addr = (void *) va; 415 ksi.ksi_addr = (void *) va;
421 416
422 if (error == ENOMEM) { 417 if (error == ENOMEM) {
423 printf("UVM: pid %d.%d (%s), uid %d killed: " 418 printf("UVM: pid %d.%d (%s), uid %d killed: "
424 "out of swap\n", 419 "out of swap\n",
425 p->p_pid, l->l_lid, p->p_comm, 420 p->p_pid, l->l_lid, p->p_comm,
426 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 421 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1);
427 ksi.ksi_signo = SIGKILL; 422 ksi.ksi_signo = SIGKILL;
428 } 423 }
429 424
430#if 0 425#if 0
431 p->p_emul->e_trapsignal(l, &ksi); 426 p->p_emul->e_trapsignal(l, &ksi);
432#else 427#else
433 trapsignal(l, &ksi); 428 trapsignal(l, &ksi);
434#endif 429#endif
435 430
436// thunk_printf("pagefault leave\n"); 431// thunk_printf("pagefault leave\n");
437out: 432out:
438 userret(l); 433 if (from_userland)
 434 userret(l);
439out_quick: 435out_quick:
440 thunk_seterrno(lwp_errno); 436 thunk_seterrno(lwp_errno);
441 pcb->pcb_errno = lwp_errno; 437 pcb->pcb_errno = lwp_errno;
442} 438}
443 439
444/* 440/*
445 * Context for handing illegal instruction from the sigill handler 441 * Context for handing illegal instruction from the sigill handler
446 */ 442 */
447static void 443static void
448illegal_instruction(void) 444illegal_instruction(vaddr_t from_userland)
449{ 445{
450 struct lwp *l = curlwp; 446 struct lwp *l = curlwp;
451 struct pcb *pcb = lwp_getpcb(l); 447 struct pcb *pcb = lwp_getpcb(l);
452 ucontext_t *ucp = &pcb->pcb_userret_ucp; 448 ucontext_t *ucp = &pcb->pcb_userret_ucp;
453 ksiginfo_t ksi; 449 ksiginfo_t ksi;
454 450
455// thunk_printf("illegal instruction\n"); 451// thunk_printf("illegal instruction\n");
456 /* if its a syscall ... */ 452 /* if its a syscall ... */
457 if (md_syscall_check_opcode(ucp)) { 453 if (md_syscall_check_opcode(ucp)) {
458 syscall(); 454 syscall();
459// thunk_printf("illegal instruction leave\n"); 455// thunk_printf("illegal instruction leave\n");
 456 KASSERT(from_userland);
460 userret(l); 457 userret(l);
461 return; 458 return;
462 } 459 }
463 460
464 thunk_printf("%s: giving SIGILL (TRAP)\n", __func__); 461 thunk_printf("%s: giving SIGILL (TRAP)\n", __func__);
465 462
466 KSI_INIT_TRAP(&ksi); 463 KSI_INIT_TRAP(&ksi);
467 ksi.ksi_signo = SIGILL; 464 ksi.ksi_signo = SIGILL;
468 ksi.ksi_trap = 0; /* XXX */ 465 ksi.ksi_trap = 0; /* XXX */
469 ksi.ksi_errno = 0; // info->si_errno; 466 ksi.ksi_errno = 0; // info->si_errno;
470 ksi.ksi_code = 0; // info->si_code; 467 ksi.ksi_code = 0; // info->si_code;
471 ksi.ksi_addr = (void *) md_get_pc(ucp); /* only relyable source */ 468 ksi.ksi_addr = (void *) md_get_pc(ucp); /* only relyable source */
472 469
473#if 0 470#if 0
474 p->p_emul->e_trapsignal(l, &ksi); 471 p->p_emul->e_trapsignal(l, &ksi);
475#else 472#else
476 trapsignal(l, &ksi); 473 trapsignal(l, &ksi);
477#endif 474#endif
 475 KASSERT(from_userland);
478 userret(l); 476 userret(l);
479} 477}
480 478