1*a355028fSad /* $NetBSD: cpu.c,v 1.84 2023/10/04 20:28:06 ad Exp $ */
238365ca3Sjmcneill
338365ca3Sjmcneill /*-
438365ca3Sjmcneill * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
538365ca3Sjmcneill * All rights reserved.
638365ca3Sjmcneill *
738365ca3Sjmcneill * Redistribution and use in source and binary forms, with or without
838365ca3Sjmcneill * modification, are permitted provided that the following conditions
938365ca3Sjmcneill * are met:
1038365ca3Sjmcneill * 1. Redistributions of source code must retain the above copyright
1138365ca3Sjmcneill * notice, this list of conditions and the following disclaimer.
1238365ca3Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
1338365ca3Sjmcneill * notice, this list of conditions and the following disclaimer in the
1438365ca3Sjmcneill * documentation and/or other materials provided with the distribution.
1538365ca3Sjmcneill *
1638365ca3Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1738365ca3Sjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1838365ca3Sjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1938365ca3Sjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2038365ca3Sjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2138365ca3Sjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2238365ca3Sjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2338365ca3Sjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2438365ca3Sjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2538365ca3Sjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2638365ca3Sjmcneill * POSSIBILITY OF SUCH DAMAGE.
2738365ca3Sjmcneill */
2838365ca3Sjmcneill
29f4f64870Sjmcneill #include "opt_cpu.h"
303dae8a59Sjmcneill #include "opt_hz.h"
31f4f64870Sjmcneill
3238365ca3Sjmcneill #include <sys/cdefs.h>
33*a355028fSad __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.84 2023/10/04 20:28:06 ad Exp $");
3438365ca3Sjmcneill
3538365ca3Sjmcneill #include <sys/param.h>
3638365ca3Sjmcneill #include <sys/conf.h>
3738365ca3Sjmcneill #include <sys/proc.h>
3838365ca3Sjmcneill #include <sys/systm.h>
3938365ca3Sjmcneill #include <sys/device.h>
4038365ca3Sjmcneill #include <sys/reboot.h>
4138365ca3Sjmcneill #include <sys/lwp.h>
4238365ca3Sjmcneill #include <sys/cpu.h>
4338365ca3Sjmcneill #include <sys/mbuf.h>
4405f1b5eaSjmcneill #include <sys/msgbuf.h>
45e5e51288Sjmcneill #include <sys/kmem.h>
467752740cSreinoud #include <sys/kernel.h>
47bd720a63Sjmcneill #include <sys/mount.h>
4838365ca3Sjmcneill
4938365ca3Sjmcneill #include <dev/cons.h>
5038365ca3Sjmcneill
5138365ca3Sjmcneill #include <machine/cpu.h>
5238365ca3Sjmcneill #include <machine/mainbus.h>
536a94506dSjmcneill #include <machine/pcb.h>
54dde6f969Sreinoud #include <machine/machdep.h>
5526740a1aSjmcneill #include <machine/thunk.h>
5638365ca3Sjmcneill
5738365ca3Sjmcneill #include <uvm/uvm_extern.h>
5838365ca3Sjmcneill #include <uvm/uvm_page.h>
5938365ca3Sjmcneill
607c4e700dSjmcneill #if __GNUC_PREREQ__(4,4)
617c4e700dSjmcneill #define cpu_unreachable() __builtin_unreachable()
627c4e700dSjmcneill #else
637c4e700dSjmcneill #define cpu_unreachable() do { thunk_abort(); } while (0)
647c4e700dSjmcneill #endif
657c4e700dSjmcneill
6638365ca3Sjmcneill static int cpu_match(device_t, cfdata_t, void *);
6738365ca3Sjmcneill static void cpu_attach(device_t, device_t, void *);
6838365ca3Sjmcneill
69b19ccb81Sreinoud /* XXX */
70b19ccb81Sreinoud //extern void *_lwp_getprivate(void);
71b19ccb81Sreinoud //extern int _lwp_setprivate(void *);
72b19ccb81Sreinoud
73b19ccb81Sreinoud
74df5e2583Sjmcneill struct cpu_info cpu_info_primary = {
75df5e2583Sjmcneill .ci_dev = 0,
76df5e2583Sjmcneill .ci_self = &cpu_info_primary,
77df5e2583Sjmcneill .ci_idepth = -1,
78df5e2583Sjmcneill .ci_curlwp = &lwp0,
79df5e2583Sjmcneill };
80df5e2583Sjmcneill
8138365ca3Sjmcneill typedef struct cpu_softc {
8238365ca3Sjmcneill device_t sc_dev;
8338365ca3Sjmcneill struct cpu_info *sc_ci;
8420157f98Sreinoud
8520157f98Sreinoud ucontext_t sc_ucp;
8620157f98Sreinoud uint8_t sc_ucp_stack[PAGE_SIZE];
8738365ca3Sjmcneill } cpu_softc_t;
8838365ca3Sjmcneill
89cd980be6Sreinoud
90cd980be6Sreinoud /* statics */
9111b9552bSjmcneill static struct pcb lwp0pcb;
92e5e51288Sjmcneill static void *um_msgbuf;
9321f7e025Sjmcneill
94cd980be6Sreinoud
95cd980be6Sreinoud /* attachment */
9638365ca3Sjmcneill CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL);
9738365ca3Sjmcneill
9838365ca3Sjmcneill static int
cpu_match(device_t parent,cfdata_t match,void * opaque)9938365ca3Sjmcneill cpu_match(device_t parent, cfdata_t match, void *opaque)
10038365ca3Sjmcneill {
10138365ca3Sjmcneill struct thunkbus_attach_args *taa = opaque;
10238365ca3Sjmcneill
10338365ca3Sjmcneill if (taa->taa_type != THUNKBUS_TYPE_CPU)
10438365ca3Sjmcneill return 0;
10538365ca3Sjmcneill
10638365ca3Sjmcneill return 1;
10738365ca3Sjmcneill }
10838365ca3Sjmcneill
10938365ca3Sjmcneill static void
cpu_attach(device_t parent,device_t self,void * opaque)11038365ca3Sjmcneill cpu_attach(device_t parent, device_t self, void *opaque)
11138365ca3Sjmcneill {
11238365ca3Sjmcneill cpu_softc_t *sc = device_private(self);
11338365ca3Sjmcneill
11438365ca3Sjmcneill aprint_naive("\n");
11538365ca3Sjmcneill aprint_normal("\n");
11638365ca3Sjmcneill
11720157f98Sreinoud cpu_info_primary.ci_dev = self;
11838365ca3Sjmcneill sc->sc_dev = self;
11938365ca3Sjmcneill sc->sc_ci = &cpu_info_primary;
12020157f98Sreinoud
12120157f98Sreinoud thunk_getcontext(&sc->sc_ucp);
12220157f98Sreinoud sc->sc_ucp.uc_stack.ss_sp = sc->sc_ucp_stack;
12320157f98Sreinoud sc->sc_ucp.uc_stack.ss_size = PAGE_SIZE - sizeof(register_t);
12420157f98Sreinoud sc->sc_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
12520157f98Sreinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGALRM);
12620157f98Sreinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGIO);
1270767c295Sreinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGINT);
1280767c295Sreinoud thunk_sigaddset(&sc->sc_ucp.uc_sigmask, SIGTSTP);
12938365ca3Sjmcneill }
13038365ca3Sjmcneill
13138365ca3Sjmcneill void
cpu_configure(void)13238365ca3Sjmcneill cpu_configure(void)
13338365ca3Sjmcneill {
134b2543b91Schristos cpu_setmodel("virtual processor");
13538365ca3Sjmcneill if (config_rootfound("mainbus", NULL) == NULL)
13638365ca3Sjmcneill panic("configure: mainbus not configured");
13738365ca3Sjmcneill
13838365ca3Sjmcneill spl0();
13938365ca3Sjmcneill }
14038365ca3Sjmcneill
141cd980be6Sreinoud
142cd980be6Sreinoud /* main guts */
14338365ca3Sjmcneill void
cpu_reboot(int howto,char * bootstr)14438365ca3Sjmcneill cpu_reboot(int howto, char *bootstr)
14538365ca3Sjmcneill {
146cd366a78Sjmcneill extern void usermode_reboot(void);
147cd366a78Sjmcneill
148bd720a63Sjmcneill if (cold)
149bd720a63Sjmcneill howto |= RB_HALT;
150bd720a63Sjmcneill
151bd720a63Sjmcneill if ((howto & RB_NOSYNC) == 0)
152bd720a63Sjmcneill vfs_shutdown();
153bd720a63Sjmcneill else
154bd720a63Sjmcneill suspendsched();
155bd720a63Sjmcneill
156bd720a63Sjmcneill doshutdownhooks();
157bd720a63Sjmcneill pmf_system_shutdown(boothowto);
15838365ca3Sjmcneill
15938365ca3Sjmcneill if ((howto & RB_POWERDOWN) == RB_POWERDOWN)
16026740a1aSjmcneill thunk_exit(0);
16138365ca3Sjmcneill
162bd720a63Sjmcneill splhigh();
163bd720a63Sjmcneill
16461d5347cSjmcneill if (howto & RB_DUMP)
16561d5347cSjmcneill thunk_abort();
16661d5347cSjmcneill
16738365ca3Sjmcneill if (howto & RB_HALT) {
16838365ca3Sjmcneill printf("\n");
16938365ca3Sjmcneill printf("The operating system has halted.\n");
17038365ca3Sjmcneill printf("Please press any key to reboot.\n\n");
17138365ca3Sjmcneill cnpollc(1);
17238365ca3Sjmcneill cngetc();
17338365ca3Sjmcneill cnpollc(0);
17438365ca3Sjmcneill }
17538365ca3Sjmcneill
17638365ca3Sjmcneill printf("rebooting...\n");
17738365ca3Sjmcneill
178cd366a78Sjmcneill usermode_reboot();
17938365ca3Sjmcneill
18038365ca3Sjmcneill /* NOTREACHED */
1817c4e700dSjmcneill cpu_unreachable();
18238365ca3Sjmcneill }
18338365ca3Sjmcneill
18438365ca3Sjmcneill void
cpu_need_resched(struct cpu_info * ci,struct lwp * l,int flags)185115c1bc0Sad cpu_need_resched(struct cpu_info *ci, struct lwp *l, int flags)
18638365ca3Sjmcneill {
1877752740cSreinoud aston(ci);
18838365ca3Sjmcneill }
18938365ca3Sjmcneill
19038365ca3Sjmcneill void
cpu_need_proftick(struct lwp * l)19138365ca3Sjmcneill cpu_need_proftick(struct lwp *l)
19238365ca3Sjmcneill {
19338365ca3Sjmcneill }
19438365ca3Sjmcneill
195d5f46765Sreinoud int
cpu_lwp_setprivate(lwp_t * l,void * ptr)196d5f46765Sreinoud cpu_lwp_setprivate(lwp_t *l, void *ptr)
197d5f46765Sreinoud {
198d5f46765Sreinoud struct pcb *pcb = lwp_getpcb(l);
199d5f46765Sreinoud
200d5f46765Sreinoud /* set both ucontexts up for TLS just in case */
201d5f46765Sreinoud pcb->pcb_ucp.uc_mcontext._mc_tlsbase =
202d5f46765Sreinoud (uintptr_t) ptr;
203d5f46765Sreinoud pcb->pcb_ucp.uc_flags |= _UC_TLSBASE;
204d5f46765Sreinoud
205d5f46765Sreinoud pcb->pcb_userret_ucp.uc_mcontext._mc_tlsbase =
206d5f46765Sreinoud (uintptr_t) ptr;
207d5f46765Sreinoud pcb->pcb_userret_ucp.uc_flags |= _UC_TLSBASE;
208d5f46765Sreinoud
209d5f46765Sreinoud return 0;
210d5f46765Sreinoud }
211b19ccb81Sreinoud
21220157f98Sreinoud static
21320157f98Sreinoud void
cpu_switchto_atomic(lwp_t * oldlwp,lwp_t * newlwp)21420157f98Sreinoud cpu_switchto_atomic(lwp_t *oldlwp, lwp_t *newlwp)
21520157f98Sreinoud {
2160767c295Sreinoud struct pcb *oldpcb;
2170767c295Sreinoud struct pcb *newpcb;
2180767c295Sreinoud struct cpu_info *ci;
2198ed4e5c0Sreinoud int s;
2200767c295Sreinoud
2210767c295Sreinoud oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
2220767c295Sreinoud newpcb = lwp_getpcb(newlwp);
2230767c295Sreinoud ci = curcpu();
22420157f98Sreinoud
2258ed4e5c0Sreinoud s = splhigh();
22620157f98Sreinoud
2278ed4e5c0Sreinoud ci->ci_stash = oldlwp;
22820157f98Sreinoud if (oldpcb)
22920157f98Sreinoud oldpcb->pcb_errno = thunk_geterrno();
23020157f98Sreinoud
23120157f98Sreinoud thunk_seterrno(newpcb->pcb_errno);
23220157f98Sreinoud curlwp = newlwp;
233d5f46765Sreinoud
2348ed4e5c0Sreinoud splx(s);
2358ed4e5c0Sreinoud
23620157f98Sreinoud if (thunk_setcontext(&newpcb->pcb_ucp))
23720157f98Sreinoud panic("setcontext failed");
2388ed4e5c0Sreinoud
23920157f98Sreinoud /* not reached */
24020157f98Sreinoud }
24120157f98Sreinoud
242b19ccb81Sreinoud
24338365ca3Sjmcneill lwp_t *
cpu_switchto(lwp_t * oldlwp,lwp_t * newlwp,bool returning)24438365ca3Sjmcneill cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
24538365ca3Sjmcneill {
246448807faSrmind struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
247448807faSrmind struct pcb *newpcb = lwp_getpcb(newlwp);
24838365ca3Sjmcneill struct cpu_info *ci = curcpu();
24920157f98Sreinoud cpu_softc_t *sc = device_private(ci->ci_dev);
25038365ca3Sjmcneill
25138365ca3Sjmcneill #ifdef CPU_DEBUG
252cc212239Sreinoud thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n",
25338365ca3Sjmcneill oldlwp ? oldlwp->l_name : "none",
2542b1abfc3Sjmcneill oldlwp ? oldlwp->l_proc->p_pid : -1,
2552b1abfc3Sjmcneill oldlwp ? oldlwp->l_lid : -1,
2562b1abfc3Sjmcneill newlwp ? newlwp->l_name : "none",
2572b1abfc3Sjmcneill newlwp ? newlwp->l_proc->p_pid : -1,
2582b1abfc3Sjmcneill newlwp ? newlwp->l_lid : -1);
25938365ca3Sjmcneill if (oldpcb) {
260cc212239Sreinoud thunk_printf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, "
261b19ccb81Sreinoud "uc_stack.ss_size=%d, l_private %p, uc_mcontext._mc_tlsbase=%p(%s)\n",
26238365ca3Sjmcneill oldpcb->pcb_ucp.uc_link,
26338365ca3Sjmcneill oldpcb->pcb_ucp.uc_stack.ss_sp,
264b19ccb81Sreinoud (int)oldpcb->pcb_ucp.uc_stack.ss_size,
265b19ccb81Sreinoud (void *) oldlwp->l_private,
266b19ccb81Sreinoud (void *) oldpcb->pcb_ucp.uc_mcontext._mc_tlsbase,
267b19ccb81Sreinoud oldpcb->pcb_ucp.uc_flags & _UC_TLSBASE? "ON":"off");
26838365ca3Sjmcneill }
26938365ca3Sjmcneill if (newpcb) {
270b19ccb81Sreinoud thunk_printf_debug(" newpewcb uc_link=%p, uc_stack.ss_sp=%p, "
271b19ccb81Sreinoud "uc_stack.ss_size=%d, l_private %p, uc_mcontext._mc_tlsbase=%p(%s)\n",
27238365ca3Sjmcneill newpcb->pcb_ucp.uc_link,
27338365ca3Sjmcneill newpcb->pcb_ucp.uc_stack.ss_sp,
274b19ccb81Sreinoud (int)newpcb->pcb_ucp.uc_stack.ss_size,
275b19ccb81Sreinoud (void *) newlwp->l_private,
276b19ccb81Sreinoud (void *) newpcb->pcb_ucp.uc_mcontext._mc_tlsbase,
277b19ccb81Sreinoud newpcb->pcb_ucp.uc_flags & _UC_TLSBASE? "ON":"off");
27838365ca3Sjmcneill }
27938365ca3Sjmcneill #endif /* !CPU_DEBUG */
28038365ca3Sjmcneill
28120157f98Sreinoud /* create atomic switcher */
2820767c295Sreinoud KASSERT(newlwp);
28320157f98Sreinoud thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic,
2848caa1870Sreinoud 2, oldlwp, newlwp, NULL, NULL);
2851ea95bd6Sreinoud KASSERT(sc);
2861ea95bd6Sreinoud if (oldpcb) {
28720157f98Sreinoud thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp);
28820157f98Sreinoud /* returns here */
2891ea95bd6Sreinoud } else {
2901ea95bd6Sreinoud thunk_setcontext(&sc->sc_ucp);
2911ea95bd6Sreinoud /* never returns */
29238365ca3Sjmcneill }
293ebe91428Sreinoud
29438365ca3Sjmcneill #ifdef CPU_DEBUG
295cc212239Sreinoud thunk_printf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp);
29638365ca3Sjmcneill #endif
29738365ca3Sjmcneill return ci->ci_stash;
29838365ca3Sjmcneill }
29938365ca3Sjmcneill
30038365ca3Sjmcneill void
cpu_dumpconf(void)30138365ca3Sjmcneill cpu_dumpconf(void)
30238365ca3Sjmcneill {
30338365ca3Sjmcneill #ifdef CPU_DEBUG
304cc212239Sreinoud thunk_printf_debug("cpu_dumpconf\n");
30538365ca3Sjmcneill #endif
30638365ca3Sjmcneill }
30738365ca3Sjmcneill
30838365ca3Sjmcneill void
cpu_signotify(struct lwp * l)30938365ca3Sjmcneill cpu_signotify(struct lwp *l)
31038365ca3Sjmcneill {
31138365ca3Sjmcneill }
31238365ca3Sjmcneill
31338365ca3Sjmcneill void
cpu_getmcontext(struct lwp * l,mcontext_t * mcp,unsigned int * flags)31438365ca3Sjmcneill cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
31538365ca3Sjmcneill {
31642256546Sreinoud struct pcb *pcb = lwp_getpcb(l);
31742256546Sreinoud ucontext_t *ucp = &pcb->pcb_userret_ucp;
31842256546Sreinoud
31938365ca3Sjmcneill #ifdef CPU_DEBUG
320cc212239Sreinoud thunk_printf_debug("cpu_getmcontext\n");
32138365ca3Sjmcneill #endif
32242256546Sreinoud memcpy(mcp, &ucp->uc_mcontext, sizeof(mcontext_t));
323b19ccb81Sreinoud
3242dccb90aSreinoud /* report we have the CPU FPU and TLSBASE registers */
325b19ccb81Sreinoud mcp->_mc_tlsbase = (uintptr_t) l->l_private;
3262dccb90aSreinoud *flags = _UC_CPU | _UC_FPU | _UC_TLSBASE;
327b19ccb81Sreinoud
32842256546Sreinoud return;
32938365ca3Sjmcneill }
33038365ca3Sjmcneill
33138365ca3Sjmcneill int
cpu_mcontext_validate(struct lwp * l,const mcontext_t * mcp)33267d81114Sreinoud cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
33367d81114Sreinoud {
33467d81114Sreinoud /*
33567d81114Sreinoud * can we check here? or should that be done in the target
33667d81114Sreinoud * specific places?
33767d81114Sreinoud */
338b19ccb81Sreinoud /* XXX NO CHECKING! XXX */
339b19ccb81Sreinoud #ifdef CPU_DEBUG
3402dccb90aSreinoud thunk_printf_debug("cpu_mcontext_validate\n");
341b19ccb81Sreinoud #endif
34267d81114Sreinoud return 0;
34367d81114Sreinoud }
34467d81114Sreinoud
34567d81114Sreinoud int
cpu_setmcontext(struct lwp * l,const mcontext_t * mcp,unsigned int flags)34638365ca3Sjmcneill cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
34738365ca3Sjmcneill {
34842256546Sreinoud struct pcb *pcb = lwp_getpcb(l);
34942256546Sreinoud ucontext_t *ucp = &pcb->pcb_userret_ucp;
35042256546Sreinoud
35138365ca3Sjmcneill #ifdef CPU_DEBUG
352cc212239Sreinoud thunk_printf_debug("cpu_setmcontext\n");
35338365ca3Sjmcneill #endif
3548ed4e5c0Sreinoud if ((flags & _UC_CPU) != 0)
355904d0d7dSreinoud memcpy(&ucp->uc_mcontext.__gregs, &mcp->__gregs, sizeof(__gregset_t));
3568ed4e5c0Sreinoud if ((flags & _UC_FPU) != 0)
357904d0d7dSreinoud memcpy(&ucp->uc_mcontext.__fpregs, &mcp->__fpregs, sizeof(__fpregset_t));
3588ed4e5c0Sreinoud if ((flags & _UC_TLSBASE) != 0)
3598ed4e5c0Sreinoud lwp_setprivate(l, (void *) (uintptr_t) mcp->_mc_tlsbase);
360b19ccb81Sreinoud
3618ed4e5c0Sreinoud #if 0
3628ed4e5c0Sreinoud /*
3638ed4e5c0Sreinoud * XXX we ignore the set and clear stack since signals are done
3648ed4e5c0Sreinoud * slightly differently.
3658ed4e5c0Sreinoud */
3668ed4e5c0Sreinoud thunk_printf("%s: flags %x\n", __func__, flags);
3678ed4e5c0Sreinoud mutex_enter(l->l_proc->p_lock);
3688ed4e5c0Sreinoud if (flags & _UC_SETSTACK)
3698ed4e5c0Sreinoud l->l_sigstk.ss_flags |= SS_ONSTACK;
3708ed4e5c0Sreinoud if (flags & _UC_CLRSTACK)
3718ed4e5c0Sreinoud l->l_sigstk.ss_flags &= ~SS_ONSTACK;
3728ed4e5c0Sreinoud mutex_exit(l->l_proc->p_lock);
3738ed4e5c0Sreinoud #endif
3748ed4e5c0Sreinoud
3758ed4e5c0Sreinoud ucp->uc_flags |= (flags & (_UC_CPU | _UC_FPU | _UC_TLSBASE));
376b19ccb81Sreinoud
37738365ca3Sjmcneill return 0;
37838365ca3Sjmcneill }
37938365ca3Sjmcneill
38038365ca3Sjmcneill void
cpu_idle(void)38138365ca3Sjmcneill cpu_idle(void)
38238365ca3Sjmcneill {
38338365ca3Sjmcneill struct cpu_info *ci = curcpu();
38438365ca3Sjmcneill
38538365ca3Sjmcneill if (ci->ci_want_resched)
38638365ca3Sjmcneill return;
38738365ca3Sjmcneill
3880ab0654aSjmcneill thunk_idle();
38938365ca3Sjmcneill }
39038365ca3Sjmcneill
39138365ca3Sjmcneill void
cpu_lwp_free(struct lwp * l,int proc)39238365ca3Sjmcneill cpu_lwp_free(struct lwp *l, int proc)
39338365ca3Sjmcneill {
39438365ca3Sjmcneill #ifdef CPU_DEBUG
395cc212239Sreinoud thunk_printf_debug("cpu_lwp_free (dummy)\n");
39638365ca3Sjmcneill #endif
39738365ca3Sjmcneill }
39838365ca3Sjmcneill
39938365ca3Sjmcneill void
cpu_lwp_free2(struct lwp * l)40038365ca3Sjmcneill cpu_lwp_free2(struct lwp *l)
40138365ca3Sjmcneill {
402448807faSrmind struct pcb *pcb = lwp_getpcb(l);
40338365ca3Sjmcneill
40438365ca3Sjmcneill #ifdef CPU_DEBUG
405cc212239Sreinoud thunk_printf_debug("cpu_lwp_free2\n");
40638365ca3Sjmcneill #endif
40738365ca3Sjmcneill
40838365ca3Sjmcneill if (pcb == NULL)
40938365ca3Sjmcneill return;
410cd980be6Sreinoud /* XXX nothing to do? */
41138365ca3Sjmcneill }
41238365ca3Sjmcneill
41338365ca3Sjmcneill static void
cpu_lwp_trampoline(ucontext_t * ucp,void (* func)(void *),void * arg)4142041dd27Sreinoud cpu_lwp_trampoline(ucontext_t *ucp, void (*func)(void *), void *arg)
41538365ca3Sjmcneill {
4163ef22b9aSreinoud #ifdef CPU_DEBUG
417cc212239Sreinoud thunk_printf_debug("cpu_lwp_trampoline called with func %p, arg %p\n", (void *) func, arg);
4183ef22b9aSreinoud #endif
4192041dd27Sreinoud /* init lwp */
42038365ca3Sjmcneill lwp_startup(curcpu()->ci_stash, curlwp);
4212041dd27Sreinoud
42252976d25Sreinoud /* actual jump */
4238caa1870Sreinoud thunk_makecontext(ucp, (void (*)(void)) func, 1, arg, NULL, NULL, NULL);
42452976d25Sreinoud thunk_setcontext(ucp);
42538365ca3Sjmcneill }
42638365ca3Sjmcneill
42738365ca3Sjmcneill void
cpu_lwp_fork(struct lwp * l1,struct lwp * l2,void * stack,size_t stacksize,void (* func)(void *),void * arg)42838365ca3Sjmcneill cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
42938365ca3Sjmcneill void (*func)(void *), void *arg)
43038365ca3Sjmcneill {
431e5e1d509Sreinoud struct pcb *pcb1 = lwp_getpcb(l1);
432e5e1d509Sreinoud struct pcb *pcb2 = lwp_getpcb(l2);
43338365ca3Sjmcneill
43438365ca3Sjmcneill #ifdef CPU_DEBUG
435cc212239Sreinoud thunk_printf_debug("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n",
43638365ca3Sjmcneill l1 ? l1->l_name : "none", l1,
43738365ca3Sjmcneill l2 ? l2->l_name : "none", l2,
43838365ca3Sjmcneill stack, (int)stacksize);
43938365ca3Sjmcneill #endif
44052976d25Sreinoud if (stack)
44152976d25Sreinoud panic("%s: stack passed, can't handle\n", __func__);
44252976d25Sreinoud
443e5e1d509Sreinoud /* copy the PCB and its switchframes from parent */
444e5e1d509Sreinoud memcpy(pcb2, pcb1, sizeof(struct pcb));
445e5e1d509Sreinoud
446b19ccb81Sreinoud /* refresh context, XXX needed? */
447e5e1d509Sreinoud if (thunk_getcontext(&pcb2->pcb_ucp))
44828828399Sjmcneill panic("getcontext failed");
449e5e1d509Sreinoud
450b19ccb81Sreinoud /* set up for TLS */
451b19ccb81Sreinoud pcb2->pcb_ucp.uc_mcontext._mc_tlsbase = (intptr_t) l2->l_private;
452b19ccb81Sreinoud pcb2->pcb_ucp.uc_flags |= _UC_TLSBASE;
453b19ccb81Sreinoud
454cd980be6Sreinoud /* recalculate the system stack top */
455cd980be6Sreinoud pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE;
456cd980be6Sreinoud
457cd980be6Sreinoud /* get l2 its own stack */
458cd980be6Sreinoud pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack;
459cd980be6Sreinoud pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack;
460c3c6935bSreinoud pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp;
4611ea95bd6Sreinoud
4621ea95bd6Sreinoud thunk_sigemptyset(&pcb2->pcb_ucp.uc_sigmask);
463b19ccb81Sreinoud
46452976d25Sreinoud thunk_makecontext(&pcb2->pcb_ucp,
46552976d25Sreinoud (void (*)(void)) cpu_lwp_trampoline,
4668caa1870Sreinoud 3, &pcb2->pcb_ucp, func, arg, NULL);
46738365ca3Sjmcneill }
46838365ca3Sjmcneill
46938365ca3Sjmcneill void
cpu_initclocks(void)47038365ca3Sjmcneill cpu_initclocks(void)
47138365ca3Sjmcneill {
472d27fbb9fSjmcneill extern timer_t clock_timerid;
4733dae8a59Sjmcneill
474d27fbb9fSjmcneill thunk_timer_start(clock_timerid, HZ);
47538365ca3Sjmcneill }
47638365ca3Sjmcneill
47738365ca3Sjmcneill void
cpu_startup(void)47838365ca3Sjmcneill cpu_startup(void)
47938365ca3Sjmcneill {
4800c0ccce6Sreinoud vaddr_t minaddr, maxaddr;
481cd980be6Sreinoud size_t msgbufsize = 32 * 1024;
482c3c6935bSreinoud
4830c0ccce6Sreinoud /* get ourself a message buffer */
484e5e51288Sjmcneill um_msgbuf = kmem_zalloc(msgbufsize, KM_SLEEP);
485e5e51288Sjmcneill initmsgbuf(um_msgbuf, msgbufsize);
48605f1b5eaSjmcneill
4870c0ccce6Sreinoud /* allocate a submap for physio, 1Mb enough? */
4880c0ccce6Sreinoud minaddr = 0;
4890c0ccce6Sreinoud phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
4900c0ccce6Sreinoud 1024 * 1024, 0, false, NULL);
4910c0ccce6Sreinoud
4920c0ccce6Sreinoud /* say hi! */
493df5e2583Sjmcneill banner();
49411b9552bSjmcneill
4950c0ccce6Sreinoud /* init lwp0 */
49611b9552bSjmcneill memset(&lwp0pcb, 0, sizeof(lwp0pcb));
497cd980be6Sreinoud thunk_getcontext(&lwp0pcb.pcb_ucp);
4981ea95bd6Sreinoud thunk_sigemptyset(&lwp0pcb.pcb_ucp.uc_sigmask);
49920157f98Sreinoud lwp0pcb.pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK;
5001ea95bd6Sreinoud
50111b9552bSjmcneill uvm_lwp_setuarea(&lwp0, (vaddr_t) &lwp0pcb);
502c3c6935bSreinoud memcpy(&lwp0pcb.pcb_userret_ucp, &lwp0pcb.pcb_ucp, sizeof(ucontext_t));
503c3c6935bSreinoud
504cd980be6Sreinoud /* set stack top */
505cd980be6Sreinoud lwp0pcb.sys_stack_top = lwp0pcb.sys_stack + TRAPSTACKSIZE;
50638365ca3Sjmcneill }
50738365ca3Sjmcneill
50838365ca3Sjmcneill void
cpu_rootconf(void)50938365ca3Sjmcneill cpu_rootconf(void)
51038365ca3Sjmcneill {
511a60846baSjmcneill extern char *usermode_root_device;
512e69482d4Sjoerg device_t rdev;
51338365ca3Sjmcneill
514a60846baSjmcneill if (usermode_root_device != NULL) {
515a60846baSjmcneill rdev = device_find_by_xname(usermode_root_device);
516a60846baSjmcneill } else {
517ce6e29d2Sjmcneill rdev = device_find_by_xname("ld0");
518ce6e29d2Sjmcneill if (rdev == NULL)
519e69482d4Sjoerg rdev = device_find_by_xname("md0");
520a60846baSjmcneill }
52138365ca3Sjmcneill
522ce6e29d2Sjmcneill aprint_normal("boot device: %s\n",
523ce6e29d2Sjmcneill rdev ? device_xname(rdev) : "<unknown>");
5248ce44338Smlelstv booted_device = rdev;
5258ce44338Smlelstv rootconf();
52638365ca3Sjmcneill }
52738365ca3Sjmcneill
52838365ca3Sjmcneill bool
cpu_intr_p(void)52938365ca3Sjmcneill cpu_intr_p(void)
53038365ca3Sjmcneill {
531df5e2583Sjmcneill int idepth;
532*a355028fSad long pctr;
5337ce773dbSad lwp_t *l;
534df5e2583Sjmcneill
5357ce773dbSad l = curlwp;
5367ce773dbSad do {
537*a355028fSad pctr = lwp_pctr();
5387ce773dbSad idepth = l->l_cpu->ci_idepth;
539*a355028fSad } while (__predict_false(pctr != lwp_pctr()));
540df5e2583Sjmcneill
5417ce773dbSad return idepth >= 0;
54238365ca3Sjmcneill }
543