locore2.c revision 1.6
1/* $NetBSD: locore2.c,v 1.6 1997/01/25 21:47:44 gwr Exp $ */ 2 3/*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Gordon W. Ross and Jeremy Cooper. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/proc.h> 42#include <sys/reboot.h> 43#include <sys/user.h> 44#include <sys/exec_aout.h> 45 46#include <vm/vm.h> 47 48#include <machine/cpu.h> 49#include <machine/db_machdep.h> 50#include <machine/dvma.h> 51#include <machine/mon.h> 52#include <machine/pte.h> 53#include <machine/pmap.h> 54#include <machine/idprom.h> 55#include <machine/obio.h> 56#include <machine/machdep.h> 57 58#include <sun3/sun3/sunmon.h> 59#include <sun3/sun3/interreg.h> 60#include <sun3/sun3/vector.h> 61 62/* This is defined in locore.s */ 63extern char kernel_text[]; 64 65/* These are defined by the linker */ 66extern char etext[], edata[], end[]; 67char *esym; /* DDB */ 68 69/* 70 * Now our own stuff. 71 */ 72int boothowto = RB_KDB; /* XXX - For now... */ 73int cold = 1; 74 75unsigned char cpu_machine_id = 0; 76char *cpu_string = NULL; 77int cpu_has_vme = 0; 78int has_iocache = 0; 79 80int msgbufmapped = 0; 81struct msgbuf *msgbufp = NULL; 82 83struct user *proc0paddr; /* proc[0] pcb address (u-area VA) */ 84extern struct pcb *curpcb; 85 86/* First C code called by locore.s */ 87void _bootstrap __P((struct exec)); 88 89static void _verify_hardware __P((void)); 90static void _vm_init __P((struct exec *kehp)); 91 92 93#if defined(DDB) && !defined(SYMTAB_SPACE) 94static void _save_symtab __P((struct exec *kehp)); 95 96/* 97 * Preserve DDB symbols and strings by setting esym. 98 */ 99static void 100_save_symtab(kehp) 101 struct exec *kehp; /* kernel exec header */ 102{ 103 int x, *symsz, *strsz; 104 char *endp; 105 char *errdesc = "?"; 106 107 /* 108 * First, sanity-check the exec header. 109 */ 110 mon_printf("_save_symtab: "); 111 if ((kehp->a_midmag & 0xFFF0) != 0x0100) { 112 errdesc = "magic"; 113 goto err; 114 } 115 /* Boundary between text and data varries a little. */ 116 x = kehp->a_text + kehp->a_data; 117 if (x != (edata - kernel_text)) { 118 errdesc = "a_text+a_data"; 119 goto err; 120 } 121 if (kehp->a_bss != (end - edata)) { 122 errdesc = "a_bss"; 123 goto err; 124 } 125 if (kehp->a_entry != (int)kernel_text) { 126 errdesc = "a_entry"; 127 goto err; 128 } 129 if (kehp->a_trsize || kehp->a_drsize) { 130 errdesc = "a_Xrsize"; 131 goto err; 132 } 133 /* The exec header looks OK... */ 134 135 /* Check the symtab length word. */ 136 endp = end; 137 symsz = (int*)endp; 138 if (kehp->a_syms != *symsz) { 139 errdesc = "a_syms"; 140 goto err; 141 } 142 endp += sizeof(int); /* past length word */ 143 endp += *symsz; /* past nlist array */ 144 145 /* Check the string table length. */ 146 strsz = (int*)endp; 147 if ((*strsz < 4) || (*strsz > 0x80000)) { 148 errdesc = "strsize"; 149 goto err; 150 } 151 152 /* Success! We have a valid symbol table! */ 153 endp += *strsz; /* past strings */ 154 esym = endp; 155 mon_printf(" found %d + %d\n", *symsz, *strsz); 156 return; 157 158 err: 159 mon_printf(" no symbols (bad %s)\n", errdesc); 160} 161#endif /* DDB && !SYMTAB_SPACE */ 162 163/* 164 * This function is called from _bootstrap() to initialize 165 * pre-vm-sytem virtual memory. All this really does is to 166 * set virtual_avail to the first page following preloaded 167 * data (i.e. the kernel and its symbol table) and special 168 * things that may be needed very early (proc0 upages). 169 * Once that is done, pmap_bootstrap() is called to do the 170 * usual preparations for our use of the MMU. 171 */ 172static void 173_vm_init(kehp) 174 struct exec *kehp; /* kernel exec header */ 175{ 176 vm_offset_t nextva; 177 178 /* 179 * First, reserve our symbol table which might have been 180 * loaded after our BSS area by the boot loader. However, 181 * if DDB is not part of this kernel, ignore the symbols. 182 */ 183 esym = end; 184#if defined(DDB) && !defined(SYMTAB_SPACE) 185 /* This will advance esym past the symbols. */ 186 _save_symtab(kehp); 187#endif 188 189 /* 190 * Steal some special-purpose, already mapped pages. 191 * Note: msgbuf is setup in machdep.c:cpu_startup() 192 */ 193 nextva = sun3x_round_page(esym); 194 195 /* 196 * Setup the u-area pages (stack, etc.) for proc0. 197 * This is done very early (here) to make sure the 198 * fault handler works in case we hit an early bug. 199 * (The fault handler may reference proc0 stuff.) 200 */ 201 proc0paddr = (struct user *) nextva; 202 nextva += USPACE; 203 bzero((caddr_t)proc0paddr, USPACE); 204 proc0.p_addr = proc0paddr; 205 206 /* 207 * Now that proc0 exists, make it the "current" one. 208 */ 209 curproc = &proc0; 210 curpcb = &proc0paddr->u_pcb; 211 212 /* 213 * Call pmap_bootstrap() so that we may begin using 214 * pmap_enter_kernel() and pmap_bootstrap_alloc(). 215 */ 216 pmap_bootstrap(nextva); 217} 218 219 220/* 221 * XXX - Should empirically estimate the divisor... 222 * Note that the value of delay_divisor is roughly 223 * 2048 / cpuclock (where cpuclock is in MHz). 224 */ 225int delay_divisor = 82; /* assume the fastest (3/260) */ 226 227static void 228_verify_hardware() 229{ 230 unsigned char machtype; 231 232 machtype = identity_prom.idp_machtype; 233 if ((machtype & CPU_ARCH_MASK) != SUN3X_ARCH) { 234 mon_printf("not a sun3x?\n"); 235 sunmon_abort(); 236 } 237 238 cpu_machine_id = machtype & SUN3X_IMPL_MASK; 239 switch (cpu_machine_id) { 240 241 case SUN3X_MACH_80 : 242 cpu_string = "80"; 243 delay_divisor = 102; /* 20 MHz ? XXX */ 244 cpu_has_vme = FALSE; 245 break; 246 247 case SUN3X_MACH_470: 248 cpu_string = "470"; 249 delay_divisor = 82; /* 25 MHz ? XXX */ 250 cpu_has_vme = TRUE; 251 break; 252 253 default: 254 mon_printf("unknown sun3x model\n"); 255 sunmon_abort(); 256 } 257} 258 259 260/* 261 * This is called from locore.s just after the kernel is remapped 262 * to its proper address, but before the call to main(). The work 263 * done here corresponds to various things done in locore.s on the 264 * hp300 port (and other m68k) but which we prefer to do in C code. 265 * Also do setup specific to the Sun PROM monitor and IDPROM here. 266 */ 267void 268_bootstrap(keh) 269 struct exec keh; /* kernel exec header */ 270{ 271 272 /* First, Clear BSS. */ 273 bzero(edata, end - edata); 274 275 /* set v_handler, get boothowto */ 276 sunmon_init(); 277 278 /* Find devices we need early (like the IDPROM). */ 279 obio_init(); 280 281 /* Note: must come after obio_init (for IDPROM). */ 282 _verify_hardware(); /* get CPU type, etc. */ 283 284 /* handle kernel mapping, pmap_bootstrap(), etc. */ 285 _vm_init(&keh); 286 287 /* 288 * Point interrupts/exceptions to our vector table. 289 * (Until now, we use the one setup by the PROM.) 290 * 291 * This is done after obio_init() / intreg_init() finds 292 * the interrupt register and disables the NMI clock so 293 * it will not cause "spurrious level 7" complaints. 294 */ 295 setvbr((void **)vector_table); 296 297 /* Interrupts are enabled later, after autoconfig. */ 298} 299