Home | History | Annotate | Line # | Download | only in dev
cpu.c revision 1.1
      1 /* $NetBSD: cpu.c,v 1.1 2007/12/29 14:38:31 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2007 Jared D. McNeill <jmcneill (at) 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  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *        This product includes software developed by Jared D. McNeill.
     18  * 4. Neither the name of The NetBSD Foundation nor the names of its
     19  *    contributors may be used to endorse or promote products derived
     20  *    from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32  * POSSIBILITY OF SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.1 2007/12/29 14:38:31 jmcneill Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/conf.h>
     40 #include <sys/proc.h>
     41 #include <sys/user.h>
     42 #include <sys/systm.h>
     43 #include <sys/device.h>
     44 #include <sys/reboot.h>
     45 #include <sys/lwp.h>
     46 #include <sys/cpu.h>
     47 #include <sys/mbuf.h>
     48 
     49 #include <dev/cons.h>
     50 
     51 #include <machine/cpu.h>
     52 #include <machine/mainbus.h>
     53 
     54 #include <uvm/uvm_extern.h>
     55 #include <uvm/uvm_page.h>
     56 
     57 /* #define CPU_DEBUG */
     58 
     59 static int	cpu_match(device_t, cfdata_t, void *);
     60 static void	cpu_attach(device_t, device_t, void *);
     61 
     62 struct cpu_info cpu_info_primary;
     63 char cpu_model[48] = "virtual processor";
     64 
     65 typedef struct cpu_softc {
     66 	device_t	sc_dev;
     67 	struct cpu_info	*sc_ci;
     68 } cpu_softc_t;
     69 
     70 CFATTACH_DECL_NEW(cpu, sizeof(cpu_softc_t), cpu_match, cpu_attach, NULL, NULL);
     71 
     72 static int
     73 cpu_match(device_t parent, cfdata_t match, void *opaque)
     74 {
     75 	struct thunkbus_attach_args *taa = opaque;
     76 
     77 	if (taa->taa_type != THUNKBUS_TYPE_CPU)
     78 		return 0;
     79 
     80 	return 1;
     81 }
     82 
     83 static void
     84 cpu_attach(device_t parent, device_t self, void *opaque)
     85 {
     86 	cpu_softc_t *sc = device_private(self);
     87 
     88 	aprint_naive("\n");
     89 	aprint_normal("\n");
     90 
     91 	sc->sc_dev = self;
     92 	sc->sc_ci = &cpu_info_primary;
     93 	sc->sc_ci->ci_dev = 0;
     94 	sc->sc_ci->ci_self = &cpu_info_primary;
     95 #if notyet
     96 	sc->sc_ci->ci_curlwp = &lwp0;
     97 #endif
     98 }
     99 
    100 void
    101 cpu_configure(void)
    102 {
    103 	if (config_rootfound("mainbus", NULL) == NULL)
    104 		panic("configure: mainbus not configured");
    105 
    106 	spl0();
    107 }
    108 
    109 void
    110 cpu_reboot(int howto, char *bootstr)
    111 {
    112 	extern void exit(int);
    113 	extern void abort(void);
    114 
    115 	splhigh();
    116 
    117 	if ((howto & RB_POWERDOWN) == RB_POWERDOWN)
    118 		exit(0);
    119 
    120 	if (howto & RB_HALT) {
    121 		printf("\n");
    122 		printf("The operating system has halted.\n");
    123 		printf("Please press any key to reboot.\n\n");
    124 		cnpollc(1);
    125 		cngetc();
    126 		cnpollc(0);
    127 	}
    128 
    129 	printf("rebooting...\n");
    130 
    131 	/*
    132 	 * XXXJDM If we've panic'd, make sure we dump a core
    133 	 */
    134 	abort();
    135 
    136 	/* NOTREACHED */
    137 }
    138 
    139 void
    140 cpu_need_resched(struct cpu_info *ci, int flags)
    141 {
    142 	ci->ci_want_resched = 1;
    143 }
    144 
    145 void
    146 cpu_need_proftick(struct lwp *l)
    147 {
    148 }
    149 
    150 lwp_t *
    151 cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
    152 {
    153 	extern int errno;
    154 	struct pcb *oldpcb = (struct pcb *)(oldlwp ? oldlwp->l_addr : NULL);
    155 	struct pcb *newpcb = (struct pcb *)newlwp->l_addr;
    156 	struct cpu_info *ci = curcpu();
    157 
    158 #ifdef CPU_DEBUG
    159 	printf("cpu_switchto [%s] -> [%s]\n",
    160 	    oldlwp ? oldlwp->l_name : "none",
    161 	    newlwp ? newlwp->l_name : "none");
    162 	if (oldpcb) {
    163 		printf("    oldpcb uc_link=%p, uc_stack.ss_sp=%p, "
    164 		    "uc_stack.ss_size=%d\n",
    165 		    oldpcb->pcb_ucp.uc_link,
    166 		    oldpcb->pcb_ucp.uc_stack.ss_sp,
    167 		    (int)oldpcb->pcb_ucp.uc_stack.ss_size);
    168 	}
    169 	if (newpcb) {
    170 		printf("    newpcb uc_link=%p, uc_stack.ss_sp=%p, "
    171 		    "uc_stack.ss_size=%d\n",
    172 		    newpcb->pcb_ucp.uc_link,
    173 		    newpcb->pcb_ucp.uc_stack.ss_sp,
    174 		    (int)newpcb->pcb_ucp.uc_stack.ss_size);
    175 	}
    176 #endif /* !CPU_DEBUG */
    177 
    178 	ci->ci_stash = oldlwp;
    179 	curlwp = newlwp;
    180 	if (oldpcb) {
    181 		if (swapcontext(&oldpcb->pcb_ucp, &newpcb->pcb_ucp))
    182 			panic("swapcontext failed: %d", errno);
    183 	} else {
    184 		if (setcontext(&newpcb->pcb_ucp))
    185 			panic("setcontext failed: %d", errno);
    186 	}
    187 
    188 #ifdef CPU_DEBUG
    189 	printf("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp);
    190 #endif
    191 	return ci->ci_stash;
    192 }
    193 
    194 void
    195 cpu_dumpconf(void)
    196 {
    197 #ifdef CPU_DEBUG
    198 	printf("cpu_dumpconf\n");
    199 #endif
    200 }
    201 
    202 void
    203 cpu_signotify(struct lwp *l)
    204 {
    205 #ifdef CPU_DEBUG
    206 	printf("cpu_signotify\n");
    207 #endif
    208 }
    209 
    210 void
    211 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
    212 {
    213 #ifdef CPU_DEBUG
    214 	printf("cpu_getmcontext\n");
    215 #endif
    216 }
    217 
    218 int
    219 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
    220 {
    221 #ifdef CPU_DEBUG
    222 	printf("cpu_setmcontext\n");
    223 #endif
    224 	return 0;
    225 }
    226 
    227 void
    228 cpu_idle(void)
    229 {
    230 	extern int usleep(useconds_t);
    231 	struct cpu_info *ci = curcpu();
    232 
    233 	if (ci->ci_want_resched)
    234 		return;
    235 
    236 #if notyet
    237 	usleep(10000);
    238 #endif
    239 }
    240 
    241 void
    242 cpu_lwp_free(struct lwp *l, int proc)
    243 {
    244 #ifdef CPU_DEBUG
    245 	printf("cpu_lwp_free\n");
    246 #endif
    247 }
    248 
    249 void
    250 cpu_lwp_free2(struct lwp *l)
    251 {
    252 	struct pcb *pcb = (struct pcb *)l->l_addr;
    253 
    254 #ifdef CPU_DEBUG
    255 	printf("cpu_lwp_free2\n");
    256 #endif
    257 
    258 	if (pcb == NULL)
    259 		return;
    260 
    261 	if (pcb->pcb_needfree) {
    262 		free(pcb->pcb_ucp.uc_stack.ss_sp, M_TEMP);
    263 		pcb->pcb_ucp.uc_stack.ss_sp = NULL;
    264 		pcb->pcb_ucp.uc_stack.ss_size = 0;
    265 		pcb->pcb_needfree = false;
    266 	}
    267 }
    268 
    269 static void
    270 cpu_lwp_trampoline(void (*func)(void *), void *arg)
    271 {
    272 	lwp_startup(curcpu()->ci_stash, curlwp);
    273 
    274 	func(arg);
    275 }
    276 
    277 void
    278 cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
    279     void (*func)(void *), void *arg)
    280 {
    281 	extern int errno;
    282 	struct pcb *pcb = (struct pcb *)l2->l_addr;
    283 
    284 #ifdef CPU_DEBUG
    285 	printf("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n",
    286 	    l1 ? l1->l_name : "none", l1,
    287 	    l2 ? l2->l_name : "none", l2,
    288 	    stack, (int)stacksize);
    289 #endif
    290 
    291 	/* XXXJDM */
    292 	if (stack == NULL) {
    293 		stack = malloc(PAGE_SIZE, M_TEMP, M_NOWAIT);
    294 		stacksize = PAGE_SIZE;
    295 		pcb->pcb_needfree = true;
    296 	} else
    297 		pcb->pcb_needfree = false;
    298 
    299 	if (getcontext(&pcb->pcb_ucp))
    300 		panic("getcontext failed: %d", errno);
    301 	pcb->pcb_ucp.uc_stack.ss_sp = stack;
    302 	pcb->pcb_ucp.uc_stack.ss_size = stacksize;
    303 	pcb->pcb_ucp.uc_link = NULL;
    304 	pcb->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU;
    305 	makecontext(&pcb->pcb_ucp, (void (*)(void))cpu_lwp_trampoline,
    306 	    2, func, arg);
    307 }
    308 
    309 void
    310 cpu_initclocks(void)
    311 {
    312 }
    313 
    314 void
    315 cpu_startup(void)
    316 {
    317 	extern int physmem;
    318 	extern struct vm_map *mb_map;
    319 	vaddr_t minaddr, maxaddr;
    320 	char pbuf[9];
    321 
    322 	printf("%s%s", copyright, version);
    323 	format_bytes(pbuf, sizeof(pbuf), ptoa(physmem));
    324 	printf("total memory = %s\n", pbuf);
    325 
    326 	minaddr = 0;
    327 	mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
    328 	    nmbclusters * mclbytes, VM_MAP_INTRSAFE, false, NULL);
    329 
    330 	format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
    331 	printf("avail memory = %s\n", pbuf);
    332 }
    333 
    334 void
    335 cpu_rootconf(void)
    336 {
    337 	device_t curdev, rdev = NULL;
    338 
    339 	TAILQ_FOREACH(curdev, &alldevs, dv_list)
    340 		if (strcmp(device_xname(curdev), "md0") == 0) {
    341 			rdev = curdev;
    342 			break;
    343 		}
    344 
    345 	setroot(rdev, 0);
    346 }
    347 
    348 bool
    349 cpu_intr_p(void)
    350 {
    351 	printf("cpu_intr_p\n");
    352 	return false;
    353 }
    354