Wed Jan 18 19:17:02 2012 UTC ()
Create an atomic switchto() that has SIGALRM and SIGIO signals blocked that
might otherwise disrupt the setting of curlwp to match the lwp context.


(reinoud)
diff -r1.67 -r1.68 src/sys/arch/usermode/dev/cpu.c

cvs diff -r1.67 -r1.68 src/sys/arch/usermode/dev/cpu.c (expand / switch to unified diff)

--- src/sys/arch/usermode/dev/cpu.c 2012/01/15 10:45:03 1.67
+++ src/sys/arch/usermode/dev/cpu.c 2012/01/18 19:17:02 1.68
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: cpu.c,v 1.67 2012/01/15 10:45:03 jmcneill Exp $ */ 1/* $NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
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.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
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 "opt_cpu.h" 29#include "opt_cpu.h"
30#include "opt_hz.h" 30#include "opt_hz.h"
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.67 2012/01/15 10:45:03 jmcneill Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.68 2012/01/18 19:17:02 reinoud Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/conf.h> 36#include <sys/conf.h>
37#include <sys/proc.h> 37#include <sys/proc.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/device.h> 39#include <sys/device.h>
40#include <sys/reboot.h> 40#include <sys/reboot.h>
41#include <sys/lwp.h> 41#include <sys/lwp.h>
42#include <sys/cpu.h> 42#include <sys/cpu.h>
43#include <sys/mbuf.h> 43#include <sys/mbuf.h>
44#include <sys/msgbuf.h> 44#include <sys/msgbuf.h>
45#include <sys/kmem.h> 45#include <sys/kmem.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
@@ -68,26 +68,29 @@ static void cpu_attach(device_t, device_ @@ -68,26 +68,29 @@ static void cpu_attach(device_t, device_
68 68
69struct cpu_info cpu_info_primary = { 69struct cpu_info cpu_info_primary = {
70 .ci_dev = 0, 70 .ci_dev = 0,
71 .ci_self = &cpu_info_primary, 71 .ci_self = &cpu_info_primary,
72 .ci_idepth = -1, 72 .ci_idepth = -1,
73 .ci_curlwp = &lwp0, 73 .ci_curlwp = &lwp0,
74}; 74};
75 75
76char cpu_model[48] = "virtual processor"; 76char cpu_model[48] = "virtual processor";
77 77
78typedef struct cpu_softc { 78typedef struct cpu_softc {
79 device_t sc_dev; 79 device_t sc_dev;
80 struct cpu_info *sc_ci; 80 struct cpu_info *sc_ci;
 81
 82 ucontext_t sc_ucp;
 83 uint8_t sc_ucp_stack[PAGE_SIZE];
81} cpu_softc_t; 84} cpu_softc_t;
82 85
83 86
84/* statics */ 87/* statics */
85static struct pcb lwp0pcb; 88static struct pcb lwp0pcb;
86static void *um_msgbuf; 89static void *um_msgbuf;
87 90
88 91
89/* attachment */ 92/* attachment */
90CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL); 93CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL);
91 94
92static int 95static int
93cpu_match(device_t parent, cfdata_t match, void *opaque) 96cpu_match(device_t parent, cfdata_t match, void *opaque)
@@ -98,28 +101,36 @@ cpu_match(device_t parent, cfdata_t matc @@ -98,28 +101,36 @@ cpu_match(device_t parent, cfdata_t matc
98 return 0; 101 return 0;
99 102
100 return 1; 103 return 1;
101} 104}
102 105
103static void 106static void
104cpu_attach(device_t parent, device_t self, void *opaque) 107cpu_attach(device_t parent, device_t self, void *opaque)
105{ 108{
106 cpu_softc_t *sc = device_private(self); 109 cpu_softc_t *sc = device_private(self);
107 110
108 aprint_naive("\n"); 111 aprint_naive("\n");
109 aprint_normal("\n"); 112 aprint_normal("\n");
110 113
 114 cpu_info_primary.ci_dev = self;
111 sc->sc_dev = self; 115 sc->sc_dev = self;
112 sc->sc_ci = &cpu_info_primary; 116 sc->sc_ci = &cpu_info_primary;
 117
 118 thunk_getcontext(&sc->sc_ucp);
 119 sc->sc_ucp.uc_stack.ss_sp = sc->sc_ucp_stack;
 120 sc->sc_ucp.uc_stack.ss_size = PAGE_SIZE - sizeof(register_t);
 121 sc->sc_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
 122 thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGALRM);
 123 thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGIO);
113} 124}
114 125
115void 126void
116cpu_configure(void) 127cpu_configure(void)
117{ 128{
118 if (config_rootfound("mainbus", NULL) == NULL) 129 if (config_rootfound("mainbus", NULL) == NULL)
119 panic("configure: mainbus not configured"); 130 panic("configure: mainbus not configured");
120 131
121 spl0(); 132 spl0();
122} 133}
123 134
124 135
125/* main guts */ 136/* main guts */
@@ -166,70 +177,89 @@ cpu_reboot(int howto, char *bootstr) @@ -166,70 +177,89 @@ cpu_reboot(int howto, char *bootstr)
166 177
167void 178void
168cpu_need_resched(struct cpu_info *ci, int flags) 179cpu_need_resched(struct cpu_info *ci, int flags)
169{ 180{
170 ci->ci_want_resched |= flags; 181 ci->ci_want_resched |= flags;
171 aston(ci); 182 aston(ci);
172} 183}
173 184
174void 185void
175cpu_need_proftick(struct lwp *l) 186cpu_need_proftick(struct lwp *l)
176{ 187{
177} 188}
178 189
 190static
 191void
 192cpu_switchto_atomic(lwp_t *oldlwp, lwp_t *newlwp)
 193{
 194 struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
 195 struct pcb *newpcb = lwp_getpcb(newlwp);
 196 struct cpu_info *ci = curcpu();
 197
 198 ci->ci_stash = oldlwp;
 199
 200 if (oldpcb)
 201 oldpcb->pcb_errno = thunk_geterrno();
 202
 203 thunk_seterrno(newpcb->pcb_errno);
 204
 205 curlwp = newlwp;
 206 if (thunk_setcontext(&newpcb->pcb_ucp))
 207 panic("setcontext failed");
 208 /* not reached */
 209}
 210
179lwp_t * 211lwp_t *
180cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning) 212cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
181{ 213{
182 struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL; 214 struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
183 struct pcb *newpcb = lwp_getpcb(newlwp); 215 struct pcb *newpcb = lwp_getpcb(newlwp);
184 struct cpu_info *ci = curcpu(); 216 struct cpu_info *ci = curcpu();
 217 cpu_softc_t *sc = device_private(ci->ci_dev);
185 218
186#ifdef CPU_DEBUG 219#ifdef CPU_DEBUG
187 thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n", 220 thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n",
188 oldlwp ? oldlwp->l_name : "none", 221 oldlwp ? oldlwp->l_name : "none",
189 oldlwp ? oldlwp->l_proc->p_pid : -1, 222 oldlwp ? oldlwp->l_proc->p_pid : -1,
190 oldlwp ? oldlwp->l_lid : -1, 223 oldlwp ? oldlwp->l_lid : -1,
191 newlwp ? newlwp->l_name : "none", 224 newlwp ? newlwp->l_name : "none",
192 newlwp ? newlwp->l_proc->p_pid : -1, 225 newlwp ? newlwp->l_proc->p_pid : -1,
193 newlwp ? newlwp->l_lid : -1); 226 newlwp ? newlwp->l_lid : -1);
194 if (oldpcb) { 227 if (oldpcb) {
195 thunk_printf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, " 228 thunk_printf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, "
196 "uc_stack.ss_size=%d\n", 229 "uc_stack.ss_size=%d\n",
197 oldpcb->pcb_ucp.uc_link, 230 oldpcb->pcb_ucp.uc_link,
198 oldpcb->pcb_ucp.uc_stack.ss_sp, 231 oldpcb->pcb_ucp.uc_stack.ss_sp,
199 (int)oldpcb->pcb_ucp.uc_stack.ss_size); 232 (int)oldpcb->pcb_ucp.uc_stack.ss_size);
200 } 233 }
201 if (newpcb) { 234 if (newpcb) {
202 thunk_printf_debug(" newpcb uc_link=%p, uc_stack.ss_sp=%p, " 235 thunk_printf_debug(" newpcb uc_link=%p, uc_stack.ss_sp=%p, "
203 "uc_stack.ss_size=%d\n", 236 "uc_stack.ss_size=%d\n",
204 newpcb->pcb_ucp.uc_link, 237 newpcb->pcb_ucp.uc_link,
205 newpcb->pcb_ucp.uc_stack.ss_sp, 238 newpcb->pcb_ucp.uc_stack.ss_sp,
206 (int)newpcb->pcb_ucp.uc_stack.ss_size); 239 (int)newpcb->pcb_ucp.uc_stack.ss_size);
207 } 240 }
208#endif /* !CPU_DEBUG */ 241#endif /* !CPU_DEBUG */
209 242
210 ci->ci_stash = oldlwp; 243 /* create atomic switcher */
211 244 thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic,
212 if (oldpcb) { 245 2, oldlwp, newlwp, NULL);
213 oldpcb->pcb_errno = thunk_geterrno(); 246
214 thunk_seterrno(newpcb->pcb_errno); 247 if (!oldpcb) {
215 curlwp = newlwp; 248 thunk_setcontext(&sc->sc_ucp);
216 if (thunk_swapcontext(&oldpcb->pcb_ucp, &newpcb->pcb_ucp)) 249 /* never returns */
217 panic("swapcontext failed"); 
218 } else { 250 } else {
219 thunk_seterrno(newpcb->pcb_errno); 251 thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp);
220 curlwp = newlwp; 252 /* returns here */
221 if (thunk_setcontext(&newpcb->pcb_ucp)) 
222 panic("setcontext failed"); 
223 } 253 }
224 254
225#ifdef CPU_DEBUG 255#ifdef CPU_DEBUG
226 thunk_printf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); 256 thunk_printf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp);
227#endif 257#endif
228 return ci->ci_stash; 258 return ci->ci_stash;
229} 259}
230 260
231void 261void
232cpu_dumpconf(void) 262cpu_dumpconf(void)
233{ 263{
234#ifdef CPU_DEBUG 264#ifdef CPU_DEBUG
235 thunk_printf_debug("cpu_dumpconf\n"); 265 thunk_printf_debug("cpu_dumpconf\n");
@@ -334,27 +364,27 @@ cpu_lwp_fork(struct lwp *l1, struct lwp  @@ -334,27 +364,27 @@ cpu_lwp_fork(struct lwp *l1, struct lwp
334 /* copy the PCB and its switchframes from parent */ 364 /* copy the PCB and its switchframes from parent */
335 memcpy(pcb2, pcb1, sizeof(struct pcb)); 365 memcpy(pcb2, pcb1, sizeof(struct pcb));
336 366
337 /* refresh context */ 367 /* refresh context */
338 if (thunk_getcontext(&pcb2->pcb_ucp)) 368 if (thunk_getcontext(&pcb2->pcb_ucp))
339 panic("getcontext failed"); 369 panic("getcontext failed");
340 370
341 /* recalculate the system stack top */ 371 /* recalculate the system stack top */
342 pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE; 372 pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE;
343 373
344 /* get l2 its own stack */ 374 /* get l2 its own stack */
345 pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack; 375 pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack;
346 pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack; 376 pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack;
347 pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU; 377 pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
348 pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp; 378 pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp;
349 thunk_makecontext(&pcb2->pcb_ucp, 379 thunk_makecontext(&pcb2->pcb_ucp,
350 (void (*)(void)) cpu_lwp_trampoline, 380 (void (*)(void)) cpu_lwp_trampoline,
351 3, &pcb2->pcb_ucp, func, arg); 381 3, &pcb2->pcb_ucp, func, arg);
352} 382}
353 383
354void 384void
355cpu_initclocks(void) 385cpu_initclocks(void)
356{ 386{
357 extern timer_t clock_timerid; 387 extern timer_t clock_timerid;
358 388
359 thunk_timer_start(clock_timerid, HZ); 389 thunk_timer_start(clock_timerid, HZ);
360} 390}
@@ -372,26 +402,27 @@ cpu_startup(void) @@ -372,26 +402,27 @@ cpu_startup(void)
372 initmsgbuf(um_msgbuf, msgbufsize); 402 initmsgbuf(um_msgbuf, msgbufsize);
373 403
374 /* allocate a submap for physio, 1Mb enough? */ 404 /* allocate a submap for physio, 1Mb enough? */
375 minaddr = 0; 405 minaddr = 0;
376 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 406 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
377 1024 * 1024, 0, false, NULL); 407 1024 * 1024, 0, false, NULL);
378 408
379 /* say hi! */ 409 /* say hi! */
380 banner(); 410 banner();
381 411
382 /* init lwp0 */ 412 /* init lwp0 */
383 memset(&lwp0pcb, 0, sizeof(lwp0pcb)); 413 memset(&lwp0pcb, 0, sizeof(lwp0pcb));
384 thunk_getcontext(&lwp0pcb.pcb_ucp); 414 thunk_getcontext(&lwp0pcb.pcb_ucp);
 415 lwp0pcb.pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
385 uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb); 416 uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb);
386 memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); 417 memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
387 418
388 /* set stack top */ 419 /* set stack top */
389 lwp0pcb.sys_stack_top = lwp0pcb.sys_stack + TRAPSTACKSIZE; 420 lwp0pcb.sys_stack_top = lwp0pcb.sys_stack + TRAPSTACKSIZE;
390} 421}
391 422
392void 423void
393cpu_rootconf(void) 424cpu_rootconf(void)
394{ 425{
395 extern char *usermode_root_device; 426 extern char *usermode_root_device;
396 device_t rdev; 427 device_t rdev;
397 428