Home | History | Annotate | Line # | Download | only in sun2
      1 /*	$NetBSD: locore2.c,v 1.34 2026/04/23 02:54:40 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 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  *
     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.34 2026/04/23 02:54:40 thorpej Exp $");
     34 
     35 #include "opt_ddb.h"
     36 #include "opt_modular.h"
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/proc.h>
     41 #include <sys/reboot.h>
     42 #define ELFSIZE 32
     43 #include <sys/exec_elf.h>
     44 
     45 #include <uvm/uvm_extern.h>
     46 
     47 #include <dev/cons.h>
     48 
     49 #include <machine/cpu.h>
     50 #include <machine/db_machdep.h>
     51 #include <machine/dvma.h>
     52 #include <machine/fcode.h>
     53 #include <machine/idprom.h>
     54 #include <machine/leds.h>
     55 #include <machine/promlib.h>
     56 #include <machine/pmap.h>
     57 #include <machine/pte.h>
     58 #include <machine/vectors.h>
     59 
     60 #include <sun2/sun2/control.h>
     61 #include <sun2/sun2/machdep.h>
     62 
     63 #include "ksyms.h"
     64 
     65 /* This is defined in locore.s */
     66 extern char kernel_text[];
     67 
     68 /* These are defined by the linker */
     69 extern char etext[], edata[], end[];
     70 int nsym;
     71 char *ssym, *esym;
     72 
     73 /*
     74  * XXX: m68k common code needs these...
     75  * ... but this port does not need to deal with anything except
     76  * an mc68010, so these two variables are always ignored.
     77  */
     78 int cputype = CPU_68010;
     79 int mmutype = MMU_SUN;
     80 
     81 /*
     82  * Now our own stuff.
     83  */
     84 
     85 u_char cpu_machine_id = 0;
     86 const char *cpu_string = NULL;
     87 int cpu_has_multibus = 0;
     88 int cpu_has_vme = 0;
     89 
     90 /* XXX This is probably overkill. */
     91 int delay_divisor = delay_divisor_est(25);
     92 
     93 extern struct pcb *curpcb;
     94 
     95 /* First C code called by locore.s */
     96 void *_bootstrap(void);
     97 
     98 #if NKSYMS || defined(DDB) || defined(MODULAR)
     99 /*
    100  * Preserve symbols and strings by setting esym.
    101  */
    102 static void
    103 _save_symtab(void)
    104 {
    105 	int i;
    106 	Elf_Ehdr *ehdr;
    107 	Elf_Shdr *shp;
    108 	vaddr_t minsym, maxsym;
    109 
    110 	/*
    111 	 * Check the ELF headers.
    112 	 */
    113 
    114 	ehdr = (void *)end;
    115 	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0 ||
    116 	    ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
    117 		prom_printf("_save_symtab: bad ELF magic\n");
    118 		return;
    119 	}
    120 
    121 	/*
    122 	 * Find the end of the symbols and strings.
    123 	 */
    124 
    125 	maxsym = 0;
    126 	minsym = ~maxsym;
    127 	shp = (Elf_Shdr *)(end + ehdr->e_shoff);
    128 	for (i = 0; i < ehdr->e_shnum; i++) {
    129 		if (shp[i].sh_type != SHT_SYMTAB &&
    130 		    shp[i].sh_type != SHT_STRTAB) {
    131 			continue;
    132 		}
    133 		minsym = uimin(minsym, (vaddr_t)end + shp[i].sh_offset);
    134 		maxsym = uimax(maxsym, (vaddr_t)end + shp[i].sh_offset +
    135 			     shp[i].sh_size);
    136 	}
    137 
    138 	nsym = 1;
    139 	ssym = (char *)ehdr;
    140 	esym = (char *)maxsym;
    141 }
    142 #endif	/* DDB */
    143 
    144 /*
    145  * This function is called from _bootstrap() to initialize
    146  * pre-vm-system virtual memory.  All this really does is to
    147  * set virtual_avail to the first page following preloaded
    148  * data (i.e. the kernel and its symbol table) and special
    149  * things that may be needed very early (lwp0 upages).
    150  * Once that is done, pmap_bootstrap() is called to do the
    151  * usual preparations for our use of the MMU.
    152  *
    153  * Returns the new kernel %sp value for lwp0.
    154  */
    155 static void *
    156 _vm_init(void)
    157 {
    158 	vaddr_t nextva;
    159 	paddr_t nextpa;
    160 
    161 	/*
    162 	 * First preserve our symbol table, which might have been
    163 	 * loaded after our BSS area by the boot loader.  However,
    164 	 * if DDB is not part of this kernel, ignore the symbols.
    165 	 */
    166 	esym = end + 4;
    167 #if NKSYMS || defined(DDB) || defined(MODULAR)
    168 	/* This will advance esym past the symbols. */
    169 	_save_symtab();
    170 #endif
    171 
    172 	/*
    173 	 * Steal some special-purpose, already mapped pages.
    174 	 * Note: msgbuf is setup in machdep.c:cpu_startup()
    175 	 */
    176 	nextva = m68k_round_page(esym);
    177 
    178 	/*
    179 	 * Setup the u-area pages (stack, etc.) for lwp0.
    180 	 * This is done very early (here) to make sure the
    181 	 * fault handler works in case we hit an early bug.
    182 	 * (The fault handler may reference lwp0 stuff.)
    183 	 */
    184 	uvm_lwp_setuarea(&lwp0, nextva);
    185 	memset((void *)nextva, 0, USPACE);
    186 	curlwp = &lwp0;
    187 	curpcb = lwp_getpcb(&lwp0);
    188 
    189 	/* Create a fake exception frame so that cpu_lwp_fork() can copy it. */
    190 	struct trapframe *tf = (struct trapframe *)(nextva + USPACE) - 1;
    191 	tf->tf_sr = PSL_USER;
    192 	lwp0.l_md.md_regs = (int *)tf;
    193 
    194 	nextva += USPACE;
    195 
    196 	/* This does most of the real work. */
    197 	nextpa = pmap_bootstrap(nextva);
    198 
    199 	machine_init_common(nextpa);
    200 
    201 	return tf;
    202 }
    203 
    204 /*
    205  * Determine which Sun2 model we are running on.
    206  *
    207  * XXX: Just save idprom.idp_machtype here, and
    208  * XXX: move the rest of this to identifycpu().
    209  * XXX: Move cache_size stuff to cache.c.
    210  */
    211 static void
    212 _verify_hardware(void)
    213 {
    214 	unsigned char machtype;
    215 	int cpu_match = 0;
    216 
    217 	machtype = identity_prom.idp_machtype;
    218 	if ((machtype & IDM_ARCH_MASK) != IDM_ARCH_SUN2) {
    219 		prom_printf("Bad IDPROM arch!\n");
    220 		prom_abort();
    221 	}
    222 
    223 	cpu_machine_id = machtype;
    224 	switch (cpu_machine_id) {
    225 
    226 	case ID_SUN2_120 :
    227 		cpu_match++;
    228 		cpu_string = "{120,170}";
    229 		cpuspeed_khz = 10000;
    230 		delay_divisor = delay_divisor_est(10);
    231 		cpu_has_multibus = true;
    232 		break;
    233 
    234 	case ID_SUN2_50 :
    235 		cpu_match++;
    236 		cpu_string = "50";
    237 		cpuspeed_khz = 10000;
    238 		delay_divisor = delay_divisor_est(10);
    239 		cpu_has_vme = true;
    240 		break;
    241 
    242 	default:
    243 		prom_printf("unknown sun2 model\n");
    244 		prom_abort();
    245 	}
    246 	if (!cpu_match) {
    247 		prom_printf("kernel not configured for the Sun 2 model\n");
    248 		prom_abort();
    249 	}
    250 }
    251 
    252 /*
    253  * This is called from locore.s just after the kernel is remapped
    254  * to its proper address, but before the call to main().  The work
    255  * done here corresponds to various things done in locore.s on the
    256  * hp300 port (and other m68k) but which we prefer to do in C code.
    257  * Also do setup specific to the Sun PROM monitor and IDPROM here.
    258  */
    259 void *
    260 _bootstrap(void)
    261 {
    262 	extern struct consdev consdev_prom;	/* XXX */
    263 	vaddr_t va;
    264 
    265 	/* First, Clear BSS. */
    266 	memset(edata, 0, end - edata);
    267 
    268 	/* Initialize the PROM. */
    269 	prom_init();
    270 
    271 	/*
    272 	 * Initialize console to point to the PROM (output only) table
    273 	 * for early printf calls.
    274 	 */
    275 	cn_tab = &consdev_prom;
    276 
    277 	/* Copy the IDPROM from control space. */
    278 	idprom_init();
    279 
    280 	/* Validate the Sun2 model (from IDPROM). */
    281 	_verify_hardware();
    282 
    283 	/* Handle kernel mapping, pmap_bootstrap(), etc. */
    284 	void *ksp = _vm_init();
    285 
    286 	/*
    287 	 * Point interrupts/exceptions to our vector table.
    288 	 * (Until now, we use the one setup by the PROM.)
    289 	 */
    290 	vec_init();
    291 	/* Interrupts are enabled later, after autoconfig. */
    292 
    293 	/*
    294  	 * Now unmap the PROM's physical/virtual pages zero through three.
    295  	 */
    296 	for(va = 0; va < PAGE_SIZE * 4; va += PAGE_SIZE)
    297 		set_pte(va, PG_INVAL);
    298 
    299 	/*
    300 	 * Turn on the LEDs so we know power is on.
    301 	 * Needs idprom_init and obio_init earlier.
    302 	 */
    303 	leds_init();
    304 
    305 	/*
    306 	 * Initialize the source/destination control registers for
    307 	 * movs.
    308 	 */
    309 	setsfc(FC_USERD);
    310 	setdfc(FC_USERD);
    311 
    312 	return ksp;
    313 }
    314