xref: /plan9-contrib/sys/src/boot/vt4/load.c (revision da917039c7f233c1a27d212bf012c6afa758af39)
1*da917039SDavid du Colombier #include "include.h"
2*da917039SDavid du Colombier #include "fs.h"
3*da917039SDavid du Colombier 
4*da917039SDavid du Colombier enum {
5*da917039SDavid du Colombier 	Dontprint,
6*da917039SDavid du Colombier 	Print,
7*da917039SDavid du Colombier 
8*da917039SDavid du Colombier 	Datamagic	= 0xfacebabe,
9*da917039SDavid du Colombier };
10*da917039SDavid du Colombier 
11*da917039SDavid du Colombier int securemem;
12*da917039SDavid du Colombier 
13*da917039SDavid du Colombier static char *etherparts[] = { "*", 0 };
14*da917039SDavid du Colombier static char *etherinis[] = {
15*da917039SDavid du Colombier 	"/cfg/pxe/%E",
16*da917039SDavid du Colombier 	0
17*da917039SDavid du Colombier };
18*da917039SDavid du Colombier 
19*da917039SDavid du Colombier Type types[] = {
20*da917039SDavid du Colombier 	{	Tether,
21*da917039SDavid du Colombier 		Fini|Fbootp,
22*da917039SDavid du Colombier 		etherinit, etherinitdev,
23*da917039SDavid du Colombier 		pxegetfspart, 0, bootpboot,
24*da917039SDavid du Colombier 		etherprintdevs,
25*da917039SDavid du Colombier 		etherparts,
26*da917039SDavid du Colombier 		etherinis,
27*da917039SDavid du Colombier 	},
28*da917039SDavid du Colombier };
29*da917039SDavid du Colombier 
30*da917039SDavid du Colombier static char *typenm[] = {
31*da917039SDavid du Colombier 	[Tether]	"ether",
32*da917039SDavid du Colombier };
33*da917039SDavid du Colombier 
34*da917039SDavid du Colombier typedef struct Mode Mode;
35*da917039SDavid du Colombier 
36*da917039SDavid du Colombier enum {
37*da917039SDavid du Colombier 	Dany		= -1,
38*da917039SDavid du Colombier 	Nmedia		= 2,		/* size reduction; was 16 */
39*da917039SDavid du Colombier };
40*da917039SDavid du Colombier 
41*da917039SDavid du Colombier enum {					/* mode */
42*da917039SDavid du Colombier 	Mauto,
43*da917039SDavid du Colombier 	Mlocal,
44*da917039SDavid du Colombier 	Manual,
45*da917039SDavid du Colombier 	NMode,
46*da917039SDavid du Colombier };
47*da917039SDavid du Colombier 
48*da917039SDavid du Colombier typedef struct Medium Medium;
49*da917039SDavid du Colombier struct Medium {
50*da917039SDavid du Colombier 	Type*	type;
51*da917039SDavid du Colombier 	ushort	flag;
52*da917039SDavid du Colombier 	ushort	dev;
53*da917039SDavid du Colombier 	char	name[NAMELEN];
54*da917039SDavid du Colombier 
55*da917039SDavid du Colombier 	Fs	*inifs;
56*da917039SDavid du Colombier 	char	*part;
57*da917039SDavid du Colombier 	char	*ini;
58*da917039SDavid du Colombier 
59*da917039SDavid du Colombier 	Medium*	next;
60*da917039SDavid du Colombier };
61*da917039SDavid du Colombier 
62*da917039SDavid du Colombier typedef struct Mode {
63*da917039SDavid du Colombier 	char*	name;
64*da917039SDavid du Colombier 	ushort	mode;
65*da917039SDavid du Colombier } Mode;
66*da917039SDavid du Colombier 
67*da917039SDavid du Colombier extern char bdata[], edata[], end[], etext[];
68*da917039SDavid du Colombier 
69*da917039SDavid du Colombier static Medium media[Nmedia];
70*da917039SDavid du Colombier static Medium *curmedium = media;
71*da917039SDavid du Colombier 
72*da917039SDavid du Colombier static Mode modes[NMode+1] = {
73*da917039SDavid du Colombier 	[Mauto]		{ "auto",   Mauto,  },
74*da917039SDavid du Colombier 	[Mlocal]	{ "local",  Mlocal, },
75*da917039SDavid du Colombier 	[Manual]	{ "manual", Manual, },
76*da917039SDavid du Colombier };
77*da917039SDavid du Colombier 
78*da917039SDavid du Colombier Mach* machptr[MAXMACH];
79*da917039SDavid du Colombier 
80*da917039SDavid du Colombier ulong cpuentry = 0;
81*da917039SDavid du Colombier 
82*da917039SDavid du Colombier char **ini;
83*da917039SDavid du Colombier char *defaultpartition;
84*da917039SDavid du Colombier char *persist;
85*da917039SDavid du Colombier 
86*da917039SDavid du Colombier int debugload;
87*da917039SDavid du Colombier int iniread;
88*da917039SDavid du Colombier int pxe = 1;
89*da917039SDavid du Colombier int scsi0port;
90*da917039SDavid du Colombier int vga;
91*da917039SDavid du Colombier 
92*da917039SDavid du Colombier uintptr memstart;				/* set before main called */
93*da917039SDavid du Colombier uintptr vectorbase;				/* set before main called */
94*da917039SDavid du Colombier 
95*da917039SDavid du Colombier static uintptr memsz;
96*da917039SDavid du Colombier 
97*da917039SDavid du Colombier static Medium*
parse(char * line,char ** file)98*da917039SDavid du Colombier parse(char *line, char **file)
99*da917039SDavid du Colombier {
100*da917039SDavid du Colombier 	char *p;
101*da917039SDavid du Colombier 	Type *tp;
102*da917039SDavid du Colombier 	Medium *mp;
103*da917039SDavid du Colombier 
104*da917039SDavid du Colombier 	if(p = strchr(line, '!')) {
105*da917039SDavid du Colombier 		*p++ = 0;
106*da917039SDavid du Colombier 		*file = p;
107*da917039SDavid du Colombier 	} else
108*da917039SDavid du Colombier 		*file = "";
109*da917039SDavid du Colombier 
110*da917039SDavid du Colombier 	tp = types;
111*da917039SDavid du Colombier 	for(mp = tp->media; mp; mp = mp->next)
112*da917039SDavid du Colombier 		if(strcmp(mp->name, line) == 0)
113*da917039SDavid du Colombier 			return mp;
114*da917039SDavid du Colombier 	if(p)
115*da917039SDavid du Colombier 		*--p = '!';
116*da917039SDavid du Colombier 	return nil;
117*da917039SDavid du Colombier }
118*da917039SDavid du Colombier 
119*da917039SDavid du Colombier static int
boot(Medium * mp,char * file)120*da917039SDavid du Colombier boot(Medium *mp, char *file)
121*da917039SDavid du Colombier {
122*da917039SDavid du Colombier 	Type *tp;
123*da917039SDavid du Colombier 	Medium *xmp;
124*da917039SDavid du Colombier 	static int didaddconf;
125*da917039SDavid du Colombier 	Boot b;
126*da917039SDavid du Colombier 
127*da917039SDavid du Colombier 	memset(&b, 0, sizeof b);
128*da917039SDavid du Colombier 	b.state = INITKERNEL;
129*da917039SDavid du Colombier 
130*da917039SDavid du Colombier 	if(didaddconf == 0) {
131*da917039SDavid du Colombier 		didaddconf = 1;
132*da917039SDavid du Colombier 		tp = types;
133*da917039SDavid du Colombier 		if(tp->addconf)
134*da917039SDavid du Colombier 			for(xmp = tp->media; xmp; xmp = xmp->next)
135*da917039SDavid du Colombier 				(*tp->addconf)(xmp->dev);
136*da917039SDavid du Colombier 	}
137*da917039SDavid du Colombier 
138*da917039SDavid du Colombier 	seprint(BOOTLINE, BOOTLINE + BOOTLINELEN, "%s!%s", mp->name, file);
139*da917039SDavid du Colombier 	print("booting %s!%s\n", mp->name, file);
140*da917039SDavid du Colombier 	return (*mp->type->boot)(mp->dev, file, &b);
141*da917039SDavid du Colombier }
142*da917039SDavid du Colombier 
143*da917039SDavid du Colombier static Medium*
allocm(Type * tp)144*da917039SDavid du Colombier allocm(Type *tp)
145*da917039SDavid du Colombier {
146*da917039SDavid du Colombier 	Medium **l;
147*da917039SDavid du Colombier 
148*da917039SDavid du Colombier 	if(curmedium >= &media[Nmedia])
149*da917039SDavid du Colombier 		return 0;
150*da917039SDavid du Colombier 
151*da917039SDavid du Colombier 	for(l = &tp->media; *l; l = &(*l)->next)
152*da917039SDavid du Colombier 		;
153*da917039SDavid du Colombier 	*l = curmedium++;
154*da917039SDavid du Colombier 	return *l;
155*da917039SDavid du Colombier }
156*da917039SDavid du Colombier 
157*da917039SDavid du Colombier Medium*
probe(int type,int flag,int dev)158*da917039SDavid du Colombier probe(int type, int flag, int dev)
159*da917039SDavid du Colombier {
160*da917039SDavid du Colombier 	Type *tp;
161*da917039SDavid du Colombier 	int i;
162*da917039SDavid du Colombier 	Medium *mp;
163*da917039SDavid du Colombier 	File f;
164*da917039SDavid du Colombier 	Fs *fs;
165*da917039SDavid du Colombier 	char **partp;
166*da917039SDavid du Colombier 
167*da917039SDavid du Colombier 	tp = types;
168*da917039SDavid du Colombier 	if(type != Tany && type != tp->type)
169*da917039SDavid du Colombier 		return 0;
170*da917039SDavid du Colombier 
171*da917039SDavid du Colombier 	if(flag != Fnone)
172*da917039SDavid du Colombier 		for(mp = tp->media; mp; mp = mp->next)
173*da917039SDavid du Colombier 			if((flag & mp->flag) && (dev == Dany || dev == mp->dev))
174*da917039SDavid du Colombier 				return mp;
175*da917039SDavid du Colombier 	if((tp->flag & Fprobe) == 0){
176*da917039SDavid du Colombier 		tp->flag |= Fprobe;
177*da917039SDavid du Colombier 		tp->mask = (*tp->init)();
178*da917039SDavid du Colombier 	}
179*da917039SDavid du Colombier 
180*da917039SDavid du Colombier 	for(i = 0; tp->mask; i++){
181*da917039SDavid du Colombier 		if((tp->mask & (1<<i)) == 0)
182*da917039SDavid du Colombier 			continue;
183*da917039SDavid du Colombier 		tp->mask &= ~(1<<i);
184*da917039SDavid du Colombier 
185*da917039SDavid du Colombier 		if((mp = allocm(tp)) == 0)
186*da917039SDavid du Colombier 			continue;
187*da917039SDavid du Colombier 
188*da917039SDavid du Colombier 		mp->dev = i;
189*da917039SDavid du Colombier 		mp->flag = tp->flag;
190*da917039SDavid du Colombier 		mp->type = tp;
191*da917039SDavid du Colombier 		(*tp->initdev)(i, mp->name);
192*da917039SDavid du Colombier 
193*da917039SDavid du Colombier 		if(mp->flag & Fini){
194*da917039SDavid du Colombier 			mp->flag &= ~Fini;
195*da917039SDavid du Colombier 			for(partp = tp->parts; *partp; partp++){
196*da917039SDavid du Colombier 				if((fs = (*tp->getfspart)(i, *partp, 0)) == nil)
197*da917039SDavid du Colombier 					continue;
198*da917039SDavid du Colombier 
199*da917039SDavid du Colombier 				for(ini = tp->inis; *ini; ini++)
200*da917039SDavid du Colombier 					if(fswalk(fs, *ini, &f) > 0){
201*da917039SDavid du Colombier 						mp->inifs = fs;
202*da917039SDavid du Colombier 						mp->part = *partp;
203*da917039SDavid du Colombier 						mp->ini = f.path;
204*da917039SDavid du Colombier 						mp->flag |= Fini;
205*da917039SDavid du Colombier 						goto Break2;
206*da917039SDavid du Colombier 					}
207*da917039SDavid du Colombier 			}
208*da917039SDavid du Colombier 		}
209*da917039SDavid du Colombier 	Break2:
210*da917039SDavid du Colombier 		if((flag & mp->flag) && (dev == Dany || dev == i))
211*da917039SDavid du Colombier 			return mp;
212*da917039SDavid du Colombier 	}
213*da917039SDavid du Colombier 	return 0;
214*da917039SDavid du Colombier }
215*da917039SDavid du Colombier 
216*da917039SDavid du Colombier enum {
217*da917039SDavid du Colombier 	Kilo = 1024,
218*da917039SDavid du Colombier };
219*da917039SDavid du Colombier 
220*da917039SDavid du Colombier /* make sure we don't get the write system call from libc */
221*da917039SDavid du Colombier long
write(int fd,void * buf,long nbytes)222*da917039SDavid du Colombier write(int fd, void *buf, long nbytes)
223*da917039SDavid du Colombier {
224*da917039SDavid du Colombier 	USED(fd);
225*da917039SDavid du Colombier 	vuartputs(buf, nbytes);
226*da917039SDavid du Colombier 	return nbytes;
227*da917039SDavid du Colombier }
228*da917039SDavid du Colombier 
229*da917039SDavid du Colombier /*
230*da917039SDavid du Colombier  * write zero words to an entire cache line (the one containing addr).
231*da917039SDavid du Colombier  * does not flush the data cache.
232*da917039SDavid du Colombier  */
233*da917039SDavid du Colombier void
cacheline0(uintptr addr)234*da917039SDavid du Colombier cacheline0(uintptr addr)
235*da917039SDavid du Colombier {
236*da917039SDavid du Colombier 	ulong *sp, *endmem;
237*da917039SDavid du Colombier 
238*da917039SDavid du Colombier 	addr &= ~(DCACHELINESZ - 1);
239*da917039SDavid du Colombier 	endmem = (ulong *)(addr + DCACHELINESZ);
240*da917039SDavid du Colombier 	for (sp = (ulong *)addr; sp < endmem; sp++)
241*da917039SDavid du Colombier 		*sp = 0;
242*da917039SDavid du Colombier //	coherence();
243*da917039SDavid du Colombier }
244*da917039SDavid du Colombier 
245*da917039SDavid du Colombier /* force the four qtm write buffers to be retired to dram by filling them. */
246*da917039SDavid du Colombier void
flushwrbufs(void)247*da917039SDavid du Colombier flushwrbufs(void)
248*da917039SDavid du Colombier {
249*da917039SDavid du Colombier 	if (!securemem)
250*da917039SDavid du Colombier 		return;
251*da917039SDavid du Colombier 	cacheline0(PHYSDRAM);
252*da917039SDavid du Colombier 	cacheline0(PHYSDRAM + DCACHELINESZ);
253*da917039SDavid du Colombier 	cacheline0(PHYSDRAM + 2*DCACHELINESZ);
254*da917039SDavid du Colombier 	cacheline0(PHYSDRAM + 3*DCACHELINESZ);
255*da917039SDavid du Colombier 	coherence();
256*da917039SDavid du Colombier }
257*da917039SDavid du Colombier 
258*da917039SDavid du Colombier static void
vfyzeros(ulong * addr,ulong * end)259*da917039SDavid du Colombier vfyzeros(ulong *addr, ulong *end)
260*da917039SDavid du Colombier {
261*da917039SDavid du Colombier 	ulong wd;
262*da917039SDavid du Colombier 	ulong *sp;
263*da917039SDavid du Colombier 
264*da917039SDavid du Colombier 	for (sp = addr; sp < end; sp++) {
265*da917039SDavid du Colombier 		wd = *sp;
266*da917039SDavid du Colombier 		if (wd != 0) {
267*da917039SDavid du Colombier 			PROG('?')
268*da917039SDavid du Colombier 			panic("bad dram: %#p read back as %#lux not 0", sp, wd);
269*da917039SDavid du Colombier 		}
270*da917039SDavid du Colombier 	}
271*da917039SDavid du Colombier }
272*da917039SDavid du Colombier 
273*da917039SDavid du Colombier static int
memreset(void)274*da917039SDavid du Colombier memreset(void)
275*da917039SDavid du Colombier {
276*da917039SDavid du Colombier 	int i, cnt;
277*da917039SDavid du Colombier 	uintptr addr, endmem;
278*da917039SDavid du Colombier 
279*da917039SDavid du Colombier 	cnt = 0;
280*da917039SDavid du Colombier 	if (securemem)
281*da917039SDavid du Colombier 		cnt = qtmmemreset();
282*da917039SDavid du Colombier 	else
283*da917039SDavid du Colombier 		/* normal dram init. should take 100—250 ms. */
284*da917039SDavid du Colombier 		for (i = 10*1000*1000; i-- > 0; )
285*da917039SDavid du Colombier 			cnt++;
286*da917039SDavid du Colombier PROG('t')
287*da917039SDavid du Colombier 	/*
288*da917039SDavid du Colombier 	 * dram must be done initialising now,
289*da917039SDavid du Colombier 	 * but qtm needs us to zero it *all* before any other use,
290*da917039SDavid du Colombier 	 * to set the macs.  even for non-qtm dram, it might be wise
291*da917039SDavid du Colombier 	 * to ensure that all the ecc bits are set.
292*da917039SDavid du Colombier 	 */
293*da917039SDavid du Colombier 	memsz = memsize();		/* may carefully probe qtm dram */
294*da917039SDavid du Colombier 	qtmerrtest("sizing memory");
295*da917039SDavid du Colombier 
296*da917039SDavid du Colombier 	dcflush(PHYSSRAM, (1ULL << 32) - PHYSSRAM);
297*da917039SDavid du Colombier 	cachesinvalidate();
298*da917039SDavid du Colombier 
299*da917039SDavid du Colombier 	endmem = PHYSDRAM + memsz;
300*da917039SDavid du Colombier 	for (addr = PHYSDRAM; addr < endmem; addr += DCACHELINESZ) {
301*da917039SDavid du Colombier 		cacheline0(addr);
302*da917039SDavid du Colombier 		qtmerrtestaddr(addr);
303*da917039SDavid du Colombier 	}
304*da917039SDavid du Colombier 	assert(addr == endmem);
305*da917039SDavid du Colombier 	coherence();
306*da917039SDavid du Colombier 	flushwrbufs();
307*da917039SDavid du Colombier 	qtmerrtest("zeroing dram");
308*da917039SDavid du Colombier 
309*da917039SDavid du Colombier #ifdef PARANOID
310*da917039SDavid du Colombier 	vfyzeros((ulong *)PHYSDRAM, (ulong *)endmem);
311*da917039SDavid du Colombier #else
312*da917039SDavid du Colombier 	vfyzeros((ulong *)(endmem - MB), (ulong *)endmem);
313*da917039SDavid du Colombier #endif
314*da917039SDavid du Colombier 	dcflush(PHYSDRAM, memsz);
315*da917039SDavid du Colombier 	dcflush(PHYSSRAM, (1ULL << 32) - PHYSSRAM);
316*da917039SDavid du Colombier 	cachesinvalidate();
317*da917039SDavid du Colombier 
318*da917039SDavid du Colombier 	/*
319*da917039SDavid du Colombier 	 * Hallelujah!  We can finally treat qtm dram just like real memory,
320*da917039SDavid du Colombier 	 * except that the last (partial) page is funny and should be avoided
321*da917039SDavid du Colombier 	 * after initialising it.
322*da917039SDavid du Colombier 	 * It happens even with caches off, so it's a bit hard to explain
323*da917039SDavid du Colombier 	 * why it should be funny.
324*da917039SDavid du Colombier 	 */
325*da917039SDavid du Colombier 	memsz &= ~(BY2PG - 1);
326*da917039SDavid du Colombier 	endmem = PHYSDRAM + memsz;
327*da917039SDavid du Colombier 
328*da917039SDavid du Colombier #ifdef PARANOID
329*da917039SDavid du Colombier 	vfyzeros((ulong *)PHYSDRAM, (ulong *)endmem);
330*da917039SDavid du Colombier #else
331*da917039SDavid du Colombier 	vfyzeros((ulong *)PHYSDRAM, (ulong *)(PHYSDRAM + MB));
332*da917039SDavid du Colombier 	vfyzeros((ulong *)(endmem - MB), (ulong *)endmem);
333*da917039SDavid du Colombier #endif
334*da917039SDavid du Colombier 	qtmerrtest("reading back dram");
335*da917039SDavid du Colombier 	return cnt;
336*da917039SDavid du Colombier }
337*da917039SDavid du Colombier 
338*da917039SDavid du Colombier static void
memtest(void)339*da917039SDavid du Colombier memtest(void)
340*da917039SDavid du Colombier {
341*da917039SDavid du Colombier 	ulong wd;
342*da917039SDavid du Colombier 	ulong *sp, *endmem;
343*da917039SDavid du Colombier 
344*da917039SDavid du Colombier 	/*
345*da917039SDavid du Colombier 	 * verify that (possibly secure) dram is more or less working.
346*da917039SDavid du Colombier 	 * write address of each word into that word.
347*da917039SDavid du Colombier 	 */
348*da917039SDavid du Colombier #ifdef PARANOID
349*da917039SDavid du Colombier 	endmem = (ulong *)(PHYSDRAM + memsz);
350*da917039SDavid du Colombier #else
351*da917039SDavid du Colombier 	endmem = (ulong *)(PHYSDRAM + MB);		/* just the first MB */
352*da917039SDavid du Colombier #endif
353*da917039SDavid du Colombier 	for (sp = (ulong *)PHYSDRAM; sp < endmem; sp++)
354*da917039SDavid du Colombier 		*sp = (ulong)sp;
355*da917039SDavid du Colombier 	coherence();
356*da917039SDavid du Colombier 	/* no need to flush caches, caches are off */
357*da917039SDavid du Colombier 
358*da917039SDavid du Colombier 	/*
359*da917039SDavid du Colombier 	 * now verify that each word contains its address.
360*da917039SDavid du Colombier 	 */
361*da917039SDavid du Colombier 	for (sp = (ulong *)PHYSDRAM; sp < endmem; sp++) {
362*da917039SDavid du Colombier 		wd = *sp;
363*da917039SDavid du Colombier 		if (wd != (ulong)sp) {
364*da917039SDavid du Colombier 			PROG('?')
365*da917039SDavid du Colombier 			panic("bad dram: %#p read back as %#lux", sp, wd);
366*da917039SDavid du Colombier 		}
367*da917039SDavid du Colombier 	}
368*da917039SDavid du Colombier PROG('t')
369*da917039SDavid du Colombier /*	memset((void *)PHYSDRAM, 0, memsz);	/* good hygiene? */
370*da917039SDavid du Colombier }
371*da917039SDavid du Colombier 
372*da917039SDavid du Colombier enum {
373*da917039SDavid du Colombier 	Testbase = PHYSDRAM + 0x4000,
374*da917039SDavid du Colombier };
375*da917039SDavid du Colombier 
376*da917039SDavid du Colombier void
meminit(void)377*da917039SDavid du Colombier meminit(void)
378*da917039SDavid du Colombier {
379*da917039SDavid du Colombier 	int i;
380*da917039SDavid du Colombier 	uchar *memc;
381*da917039SDavid du Colombier 	ulong *mem;
382*da917039SDavid du Colombier 
383*da917039SDavid du Colombier //	iprint("sanity: writing...");
384*da917039SDavid du Colombier 	mem  = (ulong *)Testbase;
385*da917039SDavid du Colombier 	memc = (uchar *)Testbase;
386*da917039SDavid du Colombier 
387*da917039SDavid du Colombier 	memset(mem, 0252, Kilo);
388*da917039SDavid du Colombier 	coherence();
389*da917039SDavid du Colombier 	dcflush(Testbase, Kilo);
390*da917039SDavid du Colombier 
391*da917039SDavid du Colombier //	iprint("reading...");
392*da917039SDavid du Colombier 	for (i = 0; i < Kilo; i++)
393*da917039SDavid du Colombier 		if (memc[i] != 0252)
394*da917039SDavid du Colombier 			panic("dram not retaining data");
395*da917039SDavid du Colombier 
396*da917039SDavid du Colombier //	iprint("zeroing...");
397*da917039SDavid du Colombier 	memset(mem, '\0', Kilo);
398*da917039SDavid du Colombier 	coherence();
399*da917039SDavid du Colombier 	dcflush(Testbase, Kilo);
400*da917039SDavid du Colombier 	if (*mem)
401*da917039SDavid du Colombier 		panic("zeroed dram not zero");
402*da917039SDavid du Colombier //	iprint("\n");
403*da917039SDavid du Colombier }
404*da917039SDavid du Colombier 
405*da917039SDavid du Colombier static int idx;
406*da917039SDavid du Colombier static char numb[32];
407*da917039SDavid du Colombier 
408*da917039SDavid du Colombier static void
gendigs(ulong n)409*da917039SDavid du Colombier gendigs(ulong n)
410*da917039SDavid du Colombier {
411*da917039SDavid du Colombier 	int dig;
412*da917039SDavid du Colombier 
413*da917039SDavid du Colombier 	do {
414*da917039SDavid du Colombier 		dig = n % 16;
415*da917039SDavid du Colombier 		if (dig > 9)
416*da917039SDavid du Colombier 			numb[idx--] = 'A' + dig - 10;
417*da917039SDavid du Colombier 		else
418*da917039SDavid du Colombier 			numb[idx--] = '0' + dig;
419*da917039SDavid du Colombier 	} while ((n /= 16) > 0);
420*da917039SDavid du Colombier }
421*da917039SDavid du Colombier 
422*da917039SDavid du Colombier static void
prnum(ulong n)423*da917039SDavid du Colombier prnum(ulong n)
424*da917039SDavid du Colombier {
425*da917039SDavid du Colombier //	PROG(' ')
426*da917039SDavid du Colombier 	idx = nelem(numb) - 1;
427*da917039SDavid du Colombier 	gendigs(n);
428*da917039SDavid du Colombier 	for (; idx < nelem(numb); idx++)
429*da917039SDavid du Colombier 		PROG(numb[idx])
430*da917039SDavid du Colombier 	PROG('\n')
431*da917039SDavid du Colombier 	PROG('\r')
432*da917039SDavid du Colombier }
433*da917039SDavid du Colombier 
434*da917039SDavid du Colombier extern uintptr vectorbase;
435*da917039SDavid du Colombier 
436*da917039SDavid du Colombier void
main(void)437*da917039SDavid du Colombier main(void)
438*da917039SDavid du Colombier {
439*da917039SDavid du Colombier 	int flag, i, j, mode, tried;
440*da917039SDavid du Colombier 	char def[2*NAMELEN], line[80], *p, *file;
441*da917039SDavid du Colombier 	Medium *mp;
442*da917039SDavid du Colombier 	Type *tp;
443*da917039SDavid du Colombier 	static int savcnt, caching;
444*da917039SDavid du Colombier 	static ulong vfy = Datamagic;
445*da917039SDavid du Colombier 
446*da917039SDavid du Colombier 	/*
447*da917039SDavid du Colombier 	 * all cpus start executing at reset address, thus start of sram.
448*da917039SDavid du Colombier 	 * cpu0 loads the kernel;
449*da917039SDavid du Colombier 	 * all others just jump to the (by now) loaded kernel.
450*da917039SDavid du Colombier 	 */
451*da917039SDavid du Colombier 	/* "\r\nPlan " already printed by l.s */
452*da917039SDavid du Colombier 	if (getpir() != 0) {
453*da917039SDavid du Colombier 		for (j = 0; j < 6; j++)
454*da917039SDavid du Colombier 			for (i = 2*1000*1000*1000; i > 0; i--)
455*da917039SDavid du Colombier 				;
456*da917039SDavid du Colombier 
457*da917039SDavid du Colombier 		cachesinvalidate();
458*da917039SDavid du Colombier 		while(cpuentry == 0)
459*da917039SDavid du Colombier 			cachesinvalidate();
460*da917039SDavid du Colombier 
461*da917039SDavid du Colombier 		for (j = 0; j < 6; j++)
462*da917039SDavid du Colombier 			for (i = 2*1000*1000*1000; i > 0; i--)
463*da917039SDavid du Colombier 				;
464*da917039SDavid du Colombier 		warp9(PADDR(cpuentry));
465*da917039SDavid du Colombier 	}
466*da917039SDavid du Colombier 
467*da917039SDavid du Colombier 	/*
468*da917039SDavid du Colombier 	 * we may have to realign the data segment; apparently ql -R4096
469*da917039SDavid du Colombier 	 * does not pad the text segment.
470*da917039SDavid du Colombier 	 */
471*da917039SDavid du Colombier 	if (vfy != Datamagic)
472*da917039SDavid du Colombier 		memmove(bdata, etext, edata - bdata);
473*da917039SDavid du Colombier 	if (vfy != Datamagic) {
474*da917039SDavid du Colombier 		PROG('?')
475*da917039SDavid du Colombier 		panic("misaligned data segment");
476*da917039SDavid du Colombier 	}
477*da917039SDavid du Colombier //	memset(edata, 0, end - edata);		/* zero bss */
478*da917039SDavid du Colombier 
479*da917039SDavid du Colombier PROG('9')
480*da917039SDavid du Colombier 	/*
481*da917039SDavid du Colombier 	 * trap vectors are in sram, so we don't have to wait for dram
482*da917039SDavid du Colombier 	 * to become ready to initialise them.
483*da917039SDavid du Colombier 	 */
484*da917039SDavid du Colombier 	trapinit();
485*da917039SDavid du Colombier PROG(' ')
486*da917039SDavid du Colombier 	securemem = (probeaddr(Qtm) >= 0);
487*da917039SDavid du Colombier 	if (securemem)
488*da917039SDavid du Colombier 		PROG('q')
489*da917039SDavid du Colombier 	else
490*da917039SDavid du Colombier 		PROG('n')
491*da917039SDavid du Colombier PROG(' ')
492*da917039SDavid du Colombier 
493*da917039SDavid du Colombier 	/*
494*da917039SDavid du Colombier 	 * the stack is now at top of sram, and entry to main just pushed
495*da917039SDavid du Colombier 	 * stuff onto it.  the new stack will be at the top of dram,
496*da917039SDavid du Colombier 	 * when dram finishes initialising itself.
497*da917039SDavid du Colombier 	 */
498*da917039SDavid du Colombier PROG('B')
499*da917039SDavid du Colombier PROG('o')
500*da917039SDavid du Colombier PROG('o')
501*da917039SDavid du Colombier 	/* do voodoo to make dram usable; prints "t".  sets memsz. */
502*da917039SDavid du Colombier 	savcnt = memreset();
503*da917039SDavid du Colombier PROG('s')
504*da917039SDavid du Colombier 	memtest();			/* also prints "t" */
505*da917039SDavid du Colombier 	intrinit();
506*da917039SDavid du Colombier 
507*da917039SDavid du Colombier 	caching = cacheson();
508*da917039SDavid du Colombier 
509*da917039SDavid du Colombier 	/*
510*da917039SDavid du Colombier 	 * switch to the dram stack just below the end of dram.
511*da917039SDavid du Colombier 	 * have to allow enough room for main's local variables,
512*da917039SDavid du Colombier 	 * to avoid address faults.
513*da917039SDavid du Colombier 	 */
514*da917039SDavid du Colombier 
515*da917039SDavid du Colombier PROG('r')
516*da917039SDavid du Colombier 	setsp(memsz - BY2PG);
517*da917039SDavid du Colombier 
518*da917039SDavid du Colombier PROG('a')
519*da917039SDavid du Colombier 	meminit();
520*da917039SDavid du Colombier 	/* memory is now more or less normal from a software perspective. */
521*da917039SDavid du Colombier 
522*da917039SDavid du Colombier 	memset(m, 0, sizeof(Mach));
523*da917039SDavid du Colombier 	m->machno = 0;
524*da917039SDavid du Colombier 	m->up = nil;
525*da917039SDavid du Colombier 	MACHP(0) = m;
526*da917039SDavid du Colombier 
527*da917039SDavid du Colombier 	/*
528*da917039SDavid du Colombier 	 * the Mach struct is now initialised, so we can print safely.
529*da917039SDavid du Colombier 	 */
530*da917039SDavid du Colombier 
531*da917039SDavid du Colombier //	print("\nPlan 9 bootstrap");	/* already printed, 1 char at a time */
532*da917039SDavid du Colombier 	print("p");
533*da917039SDavid du Colombier //	print("\n%d iterations waiting for %s init done\n",
534*da917039SDavid du Colombier //		savcnt, (securemem? "qtm": "dram"));
535*da917039SDavid du Colombier 	if (securemem)
536*da917039SDavid du Colombier 		print("; secure memory");
537*da917039SDavid du Colombier 	print("; caches %s\n", (caching? "on": "off"));
538*da917039SDavid du Colombier 	print("\n");
539*da917039SDavid du Colombier 	if ((uintptr)end < PHYSSRAM)
540*da917039SDavid du Colombier 		panic("too big; end %#p before sram @ %#ux", end, PHYSSRAM);
541*da917039SDavid du Colombier 	print("memory found: %,lud (%lux)\n", memsz, memsz);
542*da917039SDavid du Colombier 
543*da917039SDavid du Colombier 	spllo();
544*da917039SDavid du Colombier 	clockinit();
545*da917039SDavid du Colombier 	prcpuid();
546*da917039SDavid du Colombier //	etherinit();			/* probe() calls this */
547*da917039SDavid du Colombier 	kbdinit();
548*da917039SDavid du Colombier 
549*da917039SDavid du Colombier 	/*
550*da917039SDavid du Colombier 	 * find and read plan9.ini, setting configuration variables.
551*da917039SDavid du Colombier 	 */
552*da917039SDavid du Colombier 	tp = types;
553*da917039SDavid du Colombier //	debug = debugload = 1;		// DEBUG
554*da917039SDavid du Colombier 	if(pxe && (mp = probe(tp->type, Fini, Dany)) && mp->flag & Fini){
555*da917039SDavid du Colombier 		if (debug)
556*da917039SDavid du Colombier 			print("using %s!%s!%s\n", mp->name, mp->part, mp->ini);
557*da917039SDavid du Colombier //		iniread = !dotini(mp->inifs);
558*da917039SDavid du Colombier 	}
559*da917039SDavid du Colombier 
560*da917039SDavid du Colombier 	/*
561*da917039SDavid du Colombier 	 * we should now have read plan9.ini, if any.
562*da917039SDavid du Colombier 	 */
563*da917039SDavid du Colombier 	persist = getconf("*bootppersist");
564*da917039SDavid du Colombier 
565*da917039SDavid du Colombier 	tried = 0;
566*da917039SDavid du Colombier 	mode = Mauto;
567*da917039SDavid du Colombier 
568*da917039SDavid du Colombier 	p = getconf("bootfile");
569*da917039SDavid du Colombier 	if(p != 0) {
570*da917039SDavid du Colombier 		mode = Manual;
571*da917039SDavid du Colombier 		for(i = 0; i < NMode; i++){
572*da917039SDavid du Colombier 			if(strcmp(p, modes[i].name) == 0){
573*da917039SDavid du Colombier 				mode = modes[i].mode;
574*da917039SDavid du Colombier 				goto done;
575*da917039SDavid du Colombier 			}
576*da917039SDavid du Colombier 		}
577*da917039SDavid du Colombier 		if((mp = parse(p, &file)) == nil)
578*da917039SDavid du Colombier 			print("Unknown boot device: %s\n", p);
579*da917039SDavid du Colombier 		else
580*da917039SDavid du Colombier 			tried = boot(mp, file);
581*da917039SDavid du Colombier 	}
582*da917039SDavid du Colombier done:
583*da917039SDavid du Colombier 	if(tried == 0 && mode != Manual){
584*da917039SDavid du Colombier 		flag = Fany;
585*da917039SDavid du Colombier 		if(mode == Mlocal)
586*da917039SDavid du Colombier 			flag &= ~Fbootp;
587*da917039SDavid du Colombier 		if((mp = probe(Tany, flag, Dany)))
588*da917039SDavid du Colombier 			boot(mp, "");
589*da917039SDavid du Colombier 		if (debugload)
590*da917039SDavid du Colombier 			print("end auto probe\n");
591*da917039SDavid du Colombier 	}
592*da917039SDavid du Colombier 
593*da917039SDavid du Colombier 	def[0] = 0;
594*da917039SDavid du Colombier 	if(p = getconf("bootdef"))
595*da917039SDavid du Colombier 		strecpy(def, def + sizeof def, p);
596*da917039SDavid du Colombier 	flag = 0;
597*da917039SDavid du Colombier 	tp = types;
598*da917039SDavid du Colombier 	for(mp = tp->media; mp; mp = mp->next){
599*da917039SDavid du Colombier 		if(flag == 0){
600*da917039SDavid du Colombier 			flag = 1;
601*da917039SDavid du Colombier 			print("Boot devices:");
602*da917039SDavid du Colombier 		}
603*da917039SDavid du Colombier 		(*tp->printdevs)(mp->dev);
604*da917039SDavid du Colombier 	}
605*da917039SDavid du Colombier 	if(flag)
606*da917039SDavid du Colombier 		print("\n");
607*da917039SDavid du Colombier 
608*da917039SDavid du Colombier 	/*
609*da917039SDavid du Colombier 	 * e.g., *bootppersist=ether0
610*da917039SDavid du Colombier 	 *
611*da917039SDavid du Colombier 	 * previously, we looped in bootpopen if we were pxeload or if
612*da917039SDavid du Colombier 	 * *bootppersist was set.  that doesn't work well for pxeload where
613*da917039SDavid du Colombier 	 * bootp will never succeed on the first interface but only on another
614*da917039SDavid du Colombier 	 * interface.
615*da917039SDavid du Colombier 	 */
616*da917039SDavid du Colombier //print("boot mode %s\n", modes[mode].name);
617*da917039SDavid du Colombier 	if (mode == Mauto && persist != nil &&
618*da917039SDavid du Colombier 	    (mp = parse(persist, &file)) != nil) {
619*da917039SDavid du Colombier 		boot(mp, file);
620*da917039SDavid du Colombier 		print("pausing before retry...");
621*da917039SDavid du Colombier 		delay(30*1000);
622*da917039SDavid du Colombier 		print("\n");
623*da917039SDavid du Colombier 	}
624*da917039SDavid du Colombier 
625*da917039SDavid du Colombier 	for(;;){
626*da917039SDavid du Colombier 		if(getstr("boot from", line, sizeof(line), def,
627*da917039SDavid du Colombier 		    (mode != Manual)*15) >= 0)
628*da917039SDavid du Colombier 			if(mp = parse(line, &file))
629*da917039SDavid du Colombier 				boot(mp, file);
630*da917039SDavid du Colombier 		def[0] = 0;
631*da917039SDavid du Colombier 	}
632*da917039SDavid du Colombier }
633*da917039SDavid du Colombier 
634*da917039SDavid du Colombier int
getfields(char * lp,char ** fields,int n,char sep)635*da917039SDavid du Colombier getfields(char *lp, char **fields, int n, char sep)
636*da917039SDavid du Colombier {
637*da917039SDavid du Colombier 	int i;
638*da917039SDavid du Colombier 
639*da917039SDavid du Colombier 	for(i = 0; lp && *lp && i < n; i++){
640*da917039SDavid du Colombier 		while(*lp == sep)
641*da917039SDavid du Colombier 			*lp++ = 0;
642*da917039SDavid du Colombier 		if(*lp == 0)
643*da917039SDavid du Colombier 			break;
644*da917039SDavid du Colombier 		fields[i] = lp;
645*da917039SDavid du Colombier 		while(*lp && *lp != sep){
646*da917039SDavid du Colombier 			if(*lp == '\\' && *(lp+1) == '\n')
647*da917039SDavid du Colombier 				*lp++ = ' ';
648*da917039SDavid du Colombier 			lp++;
649*da917039SDavid du Colombier 		}
650*da917039SDavid du Colombier 	}
651*da917039SDavid du Colombier 	return i;
652*da917039SDavid du Colombier }
653*da917039SDavid du Colombier 
654*da917039SDavid du Colombier int
cistrcmp(char * a,char * b)655*da917039SDavid du Colombier cistrcmp(char *a, char *b)
656*da917039SDavid du Colombier {
657*da917039SDavid du Colombier 	int ac, bc;
658*da917039SDavid du Colombier 
659*da917039SDavid du Colombier 	for(;;){
660*da917039SDavid du Colombier 		ac = *a++;
661*da917039SDavid du Colombier 		bc = *b++;
662*da917039SDavid du Colombier 
663*da917039SDavid du Colombier 		if(ac >= 'A' && ac <= 'Z')
664*da917039SDavid du Colombier 			ac = 'a' + (ac - 'A');
665*da917039SDavid du Colombier 		if(bc >= 'A' && bc <= 'Z')
666*da917039SDavid du Colombier 			bc = 'a' + (bc - 'A');
667*da917039SDavid du Colombier 		ac -= bc;
668*da917039SDavid du Colombier 		if(ac)
669*da917039SDavid du Colombier 			return ac;
670*da917039SDavid du Colombier 		if(bc == 0)
671*da917039SDavid du Colombier 			break;
672*da917039SDavid du Colombier 	}
673*da917039SDavid du Colombier 	return 0;
674*da917039SDavid du Colombier }
675*da917039SDavid du Colombier 
676*da917039SDavid du Colombier int
cistrncmp(char * a,char * b,int n)677*da917039SDavid du Colombier cistrncmp(char *a, char *b, int n)
678*da917039SDavid du Colombier {
679*da917039SDavid du Colombier 	unsigned ac, bc;
680*da917039SDavid du Colombier 
681*da917039SDavid du Colombier 	while(n > 0){
682*da917039SDavid du Colombier 		ac = *a++;
683*da917039SDavid du Colombier 		bc = *b++;
684*da917039SDavid du Colombier 		n--;
685*da917039SDavid du Colombier 
686*da917039SDavid du Colombier 		if(ac >= 'A' && ac <= 'Z')
687*da917039SDavid du Colombier 			ac = 'a' + (ac - 'A');
688*da917039SDavid du Colombier 		if(bc >= 'A' && bc <= 'Z')
689*da917039SDavid du Colombier 			bc = 'a' + (bc - 'A');
690*da917039SDavid du Colombier 
691*da917039SDavid du Colombier 		ac -= bc;
692*da917039SDavid du Colombier 		if(ac)
693*da917039SDavid du Colombier 			return ac;
694*da917039SDavid du Colombier 		if(bc == 0)
695*da917039SDavid du Colombier 			break;
696*da917039SDavid du Colombier 	}
697*da917039SDavid du Colombier 
698*da917039SDavid du Colombier 	return 0;
699*da917039SDavid du Colombier }
700*da917039SDavid du Colombier 
701*da917039SDavid du Colombier #define PSTART		(8*MB)		/* start allocating here */
702*da917039SDavid du Colombier #define PEND		(100*MB)	/* below stack */
703*da917039SDavid du Colombier 
704*da917039SDavid du Colombier static ulong palloc = PSTART;
705*da917039SDavid du Colombier 
706*da917039SDavid du Colombier void*
ialloc(ulong n,int align)707*da917039SDavid du Colombier ialloc(ulong n, int align)
708*da917039SDavid du Colombier {
709*da917039SDavid du Colombier 	ulong p;
710*da917039SDavid du Colombier 	int a;
711*da917039SDavid du Colombier 
712*da917039SDavid du Colombier 	assert(palloc >= PSTART);
713*da917039SDavid du Colombier 	p = palloc;
714*da917039SDavid du Colombier 	if(align <= 0)
715*da917039SDavid du Colombier 		align = 4;
716*da917039SDavid du Colombier 	if(a = n % align)
717*da917039SDavid du Colombier 		n += align - a;
718*da917039SDavid du Colombier 	if(a = p % align)
719*da917039SDavid du Colombier 		p += align - a;
720*da917039SDavid du Colombier 
721*da917039SDavid du Colombier 	palloc = p+n;
722*da917039SDavid du Colombier 	if(palloc > PEND)
723*da917039SDavid du Colombier 		panic("ialloc(%lud, %d) called from %#p",
724*da917039SDavid du Colombier 			n, align, getcallerpc(&n));
725*da917039SDavid du Colombier 	return memset((void*)p, 0, n);
726*da917039SDavid du Colombier }
727*da917039SDavid du Colombier 
728*da917039SDavid du Colombier void*
xspanalloc(ulong size,int align,ulong span)729*da917039SDavid du Colombier xspanalloc(ulong size, int align, ulong span)
730*da917039SDavid du Colombier {
731*da917039SDavid du Colombier 	ulong a, v;
732*da917039SDavid du Colombier 
733*da917039SDavid du Colombier 	if((palloc + (size+align+span)) > PEND)
734*da917039SDavid du Colombier 		panic("xspanalloc(%lud, %d, 0x%lux) called from %#p",
735*da917039SDavid du Colombier 			size, align, span, getcallerpc(&size));
736*da917039SDavid du Colombier 
737*da917039SDavid du Colombier 	a = (ulong)ialloc(size+align+span, 0);
738*da917039SDavid du Colombier 
739*da917039SDavid du Colombier 	if(span > 2)
740*da917039SDavid du Colombier 		v = (a + span) & ~(span-1);
741*da917039SDavid du Colombier 	else
742*da917039SDavid du Colombier 		v = a;
743*da917039SDavid du Colombier 
744*da917039SDavid du Colombier 	if(align > 1)
745*da917039SDavid du Colombier 		v = (v + align) & ~(align-1);
746*da917039SDavid du Colombier 
747*da917039SDavid du Colombier 	return (void*)v;
748*da917039SDavid du Colombier }
749*da917039SDavid du Colombier 
750*da917039SDavid du Colombier static Block *allocbp;
751*da917039SDavid du Colombier 
752*da917039SDavid du Colombier Block*
allocb(int size)753*da917039SDavid du Colombier allocb(int size)
754*da917039SDavid du Colombier {
755*da917039SDavid du Colombier 	Block *bp, **lbp;
756*da917039SDavid du Colombier 	ulong addr;
757*da917039SDavid du Colombier 
758*da917039SDavid du Colombier 	lbp = &allocbp;
759*da917039SDavid du Colombier 	for(bp = *lbp; bp; bp = bp->next){
760*da917039SDavid du Colombier 		if((bp->lim - bp->base) >= size){
761*da917039SDavid du Colombier 			*lbp = bp->next;
762*da917039SDavid du Colombier 			break;
763*da917039SDavid du Colombier 		}
764*da917039SDavid du Colombier 		lbp = &bp->next;
765*da917039SDavid du Colombier 	}
766*da917039SDavid du Colombier 	if(bp == 0){
767*da917039SDavid du Colombier 		if((palloc + (sizeof(Block)+size+64)) > PEND)
768*da917039SDavid du Colombier 			panic("allocb(%d) called from %#p",
769*da917039SDavid du Colombier 				size, getcallerpc(&size));
770*da917039SDavid du Colombier 		bp = ialloc(sizeof(Block)+size+64, 0);
771*da917039SDavid du Colombier 		addr = (ulong)bp;
772*da917039SDavid du Colombier 		addr = ROUNDUP(addr + sizeof(Block), 8);
773*da917039SDavid du Colombier 		bp->base = (uchar*)addr;
774*da917039SDavid du Colombier 		bp->lim = ((uchar*)bp) + sizeof(Block)+size+64;
775*da917039SDavid du Colombier 	}
776*da917039SDavid du Colombier 
777*da917039SDavid du Colombier 	if(bp->flag)
778*da917039SDavid du Colombier 		panic("allocb reuse");
779*da917039SDavid du Colombier 
780*da917039SDavid du Colombier 	bp->rp = bp->base;
781*da917039SDavid du Colombier 	bp->wp = bp->rp;
782*da917039SDavid du Colombier 	bp->next = 0;
783*da917039SDavid du Colombier 	bp->flag = 1;
784*da917039SDavid du Colombier 
785*da917039SDavid du Colombier 	return bp;
786*da917039SDavid du Colombier }
787*da917039SDavid du Colombier 
788*da917039SDavid du Colombier void
freeb(Block * bp)789*da917039SDavid du Colombier freeb(Block* bp)
790*da917039SDavid du Colombier {
791*da917039SDavid du Colombier 	bp->next = allocbp;
792*da917039SDavid du Colombier 	allocbp = bp;
793*da917039SDavid du Colombier 
794*da917039SDavid du Colombier 	bp->flag = 0;
795*da917039SDavid du Colombier }
796*da917039SDavid du Colombier 
797*da917039SDavid du Colombier void (*etherdetach)(void);
798*da917039SDavid du Colombier 
799*da917039SDavid du Colombier void
warp9(ulong entry)800*da917039SDavid du Colombier warp9(ulong entry)
801*da917039SDavid du Colombier {
802*da917039SDavid du Colombier 	ulong inst;
803*da917039SDavid du Colombier 	ulong *mem;
804*da917039SDavid du Colombier 
805*da917039SDavid du Colombier 	if(etherdetach)
806*da917039SDavid du Colombier 		etherdetach();
807*da917039SDavid du Colombier //	consdrain();
808*da917039SDavid du Colombier 	delay(10);
809*da917039SDavid du Colombier 
810*da917039SDavid du Colombier 	splhi();
811*da917039SDavid du Colombier 	trapdisable();
812*da917039SDavid du Colombier 	coherence();
813*da917039SDavid du Colombier 	syncall();
814*da917039SDavid du Colombier 
815*da917039SDavid du Colombier 	qtmerrtest("syncs before kernel entry");
816*da917039SDavid du Colombier 	syncall();
817*da917039SDavid du Colombier 	putmsr(getmsr() & ~MSR_ME);	/* disable machine check traps */
818*da917039SDavid du Colombier 	syncall();
819*da917039SDavid du Colombier 	clrmchk();
820*da917039SDavid du Colombier 	syncall();
821*da917039SDavid du Colombier 
822*da917039SDavid du Colombier 	mem = (ulong *)PADDR(entry);
823*da917039SDavid du Colombier 	inst = *mem;
824*da917039SDavid du Colombier 	if (inst == 0)
825*da917039SDavid du Colombier 		panic("word at entry addr is zero, kernel not loaded");
826*da917039SDavid du Colombier 	/*
827*da917039SDavid du Colombier 	 * This is where to push things on the stack to
828*da917039SDavid du Colombier 	 * boot *BSD systems, e.g.
829*da917039SDavid du Colombier 	 * (*((void (*)(void*, void*, void*, void*, ulong, ulong))PADDR(entry)))
830*da917039SDavid du Colombier 	 *	(0, 0, 0, 0, 8196, 640);
831*da917039SDavid du Colombier 	 * will enable NetBSD boot (the real memory size needs to
832*da917039SDavid du Colombier 	 * go in the 5th argument).
833*da917039SDavid du Colombier 	 */
834*da917039SDavid du Colombier 	coherence();
835*da917039SDavid du Colombier 	syncall();
836*da917039SDavid du Colombier 	(*(void (*)(void))mem)();
837*da917039SDavid du Colombier 
838*da917039SDavid du Colombier 	for (;;)
839*da917039SDavid du Colombier 		;
840*da917039SDavid du Colombier }
841