locore2.c revision 1.8
1/* $NetBSD: locore2.c,v 1.8 1997/02/02 08:38:00 thorpej 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/interreg.h> 59#include <sun3/sun3/vector.h> 60 61/* This is defined in locore.s */ 62extern char kernel_text[]; 63 64/* These are defined by the linker */ 65extern char etext[], edata[], end[]; 66char *esym; /* DDB */ 67 68/* m68k common code needs these */ 69int cputype, mmutype; 70 71/* 72 * Now our own stuff. 73 */ 74int boothowto = RB_KDB; /* XXX - For now... */ 75int cold = 1; 76 77unsigned char cpu_machine_id = 0; 78char *cpu_string = NULL; 79int cpu_has_vme = 0; 80int has_iocache = 0; 81 82int msgbufmapped = 0; 83struct msgbuf *msgbufp = NULL; 84 85struct user *proc0paddr; /* proc[0] pcb address (u-area VA) */ 86extern struct pcb *curpcb; 87 88/* First C code called by locore.s */ 89void _bootstrap __P((struct exec)); 90 91static void _verify_hardware __P((void)); 92static void _vm_init __P((struct exec *kehp)); 93 94 95#if defined(DDB) && !defined(SYMTAB_SPACE) 96static void _save_symtab __P((struct exec *kehp)); 97 98/* 99 * Preserve DDB symbols and strings by setting esym. 100 */ 101static void 102_save_symtab(kehp) 103 struct exec *kehp; /* kernel exec header */ 104{ 105 int x, *symsz, *strsz; 106 char *endp; 107 char *errdesc = "?"; 108 109 /* 110 * First, sanity-check the exec header. 111 */ 112 mon_printf("_save_symtab: "); 113 if ((kehp->a_midmag & 0xFFF0) != 0x0100) { 114 errdesc = "magic"; 115 goto err; 116 } 117 /* Boundary between text and data varries a little. */ 118 x = kehp->a_text + kehp->a_data; 119 if (x != (edata - kernel_text)) { 120 errdesc = "a_text+a_data"; 121 goto err; 122 } 123 if (kehp->a_bss != (end - edata)) { 124 errdesc = "a_bss"; 125 goto err; 126 } 127 if (kehp->a_entry != (int)kernel_text) { 128 errdesc = "a_entry"; 129 goto err; 130 } 131 if (kehp->a_trsize || kehp->a_drsize) { 132 errdesc = "a_Xrsize"; 133 goto err; 134 } 135 /* The exec header looks OK... */ 136 137 /* Check the symtab length word. */ 138 endp = end; 139 symsz = (int*)endp; 140 if (kehp->a_syms != *symsz) { 141 errdesc = "a_syms"; 142 goto err; 143 } 144 endp += sizeof(int); /* past length word */ 145 endp += *symsz; /* past nlist array */ 146 147 /* Check the string table length. */ 148 strsz = (int*)endp; 149 if ((*strsz < 4) || (*strsz > 0x80000)) { 150 errdesc = "strsize"; 151 goto err; 152 } 153 154 /* Success! We have a valid symbol table! */ 155 endp += *strsz; /* past strings */ 156 esym = endp; 157 mon_printf(" found %d + %d\n", *symsz, *strsz); 158 return; 159 160 err: 161 mon_printf(" no symbols (bad %s)\n", errdesc); 162} 163#endif /* DDB && !SYMTAB_SPACE */ 164 165/* 166 * This function is called from _bootstrap() to initialize 167 * pre-vm-sytem virtual memory. All this really does is to 168 * set virtual_avail to the first page following preloaded 169 * data (i.e. the kernel and its symbol table) and special 170 * things that may be needed very early (proc0 upages). 171 * Once that is done, pmap_bootstrap() is called to do the 172 * usual preparations for our use of the MMU. 173 */ 174static void 175_vm_init(kehp) 176 struct exec *kehp; /* kernel exec header */ 177{ 178 vm_offset_t nextva; 179 180 /* 181 * First, reserve our symbol table which might have been 182 * loaded after our BSS area by the boot loader. However, 183 * if DDB is not part of this kernel, ignore the symbols. 184 */ 185 esym = end; 186#if defined(DDB) && !defined(SYMTAB_SPACE) 187 /* This will advance esym past the symbols. */ 188 _save_symtab(kehp); 189#endif 190 191 /* 192 * Steal some special-purpose, already mapped pages. 193 * Note: msgbuf is setup in machdep.c:cpu_startup() 194 */ 195 nextva = sun3x_round_page(esym); 196 197 /* 198 * Setup the u-area pages (stack, etc.) for proc0. 199 * This is done very early (here) to make sure the 200 * fault handler works in case we hit an early bug. 201 * (The fault handler may reference proc0 stuff.) 202 */ 203 proc0paddr = (struct user *) nextva; 204 nextva += USPACE; 205 bzero((caddr_t)proc0paddr, USPACE); 206 proc0.p_addr = proc0paddr; 207 208 /* 209 * Now that proc0 exists, make it the "current" one. 210 */ 211 curproc = &proc0; 212 curpcb = &proc0paddr->u_pcb; 213 214 /* 215 * Call pmap_bootstrap() so that we may begin using 216 * pmap_enter_kernel() and pmap_bootstrap_alloc(). 217 */ 218 pmap_bootstrap(nextva); 219} 220 221 222/* 223 * XXX - Should empirically estimate the divisor... 224 * Note that the value of delay_divisor is roughly 225 * 2048 / cpuclock (where cpuclock is in MHz). 226 */ 227int delay_divisor = 82; /* assume the fastest (3/260) */ 228 229static void 230_verify_hardware() 231{ 232 unsigned char machtype; 233 234 machtype = identity_prom.idp_machtype; 235 if ((machtype & CPU_ARCH_MASK) != SUN3X_ARCH) { 236 mon_printf("not a sun3x?\n"); 237 sunmon_abort(); 238 } 239 240 /* Set cputype and mmutype for common m68k code. */ 241 cputype = CPU_68030; 242 mmutype = MMU_68030; 243 244 cpu_machine_id = machtype & SUN3X_IMPL_MASK; 245 switch (cpu_machine_id) { 246 247 case SUN3X_MACH_80 : 248 cpu_string = "80"; /* Hydra */ 249 delay_divisor = 102; /* 20 MHz ? XXX */ 250 cpu_has_vme = FALSE; 251 break; 252 253 case SUN3X_MACH_470: 254 cpu_string = "470"; /* Pegasus */ 255 delay_divisor = 82; /* 25 MHz ? XXX */ 256 cpu_has_vme = TRUE; 257 break; 258 259 default: 260 mon_printf("unknown sun3x model\n"); 261 sunmon_abort(); 262 } 263} 264 265 266/* 267 * This is called from locore.s just after the kernel is remapped 268 * to its proper address, but before the call to main(). The work 269 * done here corresponds to various things done in locore.s on the 270 * hp300 port (and other m68k) but which we prefer to do in C code. 271 * Also do setup specific to the Sun PROM monitor and IDPROM here. 272 */ 273void 274_bootstrap(keh) 275 struct exec keh; /* kernel exec header */ 276{ 277 278 /* First, Clear BSS. */ 279 bzero(edata, end - edata); 280 281 /* set v_handler, get boothowto */ 282 sunmon_init(); 283 284 /* Find devices we need early (like the IDPROM). */ 285 obio_init(); 286 287 /* Note: must come after obio_init (for IDPROM). */ 288 _verify_hardware(); /* get CPU type, etc. */ 289 290 /* handle kernel mapping, pmap_bootstrap(), etc. */ 291 _vm_init(&keh); 292 293 /* 294 * Point interrupts/exceptions to our vector table. 295 * (Until now, we use the one setup by the PROM.) 296 * 297 * This is done after obio_init() / intreg_init() finds 298 * the interrupt register and disables the NMI clock so 299 * it will not cause "spurrious level 7" complaints. 300 */ 301 setvbr((void **)vector_table); 302 303 /* Interrupts are enabled later, after autoconfig. */ 304} 305