1 /* $NetBSD: cpu.c,v 1.7 2010/02/08 19:02:32 joerg Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 15 * 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. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.7 2010/02/08 19:02:32 joerg Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/conf.h> 34 #include <sys/proc.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #include <sys/reboot.h> 38 #include <sys/lwp.h> 39 #include <sys/cpu.h> 40 #include <sys/mbuf.h> 41 42 #include <dev/cons.h> 43 44 #include <machine/cpu.h> 45 #include <machine/mainbus.h> 46 47 #include <uvm/uvm_extern.h> 48 #include <uvm/uvm_page.h> 49 50 /* #define CPU_DEBUG */ 51 52 static int cpu_match(device_t, cfdata_t, void *); 53 static void cpu_attach(device_t, device_t, void *); 54 55 struct cpu_info cpu_info_primary; 56 char cpu_model[48] = "virtual processor"; 57 58 typedef struct cpu_softc { 59 device_t sc_dev; 60 struct cpu_info *sc_ci; 61 } cpu_softc_t; 62 63 CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL); 64 65 static int 66 cpu_match(device_t parent, cfdata_t match, void *opaque) 67 { 68 struct thunkbus_attach_args *taa = opaque; 69 70 if (taa->taa_type != THUNKBUS_TYPE_CPU) 71 return 0; 72 73 return 1; 74 } 75 76 static void 77 cpu_attach(device_t parent, device_t self, void *opaque) 78 { 79 cpu_softc_t *sc = device_private(self); 80 81 aprint_naive("\n"); 82 aprint_normal("\n"); 83 84 sc->sc_dev = self; 85 sc->sc_ci = &cpu_info_primary; 86 sc->sc_ci->ci_dev = 0; 87 sc->sc_ci->ci_self = &cpu_info_primary; 88 #if notyet 89 sc->sc_ci->ci_curlwp = &lwp0; 90 #endif 91 } 92 93 void 94 cpu_configure(void) 95 { 96 if (config_rootfound("mainbus", NULL) == NULL) 97 panic("configure: mainbus not configured"); 98 99 spl0(); 100 } 101 102 void 103 cpu_reboot(int howto, char *bootstr) 104 { 105 extern void exit(int); 106 extern void abort(void); 107 108 splhigh(); 109 110 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 111 exit(0); 112 113 if (howto & RB_HALT) { 114 printf("\n"); 115 printf("The operating system has halted.\n"); 116 printf("Please press any key to reboot.\n\n"); 117 cnpollc(1); 118 cngetc(); 119 cnpollc(0); 120 } 121 122 printf("rebooting...\n"); 123 124 /* 125 * XXXJDM If we've panic'd, make sure we dump a core 126 */ 127 abort(); 128 129 /* NOTREACHED */ 130 } 131 132 void 133 cpu_need_resched(struct cpu_info *ci, int flags) 134 { 135 ci->ci_want_resched = 1; 136 } 137 138 void 139 cpu_need_proftick(struct lwp *l) 140 { 141 } 142 143 lwp_t * 144 cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning) 145 { 146 extern int errno; 147 struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL; 148 struct pcb *newpcb = lwp_getpcb(newlwp); 149 struct cpu_info *ci = curcpu(); 150 151 #ifdef CPU_DEBUG 152 printf("cpu_switchto [%s] -> [%s]\n", 153 oldlwp ? oldlwp->l_name : "none", 154 newlwp ? newlwp->l_name : "none"); 155 if (oldpcb) { 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); 161 } 162 if (newpcb) { 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); 168 } 169 #endif /* !CPU_DEBUG */ 170 171 ci->ci_stash = oldlwp; 172 curlwp = newlwp; 173 if (oldpcb) { 174 if (swapcontext(&oldpcb->pcb_ucp, &newpcb->pcb_ucp)) 175 panic("swapcontext failed: %d", errno); 176 } else { 177 if (setcontext(&newpcb->pcb_ucp)) 178 panic("setcontext failed: %d", errno); 179 } 180 181 #ifdef CPU_DEBUG 182 printf("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); 183 #endif 184 return ci->ci_stash; 185 } 186 187 void 188 cpu_dumpconf(void) 189 { 190 #ifdef CPU_DEBUG 191 printf("cpu_dumpconf\n"); 192 #endif 193 } 194 195 void 196 cpu_signotify(struct lwp *l) 197 { 198 #ifdef CPU_DEBUG 199 printf("cpu_signotify\n"); 200 #endif 201 } 202 203 void 204 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) 205 { 206 #ifdef CPU_DEBUG 207 printf("cpu_getmcontext\n"); 208 #endif 209 } 210 211 int 212 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) 213 { 214 #ifdef CPU_DEBUG 215 printf("cpu_setmcontext\n"); 216 #endif 217 return 0; 218 } 219 220 void 221 cpu_idle(void) 222 { 223 extern int usleep(useconds_t); 224 struct cpu_info *ci = curcpu(); 225 226 if (ci->ci_want_resched) 227 return; 228 229 #if notyet 230 usleep(10000); 231 #endif 232 } 233 234 void 235 cpu_lwp_free(struct lwp *l, int proc) 236 { 237 #ifdef CPU_DEBUG 238 printf("cpu_lwp_free\n"); 239 #endif 240 } 241 242 void 243 cpu_lwp_free2(struct lwp *l) 244 { 245 struct pcb *pcb = lwp_getpcb(l); 246 247 #ifdef CPU_DEBUG 248 printf("cpu_lwp_free2\n"); 249 #endif 250 251 if (pcb == NULL) 252 return; 253 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; 259 } 260 } 261 262 static void 263 cpu_lwp_trampoline(void (*func)(void *), void *arg) 264 { 265 lwp_startup(curcpu()->ci_stash, curlwp); 266 267 func(arg); 268 } 269 270 void 271 cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, 272 void (*func)(void *), void *arg) 273 { 274 extern int errno; 275 struct pcb *pcb = lwp_getpcb(l2); 276 277 #ifdef CPU_DEBUG 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); 282 #endif 283 284 /* XXXJDM */ 285 if (stack == NULL) { 286 stack = malloc(PAGE_SIZE, M_TEMP, M_NOWAIT); 287 stacksize = PAGE_SIZE; 288 pcb->pcb_needfree = true; 289 } else 290 pcb->pcb_needfree = false; 291 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, 299 2, func, arg); 300 } 301 302 void 303 cpu_initclocks(void) 304 { 305 } 306 307 void 308 cpu_startup(void) 309 { 310 char pbuf[9]; 311 312 printf("%s%s", copyright, version); 313 format_bytes(pbuf, sizeof(pbuf), ptoa(physmem)); 314 printf("total memory = %s\n", pbuf); 315 316 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 317 printf("avail memory = %s\n", pbuf); 318 } 319 320 void 321 cpu_rootconf(void) 322 { 323 device_t rdev; 324 325 rdev = device_find_by_xname("md0"); 326 327 setroot(rdev, 0); 328 } 329 330 bool 331 cpu_intr_p(void) 332 { 333 printf("cpu_intr_p\n"); 334 return false; 335 } 336