1 /* $NetBSD: locore2.c,v 1.79 2001/09/05 14:12:21 tsutsui 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 Adam Glass and Gordon W. Ross. 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 "opt_ddb.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/proc.h> 44 #include <sys/reboot.h> 45 #include <sys/user.h> 46 #define ELFSIZE 32 47 #include <sys/exec_elf.h> 48 49 #include <uvm/uvm_extern.h> 50 51 #include <machine/cpu.h> 52 #include <machine/db_machdep.h> 53 #include <machine/dvma.h> 54 #include <machine/idprom.h> 55 #include <machine/leds.h> 56 #include <machine/mon.h> 57 #include <machine/pmap.h> 58 #include <machine/pte.h> 59 60 #include <sun3/sun3/control.h> 61 #include <sun3/sun3/interreg.h> 62 #include <sun3/sun3/machdep.h> 63 #include <sun3/sun3/obmem.h> 64 #include <sun3/sun3/vector.h> 65 66 /* This is defined in locore.s */ 67 extern char kernel_text[]; 68 69 /* These are defined by the linker */ 70 extern char etext[], edata[], end[]; 71 int nsym; 72 char *ssym, *esym; 73 74 /* Basically a flag: "Do we have a VAC?" */ 75 int cache_size; 76 77 /* 78 * XXX: m68k common code needs these... 79 * ... but this port does not need to deal with anything except 80 * an mc68020, so these two variables are always ignored. 81 */ 82 int cputype = CPU_68020; 83 int mmutype = MMU_SUN; 84 85 /* 86 * Now our own stuff. 87 */ 88 89 u_char cpu_machine_id = 0; 90 char *cpu_string = NULL; 91 int cpu_has_vme = 0; 92 93 /* 94 * XXX - Should empirically estimate the divisor... 95 * Note that the value of delay_divisor is roughly 96 * 2048 / cpuclock (where cpuclock is in MHz). 97 */ 98 int delay_divisor = 82; /* assume the fastest (3/260) */ 99 100 extern int physmem; 101 102 struct user *proc0paddr; /* proc[0] pcb address (u-area VA) */ 103 extern struct pcb *curpcb; 104 105 /* First C code called by locore.s */ 106 void _bootstrap __P((void)); 107 108 static void _verify_hardware __P((void)); 109 static void _vm_init __P((void)); 110 111 #if defined(DDB) && !defined(SYMTAB_SPACE) 112 static void _save_symtab __P((void)); 113 114 /* 115 * Preserve DDB symbols and strings by setting esym. 116 */ 117 static void 118 _save_symtab() 119 { 120 int i; 121 Elf_Ehdr *ehdr; 122 Elf_Shdr *shp; 123 vaddr_t minsym, maxsym; 124 125 /* 126 * Check the ELF headers. 127 */ 128 129 ehdr = (void *)end; 130 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 || 131 ehdr->e_ident[EI_CLASS] != ELFCLASS32) { 132 mon_printf("_save_symtab: bad ELF magic\n"); 133 return; 134 } 135 136 /* 137 * Find the end of the symbols and strings. 138 */ 139 140 maxsym = 0; 141 minsym = ~maxsym; 142 shp = (Elf_Shdr *)(end + ehdr->e_shoff); 143 for (i = 0; i < ehdr->e_shnum; i++) { 144 if (shp[i].sh_type != SHT_SYMTAB && 145 shp[i].sh_type != SHT_STRTAB) { 146 continue; 147 } 148 minsym = min(minsym, (vaddr_t)end + shp[i].sh_offset); 149 maxsym = max(maxsym, (vaddr_t)end + shp[i].sh_offset + 150 shp[i].sh_size); 151 } 152 153 /* 154 * The Sun3/50 has further restrictions on the 155 * size of the kernel boot image. If preserving 156 * the symbol table would take us over the limit, 157 * then just ignore the symbols. 158 */ 159 160 if ((cpu_machine_id == SUN3_MACH_50) && 161 ((vaddr_t)maxsym > (KERNBASE + OBMEM_BW50_ADDR - USPACE))) { 162 mon_printf("_save_symtab: too large for 3/50"); 163 return; 164 } 165 166 nsym = 1; 167 ssym = (char *)ehdr; 168 esym = (char *)maxsym; 169 } 170 #endif /* DDB && !SYMTAB_SPACE */ 171 172 /* 173 * This function is called from _bootstrap() to initialize 174 * pre-vm-sytem virtual memory. All this really does is to 175 * set virtual_avail to the first page following preloaded 176 * data (i.e. the kernel and its symbol table) and special 177 * things that may be needed very early (proc0 upages). 178 * Once that is done, pmap_bootstrap() is called to do the 179 * usual preparations for our use of the MMU. 180 */ 181 static void 182 _vm_init() 183 { 184 vaddr_t nextva; 185 186 /* 187 * First preserve our symbol table, which might have been 188 * loaded after our BSS area by the boot loader. However, 189 * if DDB is not part of this kernel, ignore the symbols. 190 */ 191 esym = end + 4; 192 #if defined(DDB) && !defined(SYMTAB_SPACE) 193 /* This will advance esym past the symbols. */ 194 _save_symtab(); 195 #endif 196 197 /* 198 * Steal some special-purpose, already mapped pages. 199 * Note: msgbuf is setup in machdep.c:cpu_startup() 200 */ 201 nextva = m68k_round_page(esym); 202 203 /* 204 * Setup the u-area pages (stack, etc.) for proc0. 205 * This is done very early (here) to make sure the 206 * fault handler works in case we hit an early bug. 207 * (The fault handler may reference proc0 stuff.) 208 */ 209 proc0paddr = (struct user *) nextva; 210 nextva += USPACE; 211 memset((caddr_t)proc0paddr, 0, USPACE); 212 proc0.p_addr = proc0paddr; 213 214 /* 215 * Now that proc0 exists, make it the "current" one. 216 */ 217 curproc = &proc0; 218 curpcb = &proc0paddr->u_pcb; 219 220 /* This does most of the real work. */ 221 pmap_bootstrap(nextva); 222 } 223 224 /* 225 * Determine which Sun3 model we are running on. 226 * We have to do this very early on the Sun3 because 227 * pmap_bootstrap() needs to know if it should avoid 228 * the video memory on the Sun3/50. 229 * 230 * XXX: Just save idprom.idp_machtype here, and 231 * XXX: move the rest of this to identifycpu(). 232 * XXX: Move cache_size stuff to cache.c. 233 */ 234 static void 235 _verify_hardware() 236 { 237 unsigned char machtype; 238 int cpu_match = 0; 239 240 machtype = identity_prom.idp_machtype; 241 if ((machtype & IDM_ARCH_MASK) != IDM_ARCH_SUN3) { 242 mon_printf("Bad IDPROM arch!\n"); 243 sunmon_abort(); 244 } 245 246 cpu_machine_id = machtype; 247 switch (cpu_machine_id) { 248 249 case SUN3_MACH_50 : 250 cpu_match++; 251 cpu_string = "50"; 252 delay_divisor = 128; /* 16 MHz */ 253 break; 254 255 case SUN3_MACH_60 : 256 cpu_match++; 257 cpu_string = "60"; 258 delay_divisor = 102; /* 20 MHz */ 259 break; 260 261 case SUN3_MACH_110: 262 cpu_match++; 263 cpu_string = "110"; 264 delay_divisor = 120; /* 17 MHz */ 265 cpu_has_vme = TRUE; 266 break; 267 268 case SUN3_MACH_160: 269 cpu_match++; 270 cpu_string = "160"; 271 delay_divisor = 120; /* 17 MHz */ 272 cpu_has_vme = TRUE; 273 break; 274 275 case SUN3_MACH_260: 276 cpu_match++; 277 cpu_string = "260"; 278 delay_divisor = 82; /* 25 MHz */ 279 cpu_has_vme = TRUE; 280 #ifdef HAVECACHE 281 cache_size = 0x10000; /* 64K */ 282 #endif 283 break; 284 285 case SUN3_MACH_E : 286 cpu_match++; 287 cpu_string = "E"; 288 delay_divisor = 102; /* 20 MHz XXX: Correct? */ 289 cpu_has_vme = TRUE; 290 break; 291 292 default: 293 mon_printf("unknown sun3 model\n"); 294 sunmon_abort(); 295 } 296 if (!cpu_match) { 297 mon_printf("kernel not configured for the Sun 3 model\n"); 298 sunmon_abort(); 299 } 300 } 301 302 /* 303 * This is called from locore.s just after the kernel is remapped 304 * to its proper address, but before the call to main(). The work 305 * done here corresponds to various things done in locore.s on the 306 * hp300 port (and other m68k) but which we prefer to do in C code. 307 * Also do setup specific to the Sun PROM monitor and IDPROM here. 308 */ 309 void 310 _bootstrap() 311 { 312 313 /* First, Clear BSS. */ 314 memset(edata, 0, end - edata); 315 316 /* Set v_handler, get boothowto. */ 317 sunmon_init(); 318 319 /* Copy the IDPROM from control space. */ 320 idprom_init(); 321 322 /* Validate the Sun3 model (from IDPROM). */ 323 _verify_hardware(); 324 325 /* Handle kernel mapping, pmap_bootstrap(), etc. */ 326 _vm_init(); 327 328 /* 329 * Find and save OBIO mappings needed early, 330 * and call some init functions. 331 */ 332 obio_init(); 333 334 /* 335 * Point interrupts/exceptions to our vector table. 336 * (Until now, we use the one setup by the PROM.) 337 * 338 * This is done after obio_init() / intreg_init() finds 339 * the interrupt register and disables the NMI clock so 340 * it will not cause "spurrious level 7" complaints. 341 * Done after _vm_init so the PROM can debug that. 342 */ 343 setvbr((void **)vector_table); 344 /* Interrupts are enabled later, after autoconfig. */ 345 346 /* 347 * Turn on the LEDs so we know power is on. 348 * Needs idprom_init and obio_init earlier. 349 */ 350 leds_init(); 351 } 352