1 /* $NetBSD: cpu.c,v 1.5 2009/11/21 05:54:04 rmind Exp $ */
4 * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
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
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.5 2009/11/21 05:54:04 rmind Exp $");
32 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/reboot.h>
44 #include <machine/cpu.h>
45 #include <machine/mainbus.h>
47 #include <uvm/uvm_extern.h>
48 #include <uvm/uvm_page.h>
50 /* #define CPU_DEBUG */
52 static int cpu_match(device_t
, cfdata_t
, void *);
53 static void cpu_attach(device_t
, device_t
, void *);
55 struct cpu_info cpu_info_primary
;
56 char cpu_model
[48] = "virtual processor";
58 typedef struct cpu_softc
{
60 struct cpu_info
*sc_ci
;
63 CFATTACH_DECL_NEW(cpu
, sizeof(cpu_softc_t
), cpu_match
, cpu_attach
, NULL
, NULL
);
66 cpu_match(device_t parent
, cfdata_t match
, void *opaque
)
68 struct thunkbus_attach_args
*taa
= opaque
;
70 if (taa
->taa_type
!= THUNKBUS_TYPE_CPU
)
77 cpu_attach(device_t parent
, device_t self
, void *opaque
)
79 cpu_softc_t
*sc
= device_private(self
);
85 sc
->sc_ci
= &cpu_info_primary
;
86 sc
->sc_ci
->ci_dev
= 0;
87 sc
->sc_ci
->ci_self
= &cpu_info_primary
;
89 sc
->sc_ci
->ci_curlwp
= &lwp0
;
96 if (config_rootfound("mainbus", NULL
) == NULL
)
97 panic("configure: mainbus not configured");
103 cpu_reboot(int howto
, char *bootstr
)
105 extern void exit(int);
106 extern void abort(void);
110 if ((howto
& RB_POWERDOWN
) == RB_POWERDOWN
)
113 if (howto
& RB_HALT
) {
115 printf("The operating system has halted.\n");
116 printf("Please press any key to reboot.\n\n");
122 printf("rebooting...\n");
125 * XXXJDM If we've panic'd, make sure we dump a core
133 cpu_need_resched(struct cpu_info
*ci
, int flags
)
135 ci
->ci_want_resched
= 1;
139 cpu_need_proftick(struct lwp
*l
)
144 cpu_switchto(lwp_t
*oldlwp
, lwp_t
*newlwp
, bool returning
)
147 struct pcb
*oldpcb
= oldlwp
? lwp_getpcb(oldlwp
) : NULL
;
148 struct pcb
*newpcb
= lwp_getpcb(newlwp
);
149 struct cpu_info
*ci
= curcpu();
152 printf("cpu_switchto [%s] -> [%s]\n",
153 oldlwp
? oldlwp
->l_name
: "none",
154 newlwp
? newlwp
->l_name
: "none");
156 printf(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, "
157 "uc_stack.ss_size=%d\n",
158 oldpcb
->pcb_ucp
.uc_link
,
159 oldpcb
->pcb_ucp
.uc_stack
.ss_sp
,
160 (int)oldpcb
->pcb_ucp
.uc_stack
.ss_size
);
163 printf(" newpcb uc_link=%p, uc_stack.ss_sp=%p, "
164 "uc_stack.ss_size=%d\n",
165 newpcb
->pcb_ucp
.uc_link
,
166 newpcb
->pcb_ucp
.uc_stack
.ss_sp
,
167 (int)newpcb
->pcb_ucp
.uc_stack
.ss_size
);
169 #endif /* !CPU_DEBUG */
171 ci
->ci_stash
= oldlwp
;
174 if (swapcontext(&oldpcb
->pcb_ucp
, &newpcb
->pcb_ucp
))
175 panic("swapcontext failed: %d", errno
);
177 if (setcontext(&newpcb
->pcb_ucp
))
178 panic("setcontext failed: %d", errno
);
182 printf("cpu_switchto: returning %p (was %p)\n", ci
->ci_stash
, oldlwp
);
191 printf("cpu_dumpconf\n");
196 cpu_signotify(struct lwp
*l
)
199 printf("cpu_signotify\n");
204 cpu_getmcontext(struct lwp
*l
, mcontext_t
*mcp
, unsigned int *flags
)
207 printf("cpu_getmcontext\n");
212 cpu_setmcontext(struct lwp
*l
, const mcontext_t
*mcp
, unsigned int flags
)
215 printf("cpu_setmcontext\n");
223 extern int usleep(useconds_t
);
224 struct cpu_info
*ci
= curcpu();
226 if (ci
->ci_want_resched
)
235 cpu_lwp_free(struct lwp
*l
, int proc
)
238 printf("cpu_lwp_free\n");
243 cpu_lwp_free2(struct lwp
*l
)
245 struct pcb
*pcb
= lwp_getpcb(l
);
248 printf("cpu_lwp_free2\n");
254 if (pcb
->pcb_needfree
) {
255 free(pcb
->pcb_ucp
.uc_stack
.ss_sp
, M_TEMP
);
256 pcb
->pcb_ucp
.uc_stack
.ss_sp
= NULL
;
257 pcb
->pcb_ucp
.uc_stack
.ss_size
= 0;
258 pcb
->pcb_needfree
= false;
263 cpu_lwp_trampoline(void (*func
)(void *), void *arg
)
265 lwp_startup(curcpu()->ci_stash
, curlwp
);
271 cpu_lwp_fork(struct lwp
*l1
, struct lwp
*l2
, void *stack
, size_t stacksize
,
272 void (*func
)(void *), void *arg
)
275 struct pcb
*pcb
= lwp_getpcb(l2
);
278 printf("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n",
279 l1
? l1
->l_name
: "none", l1
,
280 l2
? l2
->l_name
: "none", l2
,
281 stack
, (int)stacksize
);
286 stack
= malloc(PAGE_SIZE
, M_TEMP
, M_NOWAIT
);
287 stacksize
= PAGE_SIZE
;
288 pcb
->pcb_needfree
= true;
290 pcb
->pcb_needfree
= false;
292 if (getcontext(&pcb
->pcb_ucp
))
293 panic("getcontext failed: %d", errno
);
294 pcb
->pcb_ucp
.uc_stack
.ss_sp
= stack
;
295 pcb
->pcb_ucp
.uc_stack
.ss_size
= stacksize
;
296 pcb
->pcb_ucp
.uc_link
= NULL
;
297 pcb
->pcb_ucp
.uc_flags
= _UC_STACK
| _UC_CPU
;
298 makecontext(&pcb
->pcb_ucp
, (void (*)(void))cpu_lwp_trampoline
,
310 extern struct vm_map
*mb_map
;
311 vaddr_t minaddr
, maxaddr
;
314 printf("%s%s", copyright
, version
);
315 format_bytes(pbuf
, sizeof(pbuf
), ptoa(physmem
));
316 printf("total memory = %s\n", pbuf
);
319 mb_map
= uvm_km_suballoc(kernel_map
, &minaddr
, &maxaddr
,
320 nmbclusters
* mclbytes
, VM_MAP_INTRSAFE
, false, NULL
);
322 format_bytes(pbuf
, sizeof(pbuf
), ptoa(uvmexp
.free
));
323 printf("avail memory = %s\n", pbuf
);
331 rdev
= device_find_by_xname("md0");
339 printf("cpu_intr_p\n");