xref: /netbsd-src/sys/arch/usermode/dev/cpu.c (revision a355028fa4f1eaedfae402807330fbc7bf5e9102)
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