1 /* $NetBSD: locore2.c,v 1.7 2002/08/02 18:19:58 soren 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, Gordon W. Ross, and Matthew Fredette. 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/promlib.h> 57 #include <machine/pmap.h> 58 #include <machine/pte.h> 59 60 #include <machine/stdarg.h> 61 62 #include <sun2/sun2/control.h> 63 #include <sun2/sun2/machdep.h> 64 #include <sun68k/sun68k/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 /* 75 * XXX: m68k common code needs these... 76 * ... but this port does not need to deal with anything except 77 * an mc68010, so these two variables are always ignored. 78 */ 79 int cputype = CPU_68010; 80 int mmutype = MMU_SUN; 81 82 /* 83 * Now our own stuff. 84 */ 85 86 u_char cpu_machine_id = 0; 87 char *cpu_string = NULL; 88 int cpu_has_multibus = 0; 89 int cpu_has_vme = 0; 90 91 /* 92 * XXX - Should empirically estimate the divisor... 93 * Note that the value of delay_divisor is roughly 94 * 2048 / cpuclock (where cpuclock is in MHz). 95 */ 96 int delay_divisor = 82; /* assume the fastest (3/260) */ 97 98 extern int physmem; 99 100 struct user *proc0paddr; /* proc[0] pcb address (u-area VA) */ 101 extern struct pcb *curpcb; 102 103 /* First C code called by locore.s */ 104 void _bootstrap __P((void)); 105 106 static void _verify_hardware __P((void)); 107 static void _vm_init __P((void)); 108 109 #if defined(DDB) 110 static void _save_symtab __P((void)); 111 112 /* 113 * Preserve DDB symbols and strings by setting esym. 114 */ 115 static void 116 _save_symtab() 117 { 118 int i; 119 Elf_Ehdr *ehdr; 120 Elf_Shdr *shp; 121 vaddr_t minsym, maxsym; 122 123 /* 124 * Check the ELF headers. 125 */ 126 127 ehdr = (void *)end; 128 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 || 129 ehdr->e_ident[EI_CLASS] != ELFCLASS32) { 130 prom_printf("_save_symtab: bad ELF magic\n"); 131 return; 132 } 133 134 /* 135 * Find the end of the symbols and strings. 136 */ 137 138 maxsym = 0; 139 minsym = ~maxsym; 140 shp = (Elf_Shdr *)(end + ehdr->e_shoff); 141 for (i = 0; i < ehdr->e_shnum; i++) { 142 if (shp[i].sh_type != SHT_SYMTAB && 143 shp[i].sh_type != SHT_STRTAB) { 144 continue; 145 } 146 minsym = min(minsym, (vaddr_t)end + shp[i].sh_offset); 147 maxsym = max(maxsym, (vaddr_t)end + shp[i].sh_offset + 148 shp[i].sh_size); 149 } 150 151 nsym = 1; 152 ssym = (char *)ehdr; 153 esym = (char *)maxsym; 154 } 155 #endif /* DDB */ 156 157 /* 158 * This function is called from _bootstrap() to initialize 159 * pre-vm-sytem virtual memory. All this really does is to 160 * set virtual_avail to the first page following preloaded 161 * data (i.e. the kernel and its symbol table) and special 162 * things that may be needed very early (proc0 upages). 163 * Once that is done, pmap_bootstrap() is called to do the 164 * usual preparations for our use of the MMU. 165 */ 166 static void 167 _vm_init() 168 { 169 vaddr_t nextva; 170 171 /* 172 * First preserve our symbol table, which might have been 173 * loaded after our BSS area by the boot loader. However, 174 * if DDB is not part of this kernel, ignore the symbols. 175 */ 176 esym = end + 4; 177 #if defined(DDB) 178 /* This will advance esym past the symbols. */ 179 _save_symtab(); 180 #endif 181 182 /* 183 * Steal some special-purpose, already mapped pages. 184 * Note: msgbuf is setup in machdep.c:cpu_startup() 185 */ 186 nextva = m68k_round_page(esym); 187 188 /* 189 * Setup the u-area pages (stack, etc.) for proc0. 190 * This is done very early (here) to make sure the 191 * fault handler works in case we hit an early bug. 192 * (The fault handler may reference proc0 stuff.) 193 */ 194 proc0paddr = (struct user *) nextva; 195 nextva += USPACE; 196 memset((caddr_t)proc0paddr, 0, USPACE); 197 proc0.p_addr = proc0paddr; 198 199 /* 200 * Now that proc0 exists, make it the "current" one. 201 */ 202 curproc = &proc0; 203 curpcb = &proc0paddr->u_pcb; 204 205 /* This does most of the real work. */ 206 pmap_bootstrap(nextva); 207 } 208 209 /* 210 * Determine which Sun2 model we are running on. 211 * 212 * XXX: Just save idprom.idp_machtype here, and 213 * XXX: move the rest of this to identifycpu(). 214 * XXX: Move cache_size stuff to cache.c. 215 */ 216 static void 217 _verify_hardware() 218 { 219 unsigned char machtype; 220 int cpu_match = 0; 221 222 machtype = identity_prom.idp_machtype; 223 if ((machtype & IDM_ARCH_MASK) != IDM_ARCH_SUN2) { 224 prom_printf("Bad IDPROM arch!\n"); 225 prom_abort(); 226 } 227 228 cpu_machine_id = machtype; 229 switch (cpu_machine_id) { 230 231 case SUN2_MACH_120 : 232 cpu_match++; 233 cpu_string = "{120,170}"; 234 delay_divisor = 205; /* 10 MHz */ 235 cpu_has_multibus = TRUE; 236 break; 237 238 case SUN2_MACH_50 : 239 cpu_match++; 240 cpu_string = "50"; 241 delay_divisor = 205; /* 10 MHz */ 242 cpu_has_vme = TRUE; 243 break; 244 245 default: 246 prom_printf("unknown sun2 model\n"); 247 prom_abort(); 248 } 249 if (!cpu_match) { 250 prom_printf("kernel not configured for the Sun 2 model\n"); 251 prom_abort(); 252 } 253 } 254 255 /* 256 * This is called from locore.s just after the kernel is remapped 257 * to its proper address, but before the call to main(). The work 258 * done here corresponds to various things done in locore.s on the 259 * hp300 port (and other m68k) but which we prefer to do in C code. 260 * Also do setup specific to the Sun PROM monitor and IDPROM here. 261 */ 262 void 263 _bootstrap() 264 { 265 vaddr_t va; 266 267 /* First, Clear BSS. */ 268 memset(edata, 0, end - edata); 269 270 /* Initialize the PROM. */ 271 prom_init(); 272 273 /* Copy the IDPROM from control space. */ 274 idprom_init(); 275 276 /* Validate the Sun2 model (from IDPROM). */ 277 _verify_hardware(); 278 279 /* Handle kernel mapping, pmap_bootstrap(), etc. */ 280 _vm_init(); 281 282 /* 283 * Point interrupts/exceptions to our vector table. 284 * (Until now, we use the one setup by the PROM.) 285 */ 286 setvbr((void **)vector_table); 287 /* Interrupts are enabled later, after autoconfig. */ 288 289 /* 290 * Now unmap the PROM's physical/virtual pages zero through three. 291 */ 292 for(va = 0; va < NBPG * 4; va += NBPG) 293 set_pte(va, PG_INVAL); 294 295 /* 296 * Turn on the LEDs so we know power is on. 297 * Needs idprom_init and obio_init earlier. 298 */ 299 leds_init(); 300 } 301