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