locore2.c revision 1.35
1/* $NetBSD: locore2.c,v 1.35 2009/11/21 04:16:53 rmind 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__KERNEL_RCSID(0, "$NetBSD: locore2.c,v 1.35 2009/11/21 04:16:53 rmind Exp $"); 34 35#include "opt_ddb.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/proc.h> 40#include <sys/reboot.h> 41#define ELFSIZE 32 42#include <sys/exec_elf.h> 43 44#include <uvm/uvm_extern.h> 45 46#include <machine/cpu.h> 47#include <machine/db_machdep.h> 48#include <machine/dvma.h> 49#include <machine/idprom.h> 50#include <machine/leds.h> 51#include <machine/mon.h> 52#include <machine/pmap.h> 53#include <machine/pte.h> 54 55#include <sun3/sun3/interreg.h> 56#include <sun3/sun3/machdep.h> 57#include <sun68k/sun68k/vector.h> 58 59/* This is defined in locore.s */ 60extern char kernel_text[]; 61 62/* These are defined by the linker */ 63extern char etext[], edata[], end[]; 64int nsym; 65char *ssym, *esym; 66 67/* 68 * XXX: m68k common code needs these... 69 * ... but this port does not need to deal with anything except 70 * an mc68030, so these two variables are always ignored. 71 */ 72int cputype = CPU_68030; 73int mmutype = MMU_68030; 74 75/* 76 * Now our own stuff. 77 */ 78 79struct user *proc0paddr; /* proc[0] pcb address (u-area VA) */ 80extern struct pcb *curpcb; 81 82/* First C code called by locore.s */ 83void _bootstrap(void); 84 85static void _vm_init(void); 86 87#if defined(DDB) 88static void _save_symtab(void); 89 90/* 91 * Preserve DDB symbols and strings by setting esym. 92 */ 93static void 94_save_symtab(void) 95{ 96 int i; 97 Elf_Ehdr *ehdr; 98 Elf_Shdr *shp; 99 vaddr_t minsym, maxsym; 100 101 /* 102 * Check the ELF headers. 103 */ 104 105 ehdr = (void *)end; 106 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 || 107 ehdr->e_ident[EI_CLASS] != ELFCLASS32) { 108 mon_printf("_save_symtab: bad ELF magic\n"); 109 return; 110 } 111 112 /* 113 * Find the end of the symbols and strings. 114 */ 115 116 maxsym = 0; 117 minsym = ~maxsym; 118 shp = (Elf_Shdr *)(end + ehdr->e_shoff); 119 for (i = 0; i < ehdr->e_shnum; i++) { 120 if (shp[i].sh_type != SHT_SYMTAB && 121 shp[i].sh_type != SHT_STRTAB) { 122 continue; 123 } 124 minsym = min(minsym, (vaddr_t)end + shp[i].sh_offset); 125 maxsym = max(maxsym, (vaddr_t)end + shp[i].sh_offset + 126 shp[i].sh_size); 127 } 128 nsym = 1; 129 ssym = (char *)ehdr; 130 esym = (char *)maxsym; 131} 132#endif /* DDB */ 133 134/* 135 * This function is called from _bootstrap() to initialize 136 * pre-vm-sytem virtual memory. All this really does is to 137 * set virtual_avail to the first page following preloaded 138 * data (i.e. the kernel and its symbol table) and special 139 * things that may be needed very early (lwp0 upages). 140 * Once that is done, pmap_bootstrap() is called to do the 141 * usual preparations for our use of the MMU. 142 */ 143static void 144_vm_init(void) 145{ 146 vaddr_t nextva; 147 148 /* 149 * First preserve our symbol table, which might have been 150 * loaded after our BSS area by the boot loader. However, 151 * if DDB is not part of this kernel, ignore the symbols. 152 */ 153 esym = end + 4; 154#if defined(DDB) 155 /* This will advance esym past the symbols. */ 156 _save_symtab(); 157#endif 158 159 /* 160 * Steal some special-purpose, already mapped pages. 161 * Note: msgbuf is setup in machdep.c:cpu_startup() 162 */ 163 nextva = m68k_round_page(esym); 164 165 /* 166 * Setup the u-area pages (stack, etc.) for lwp0. 167 * This is done very early (here) to make sure the 168 * fault handler works in case we hit an early bug. 169 * (The fault handler may reference lwp0 stuff.) 170 */ 171 proc0paddr = (struct user *) nextva; 172 nextva += USPACE; 173 memset((void *)proc0paddr, 0, USPACE); 174 lwp0.l_addr = proc0paddr; 175 176 /* 177 * Now that lwp0 exists, make it the "current" one. 178 */ 179 curlwp = &lwp0; 180 curpcb = &proc0paddr->u_pcb; 181 182 /* This does most of the real work. */ 183 pmap_bootstrap(nextva); 184} 185 186/* 187 * This is called from locore.s just after the kernel is remapped 188 * to its proper address, but before the call to main(). The work 189 * done here corresponds to various things done in locore.s on the 190 * hp300 port (and other m68k) but which we prefer to do in C code. 191 * Also do setup specific to the Sun PROM monitor and IDPROM here. 192 */ 193void 194_bootstrap(void) 195{ 196 197 /* First, Clear BSS. */ 198 memset(edata, 0, end - edata); 199 200 /* Set v_handler, get boothowto. */ 201 sunmon_init(); 202 203 /* Handle kernel mapping, pmap_bootstrap(), etc. */ 204 _vm_init(); 205 206 /* 207 * Find and save OBIO mappings needed early, 208 * and call some init functions. 209 */ 210 obio_init(); 211 212 /* 213 * Point interrupts/exceptions to our vector table. 214 * (Until now, we use the one setup by the PROM.) 215 * 216 * This is done after obio_init() / intreg_init() finds 217 * the interrupt register and disables the NMI clock so 218 * it will not cause "spurrious level 7" complaints. 219 * Done after _vm_init so the PROM can debug that. 220 */ 221 setvbr((void **)vector_table); 222 /* Interrupts are enabled later, after autoconfig. */ 223 224 /* 225 * Find the IDPROM and copy it to memory. 226 * Needs obio_init and setvbr earlier. 227 */ 228 idprom_init(); 229 230 /* 231 * Turn on the LEDs so we know power is on. 232 * Needs idprom_init and obio_init earlier. 233 */ 234 leds_init(); 235} 236