1 1.84 ad /* $NetBSD: cpu.c,v 1.84 2023/10/04 20:28:06 ad Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 jmcneill * Copyright (c) 2007 Jared D. McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jmcneill * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jmcneill */ 28 1.1 jmcneill 29 1.19 jmcneill #include "opt_cpu.h" 30 1.37 jmcneill #include "opt_hz.h" 31 1.19 jmcneill 32 1.1 jmcneill #include <sys/cdefs.h> 33 1.84 ad __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.84 2023/10/04 20:28:06 ad Exp $"); 34 1.1 jmcneill 35 1.1 jmcneill #include <sys/param.h> 36 1.1 jmcneill #include <sys/conf.h> 37 1.1 jmcneill #include <sys/proc.h> 38 1.1 jmcneill #include <sys/systm.h> 39 1.1 jmcneill #include <sys/device.h> 40 1.1 jmcneill #include <sys/reboot.h> 41 1.1 jmcneill #include <sys/lwp.h> 42 1.1 jmcneill #include <sys/cpu.h> 43 1.1 jmcneill #include <sys/mbuf.h> 44 1.16 jmcneill #include <sys/msgbuf.h> 45 1.54 jmcneill #include <sys/kmem.h> 46 1.65 reinoud #include <sys/kernel.h> 47 1.67 jmcneill #include <sys/mount.h> 48 1.1 jmcneill 49 1.1 jmcneill #include <dev/cons.h> 50 1.1 jmcneill 51 1.1 jmcneill #include <machine/cpu.h> 52 1.1 jmcneill #include <machine/mainbus.h> 53 1.8 jmcneill #include <machine/pcb.h> 54 1.40 reinoud #include <machine/machdep.h> 55 1.10 jmcneill #include <machine/thunk.h> 56 1.1 jmcneill 57 1.1 jmcneill #include <uvm/uvm_extern.h> 58 1.1 jmcneill #include <uvm/uvm_page.h> 59 1.1 jmcneill 60 1.27 jmcneill #if __GNUC_PREREQ__(4,4) 61 1.27 jmcneill #define cpu_unreachable() __builtin_unreachable() 62 1.27 jmcneill #else 63 1.27 jmcneill #define cpu_unreachable() do { thunk_abort(); } while (0) 64 1.27 jmcneill #endif 65 1.27 jmcneill 66 1.1 jmcneill static int cpu_match(device_t, cfdata_t, void *); 67 1.1 jmcneill static void cpu_attach(device_t, device_t, void *); 68 1.1 jmcneill 69 1.76 reinoud /* XXX */ 70 1.76 reinoud //extern void *_lwp_getprivate(void); 71 1.76 reinoud //extern int _lwp_setprivate(void *); 72 1.76 reinoud 73 1.76 reinoud 74 1.13 jmcneill struct cpu_info cpu_info_primary = { 75 1.13 jmcneill .ci_dev = 0, 76 1.13 jmcneill .ci_self = &cpu_info_primary, 77 1.13 jmcneill .ci_idepth = -1, 78 1.13 jmcneill .ci_curlwp = &lwp0, 79 1.13 jmcneill }; 80 1.13 jmcneill 81 1.1 jmcneill typedef struct cpu_softc { 82 1.1 jmcneill device_t sc_dev; 83 1.1 jmcneill struct cpu_info *sc_ci; 84 1.68 reinoud 85 1.68 reinoud ucontext_t sc_ucp; 86 1.68 reinoud uint8_t sc_ucp_stack[PAGE_SIZE]; 87 1.1 jmcneill } cpu_softc_t; 88 1.1 jmcneill 89 1.64 reinoud 90 1.64 reinoud /* statics */ 91 1.15 jmcneill static struct pcb lwp0pcb; 92 1.54 jmcneill static void *um_msgbuf; 93 1.9 jmcneill 94 1.64 reinoud 95 1.64 reinoud /* attachment */ 96 1.1 jmcneill CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL); 97 1.1 jmcneill 98 1.1 jmcneill static int 99 1.1 jmcneill cpu_match(device_t parent, cfdata_t match, void *opaque) 100 1.1 jmcneill { 101 1.1 jmcneill struct thunkbus_attach_args *taa = opaque; 102 1.1 jmcneill 103 1.1 jmcneill if (taa->taa_type != THUNKBUS_TYPE_CPU) 104 1.1 jmcneill return 0; 105 1.1 jmcneill 106 1.1 jmcneill return 1; 107 1.1 jmcneill } 108 1.1 jmcneill 109 1.1 jmcneill static void 110 1.1 jmcneill cpu_attach(device_t parent, device_t self, void *opaque) 111 1.1 jmcneill { 112 1.1 jmcneill cpu_softc_t *sc = device_private(self); 113 1.1 jmcneill 114 1.1 jmcneill aprint_naive("\n"); 115 1.1 jmcneill aprint_normal("\n"); 116 1.1 jmcneill 117 1.68 reinoud cpu_info_primary.ci_dev = self; 118 1.1 jmcneill sc->sc_dev = self; 119 1.1 jmcneill sc->sc_ci = &cpu_info_primary; 120 1.68 reinoud 121 1.68 reinoud thunk_getcontext(&sc->sc_ucp); 122 1.68 reinoud sc->sc_ucp.uc_stack.ss_sp = sc->sc_ucp_stack; 123 1.68 reinoud sc->sc_ucp.uc_stack.ss_size = PAGE_SIZE - sizeof(register_t); 124 1.68 reinoud sc->sc_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK; 125 1.68 reinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGALRM); 126 1.68 reinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGIO); 127 1.75 reinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGINT); 128 1.75 reinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGTSTP); 129 1.1 jmcneill } 130 1.1 jmcneill 131 1.1 jmcneill void 132 1.1 jmcneill cpu_configure(void) 133 1.1 jmcneill { 134 1.73 christos cpu_setmodel("virtual processor"); 135 1.1 jmcneill if (config_rootfound("mainbus", NULL) == NULL) 136 1.1 jmcneill panic("configure: mainbus not configured"); 137 1.1 jmcneill 138 1.1 jmcneill spl0(); 139 1.1 jmcneill } 140 1.1 jmcneill 141 1.64 reinoud 142 1.64 reinoud /* main guts */ 143 1.1 jmcneill void 144 1.1 jmcneill cpu_reboot(int howto, char *bootstr) 145 1.1 jmcneill { 146 1.11 jmcneill extern void usermode_reboot(void); 147 1.11 jmcneill 148 1.67 jmcneill if (cold) 149 1.67 jmcneill howto |= RB_HALT; 150 1.67 jmcneill 151 1.67 jmcneill if ((howto & RB_NOSYNC) == 0) 152 1.67 jmcneill vfs_shutdown(); 153 1.67 jmcneill else 154 1.67 jmcneill suspendsched(); 155 1.67 jmcneill 156 1.67 jmcneill doshutdownhooks(); 157 1.67 jmcneill pmf_system_shutdown(boothowto); 158 1.1 jmcneill 159 1.1 jmcneill if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 160 1.10 jmcneill thunk_exit(0); 161 1.1 jmcneill 162 1.67 jmcneill splhigh(); 163 1.67 jmcneill 164 1.22 jmcneill if (howto & RB_DUMP) 165 1.22 jmcneill thunk_abort(); 166 1.22 jmcneill 167 1.1 jmcneill if (howto & RB_HALT) { 168 1.1 jmcneill printf("\n"); 169 1.1 jmcneill printf("The operating system has halted.\n"); 170 1.1 jmcneill printf("Please press any key to reboot.\n\n"); 171 1.1 jmcneill cnpollc(1); 172 1.1 jmcneill cngetc(); 173 1.1 jmcneill cnpollc(0); 174 1.1 jmcneill } 175 1.1 jmcneill 176 1.1 jmcneill printf("rebooting...\n"); 177 1.1 jmcneill 178 1.11 jmcneill usermode_reboot(); 179 1.1 jmcneill 180 1.1 jmcneill /* NOTREACHED */ 181 1.27 jmcneill cpu_unreachable(); 182 1.1 jmcneill } 183 1.1 jmcneill 184 1.1 jmcneill void 185 1.81 ad cpu_need_resched(struct cpu_info *ci, struct lwp *l, int flags) 186 1.1 jmcneill { 187 1.65 reinoud aston(ci); 188 1.1 jmcneill } 189 1.1 jmcneill 190 1.1 jmcneill void 191 1.1 jmcneill cpu_need_proftick(struct lwp *l) 192 1.1 jmcneill { 193 1.1 jmcneill } 194 1.1 jmcneill 195 1.78 reinoud int 196 1.78 reinoud cpu_lwp_setprivate(lwp_t *l, void *ptr) 197 1.78 reinoud { 198 1.78 reinoud struct pcb *pcb = lwp_getpcb(l); 199 1.78 reinoud 200 1.78 reinoud /* set both ucontexts up for TLS just in case */ 201 1.78 reinoud pcb->pcb_ucp.uc_mcontext._mc_tlsbase = 202 1.78 reinoud (uintptr_t) ptr; 203 1.78 reinoud pcb->pcb_ucp.uc_flags |= _UC_TLSBASE; 204 1.78 reinoud 205 1.78 reinoud pcb->pcb_userret_ucp.uc_mcontext._mc_tlsbase = 206 1.78 reinoud (uintptr_t) ptr; 207 1.78 reinoud pcb->pcb_userret_ucp.uc_flags |= _UC_TLSBASE; 208 1.78 reinoud 209 1.78 reinoud return 0; 210 1.78 reinoud } 211 1.76 reinoud 212 1.68 reinoud static 213 1.68 reinoud void 214 1.68 reinoud cpu_switchto_atomic(lwp_t *oldlwp, lwp_t *newlwp) 215 1.68 reinoud { 216 1.75 reinoud struct pcb *oldpcb; 217 1.75 reinoud struct pcb *newpcb; 218 1.75 reinoud struct cpu_info *ci; 219 1.77 reinoud int s; 220 1.75 reinoud 221 1.75 reinoud oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL; 222 1.75 reinoud newpcb = lwp_getpcb(newlwp); 223 1.75 reinoud ci = curcpu(); 224 1.68 reinoud 225 1.77 reinoud s = splhigh(); 226 1.77 reinoud 227 1.68 reinoud ci->ci_stash = oldlwp; 228 1.68 reinoud if (oldpcb) 229 1.68 reinoud oldpcb->pcb_errno = thunk_geterrno(); 230 1.68 reinoud 231 1.68 reinoud thunk_seterrno(newpcb->pcb_errno); 232 1.78 reinoud curlwp = newlwp; 233 1.68 reinoud 234 1.77 reinoud splx(s); 235 1.77 reinoud 236 1.68 reinoud if (thunk_setcontext(&newpcb->pcb_ucp)) 237 1.68 reinoud panic("setcontext failed"); 238 1.77 reinoud 239 1.68 reinoud /* not reached */ 240 1.68 reinoud } 241 1.68 reinoud 242 1.76 reinoud 243 1.1 jmcneill lwp_t * 244 1.1 jmcneill cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning) 245 1.1 jmcneill { 246 1.5 rmind struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL; 247 1.5 rmind struct pcb *newpcb = lwp_getpcb(newlwp); 248 1.1 jmcneill struct cpu_info *ci = curcpu(); 249 1.68 reinoud cpu_softc_t *sc = device_private(ci->ci_dev); 250 1.1 jmcneill 251 1.1 jmcneill #ifdef CPU_DEBUG 252 1.58 reinoud thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n", 253 1.1 jmcneill oldlwp ? oldlwp->l_name : "none", 254 1.17 jmcneill oldlwp ? oldlwp->l_proc->p_pid : -1, 255 1.17 jmcneill oldlwp ? oldlwp->l_lid : -1, 256 1.17 jmcneill newlwp ? newlwp->l_name : "none", 257 1.17 jmcneill newlwp ? newlwp->l_proc->p_pid : -1, 258 1.17 jmcneill newlwp ? newlwp->l_lid : -1); 259 1.1 jmcneill if (oldpcb) { 260 1.58 reinoud thunk_printf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, " 261 1.76 reinoud "uc_stack.ss_size=%d, l_private %p, uc_mcontext._mc_tlsbase=%p(%s)\n", 262 1.1 jmcneill oldpcb->pcb_ucp.uc_link, 263 1.1 jmcneill oldpcb->pcb_ucp.uc_stack.ss_sp, 264 1.76 reinoud (int)oldpcb->pcb_ucp.uc_stack.ss_size, 265 1.76 reinoud (void *) oldlwp->l_private, 266 1.76 reinoud (void *) oldpcb->pcb_ucp.uc_mcontext._mc_tlsbase, 267 1.76 reinoud oldpcb->pcb_ucp.uc_flags & _UC_TLSBASE? "ON":"off"); 268 1.1 jmcneill } 269 1.1 jmcneill if (newpcb) { 270 1.76 reinoud thunk_printf_debug(" newpewcb uc_link=%p, uc_stack.ss_sp=%p, " 271 1.76 reinoud "uc_stack.ss_size=%d, l_private %p, uc_mcontext._mc_tlsbase=%p(%s)\n", 272 1.1 jmcneill newpcb->pcb_ucp.uc_link, 273 1.1 jmcneill newpcb->pcb_ucp.uc_stack.ss_sp, 274 1.76 reinoud (int)newpcb->pcb_ucp.uc_stack.ss_size, 275 1.76 reinoud (void *) newlwp->l_private, 276 1.76 reinoud (void *) newpcb->pcb_ucp.uc_mcontext._mc_tlsbase, 277 1.76 reinoud newpcb->pcb_ucp.uc_flags & _UC_TLSBASE? "ON":"off"); 278 1.1 jmcneill } 279 1.1 jmcneill #endif /* !CPU_DEBUG */ 280 1.1 jmcneill 281 1.68 reinoud /* create atomic switcher */ 282 1.75 reinoud KASSERT(newlwp); 283 1.68 reinoud thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic, 284 1.70 reinoud 2, oldlwp, newlwp, NULL, NULL); 285 1.69 reinoud KASSERT(sc); 286 1.69 reinoud if (oldpcb) { 287 1.69 reinoud thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp); 288 1.69 reinoud /* returns here */ 289 1.69 reinoud } else { 290 1.68 reinoud thunk_setcontext(&sc->sc_ucp); 291 1.68 reinoud /* never returns */ 292 1.1 jmcneill } 293 1.30 reinoud 294 1.1 jmcneill #ifdef CPU_DEBUG 295 1.58 reinoud thunk_printf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); 296 1.1 jmcneill #endif 297 1.1 jmcneill return ci->ci_stash; 298 1.1 jmcneill } 299 1.1 jmcneill 300 1.1 jmcneill void 301 1.1 jmcneill cpu_dumpconf(void) 302 1.1 jmcneill { 303 1.1 jmcneill #ifdef CPU_DEBUG 304 1.58 reinoud thunk_printf_debug("cpu_dumpconf\n"); 305 1.1 jmcneill #endif 306 1.1 jmcneill } 307 1.1 jmcneill 308 1.1 jmcneill void 309 1.1 jmcneill cpu_signotify(struct lwp *l) 310 1.1 jmcneill { 311 1.1 jmcneill } 312 1.1 jmcneill 313 1.1 jmcneill void 314 1.1 jmcneill cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) 315 1.1 jmcneill { 316 1.56 reinoud struct pcb *pcb = lwp_getpcb(l); 317 1.56 reinoud ucontext_t *ucp = &pcb->pcb_userret_ucp; 318 1.76 reinoud 319 1.1 jmcneill #ifdef CPU_DEBUG 320 1.58 reinoud thunk_printf_debug("cpu_getmcontext\n"); 321 1.1 jmcneill #endif 322 1.56 reinoud memcpy(mcp, &ucp->uc_mcontext, sizeof(mcontext_t)); 323 1.76 reinoud 324 1.79 reinoud /* report we have the CPU FPU and TLSBASE registers */ 325 1.76 reinoud mcp->_mc_tlsbase = (uintptr_t) l->l_private; 326 1.79 reinoud *flags = _UC_CPU | _UC_FPU | _UC_TLSBASE; 327 1.76 reinoud 328 1.56 reinoud return; 329 1.1 jmcneill } 330 1.1 jmcneill 331 1.1 jmcneill int 332 1.71 reinoud cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp) 333 1.71 reinoud { 334 1.71 reinoud /* 335 1.71 reinoud * can we check here? or should that be done in the target 336 1.71 reinoud * specific places? 337 1.71 reinoud */ 338 1.76 reinoud /* XXX NO CHECKING! XXX */ 339 1.76 reinoud #ifdef CPU_DEBUG 340 1.79 reinoud thunk_printf_debug("cpu_mcontext_validate\n"); 341 1.76 reinoud #endif 342 1.71 reinoud return 0; 343 1.71 reinoud } 344 1.71 reinoud 345 1.71 reinoud int 346 1.1 jmcneill cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 347 1.1 jmcneill { 348 1.56 reinoud struct pcb *pcb = lwp_getpcb(l); 349 1.56 reinoud ucontext_t *ucp = &pcb->pcb_userret_ucp; 350 1.56 reinoud 351 1.1 jmcneill #ifdef CPU_DEBUG 352 1.58 reinoud thunk_printf_debug("cpu_setmcontext\n"); 353 1.1 jmcneill #endif 354 1.77 reinoud if ((flags & _UC_CPU) != 0) 355 1.80 reinoud memcpy(&ucp->uc_mcontext.__gregs, &mcp->__gregs, sizeof(__gregset_t)); 356 1.77 reinoud if ((flags & _UC_FPU) != 0) 357 1.80 reinoud memcpy(&ucp->uc_mcontext.__fpregs, &mcp->__fpregs, sizeof(__fpregset_t)); 358 1.77 reinoud if ((flags & _UC_TLSBASE) != 0) 359 1.77 reinoud lwp_setprivate(l, (void *) (uintptr_t) mcp->_mc_tlsbase); 360 1.76 reinoud 361 1.77 reinoud #if 0 362 1.77 reinoud /* 363 1.77 reinoud * XXX we ignore the set and clear stack since signals are done 364 1.77 reinoud * slightly differently. 365 1.77 reinoud */ 366 1.77 reinoud thunk_printf("%s: flags %x\n", __func__, flags); 367 1.77 reinoud mutex_enter(l->l_proc->p_lock); 368 1.77 reinoud if (flags & _UC_SETSTACK) 369 1.77 reinoud l->l_sigstk.ss_flags |= SS_ONSTACK; 370 1.77 reinoud if (flags & _UC_CLRSTACK) 371 1.77 reinoud l->l_sigstk.ss_flags &= ~SS_ONSTACK; 372 1.77 reinoud mutex_exit(l->l_proc->p_lock); 373 1.77 reinoud #endif 374 1.77 reinoud 375 1.77 reinoud ucp->uc_flags |= (flags & (_UC_CPU | _UC_FPU | _UC_TLSBASE)); 376 1.76 reinoud 377 1.1 jmcneill return 0; 378 1.1 jmcneill } 379 1.1 jmcneill 380 1.1 jmcneill void 381 1.1 jmcneill cpu_idle(void) 382 1.1 jmcneill { 383 1.1 jmcneill struct cpu_info *ci = curcpu(); 384 1.1 jmcneill 385 1.1 jmcneill if (ci->ci_want_resched) 386 1.1 jmcneill return; 387 1.1 jmcneill 388 1.53 jmcneill thunk_idle(); 389 1.1 jmcneill } 390 1.1 jmcneill 391 1.1 jmcneill void 392 1.1 jmcneill cpu_lwp_free(struct lwp *l, int proc) 393 1.1 jmcneill { 394 1.1 jmcneill #ifdef CPU_DEBUG 395 1.58 reinoud thunk_printf_debug("cpu_lwp_free (dummy)\n"); 396 1.1 jmcneill #endif 397 1.1 jmcneill } 398 1.1 jmcneill 399 1.1 jmcneill void 400 1.1 jmcneill cpu_lwp_free2(struct lwp *l) 401 1.1 jmcneill { 402 1.5 rmind struct pcb *pcb = lwp_getpcb(l); 403 1.1 jmcneill 404 1.1 jmcneill #ifdef CPU_DEBUG 405 1.58 reinoud thunk_printf_debug("cpu_lwp_free2\n"); 406 1.1 jmcneill #endif 407 1.1 jmcneill 408 1.1 jmcneill if (pcb == NULL) 409 1.1 jmcneill return; 410 1.64 reinoud /* XXX nothing to do? */ 411 1.1 jmcneill } 412 1.1 jmcneill 413 1.1 jmcneill static void 414 1.44 reinoud cpu_lwp_trampoline(ucontext_t *ucp, void (*func)(void *), void *arg) 415 1.1 jmcneill { 416 1.18 reinoud #ifdef CPU_DEBUG 417 1.58 reinoud thunk_printf_debug("cpu_lwp_trampoline called with func %p, arg %p\n", (void *) func, arg); 418 1.18 reinoud #endif 419 1.44 reinoud /* init lwp */ 420 1.1 jmcneill lwp_startup(curcpu()->ci_stash, curlwp); 421 1.44 reinoud 422 1.45 reinoud /* actual jump */ 423 1.70 reinoud thunk_makecontext(ucp, (void (*)(void)) func, 1, arg, NULL, NULL, NULL); 424 1.45 reinoud thunk_setcontext(ucp); 425 1.1 jmcneill } 426 1.1 jmcneill 427 1.1 jmcneill void 428 1.1 jmcneill cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, 429 1.1 jmcneill void (*func)(void *), void *arg) 430 1.1 jmcneill { 431 1.23 reinoud struct pcb *pcb1 = lwp_getpcb(l1); 432 1.23 reinoud struct pcb *pcb2 = lwp_getpcb(l2); 433 1.1 jmcneill 434 1.1 jmcneill #ifdef CPU_DEBUG 435 1.58 reinoud thunk_printf_debug("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n", 436 1.1 jmcneill l1 ? l1->l_name : "none", l1, 437 1.1 jmcneill l2 ? l2->l_name : "none", l2, 438 1.1 jmcneill stack, (int)stacksize); 439 1.1 jmcneill #endif 440 1.45 reinoud if (stack) 441 1.45 reinoud panic("%s: stack passed, can't handle\n", __func__); 442 1.45 reinoud 443 1.23 reinoud /* copy the PCB and its switchframes from parent */ 444 1.23 reinoud memcpy(pcb2, pcb1, sizeof(struct pcb)); 445 1.23 reinoud 446 1.76 reinoud /* refresh context, XXX needed? */ 447 1.23 reinoud if (thunk_getcontext(&pcb2->pcb_ucp)) 448 1.26 jmcneill panic("getcontext failed"); 449 1.23 reinoud 450 1.76 reinoud /* set up for TLS */ 451 1.76 reinoud pcb2->pcb_ucp.uc_mcontext._mc_tlsbase = (intptr_t) l2->l_private; 452 1.76 reinoud pcb2->pcb_ucp.uc_flags |= _UC_TLSBASE; 453 1.76 reinoud 454 1.64 reinoud /* recalculate the system stack top */ 455 1.64 reinoud pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE; 456 1.64 reinoud 457 1.64 reinoud /* get l2 its own stack */ 458 1.64 reinoud pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack; 459 1.64 reinoud pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack; 460 1.69 reinoud pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp; 461 1.69 reinoud 462 1.69 reinoud thunk_sigemptyset(&pcb2->pcb_ucp.uc_sigmask); 463 1.76 reinoud 464 1.45 reinoud thunk_makecontext(&pcb2->pcb_ucp, 465 1.45 reinoud (void (*)(void)) cpu_lwp_trampoline, 466 1.70 reinoud 3, &pcb2->pcb_ucp, func, arg, NULL); 467 1.1 jmcneill } 468 1.1 jmcneill 469 1.1 jmcneill void 470 1.1 jmcneill cpu_initclocks(void) 471 1.1 jmcneill { 472 1.55 jmcneill extern timer_t clock_timerid; 473 1.37 jmcneill 474 1.55 jmcneill thunk_timer_start(clock_timerid, HZ); 475 1.1 jmcneill } 476 1.1 jmcneill 477 1.1 jmcneill void 478 1.1 jmcneill cpu_startup(void) 479 1.1 jmcneill { 480 1.57 reinoud vaddr_t minaddr, maxaddr; 481 1.64 reinoud size_t msgbufsize = 32 * 1024; 482 1.47 reinoud 483 1.57 reinoud /* get ourself a message buffer */ 484 1.54 jmcneill um_msgbuf = kmem_zalloc(msgbufsize, KM_SLEEP); 485 1.54 jmcneill initmsgbuf(um_msgbuf, msgbufsize); 486 1.16 jmcneill 487 1.57 reinoud /* allocate a submap for physio, 1Mb enough? */ 488 1.57 reinoud minaddr = 0; 489 1.57 reinoud phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 490 1.57 reinoud 1024 * 1024, 0, false, NULL); 491 1.57 reinoud 492 1.57 reinoud /* say hi! */ 493 1.13 jmcneill banner(); 494 1.15 jmcneill 495 1.57 reinoud /* init lwp0 */ 496 1.15 jmcneill memset(&lwp0pcb, 0, sizeof(lwp0pcb)); 497 1.64 reinoud thunk_getcontext(&lwp0pcb.pcb_ucp); 498 1.69 reinoud thunk_sigemptyset(&lwp0pcb.pcb_ucp.uc_sigmask); 499 1.68 reinoud lwp0pcb.pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK; 500 1.69 reinoud 501 1.64 reinoud uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb); 502 1.64 reinoud memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t)); 503 1.23 reinoud 504 1.64 reinoud /* set stack top */ 505 1.64 reinoud lwp0pcb.sys_stack_top = lwp0pcb.sys_stack + TRAPSTACKSIZE; 506 1.1 jmcneill } 507 1.1 jmcneill 508 1.1 jmcneill void 509 1.1 jmcneill cpu_rootconf(void) 510 1.1 jmcneill { 511 1.66 jmcneill extern char *usermode_root_device; 512 1.2 joerg device_t rdev; 513 1.1 jmcneill 514 1.66 jmcneill if (usermode_root_device != NULL) { 515 1.66 jmcneill rdev = device_find_by_xname(usermode_root_device); 516 1.66 jmcneill } else { 517 1.66 jmcneill rdev = device_find_by_xname("ld0"); 518 1.66 jmcneill if (rdev == NULL) 519 1.66 jmcneill rdev = device_find_by_xname("md0"); 520 1.66 jmcneill } 521 1.1 jmcneill 522 1.12 jmcneill aprint_normal("boot device: %s\n", 523 1.12 jmcneill rdev ? device_xname(rdev) : "<unknown>"); 524 1.72 mlelstv booted_device = rdev; 525 1.72 mlelstv rootconf(); 526 1.1 jmcneill } 527 1.1 jmcneill 528 1.1 jmcneill bool 529 1.1 jmcneill cpu_intr_p(void) 530 1.1 jmcneill { 531 1.13 jmcneill int idepth; 532 1.84 ad long pctr; 533 1.82 ad lwp_t *l; 534 1.13 jmcneill 535 1.82 ad l = curlwp; 536 1.82 ad do { 537 1.84 ad pctr = lwp_pctr(); 538 1.82 ad idepth = l->l_cpu->ci_idepth; 539 1.84 ad } while (__predict_false(pctr != lwp_pctr())); 540 1.13 jmcneill 541 1.82 ad return idepth >= 0; 542 1.1 jmcneill } 543