xref: /plan9-contrib/sys/src/9/loongson64/main.c (revision 0c0b2b49cfb685ea1f1b8483a5cf30f72b8eb1f2)
1*0c0b2b49SDavid du Colombier #include "u.h"
2*0c0b2b49SDavid du Colombier #include "../port/lib.h"
3*0c0b2b49SDavid du Colombier #include "mem.h"
4*0c0b2b49SDavid du Colombier #include "dat.h"
5*0c0b2b49SDavid du Colombier #include "fns.h"
6*0c0b2b49SDavid du Colombier #include "io.h"
7*0c0b2b49SDavid du Colombier #include "../ip/ip.h"
8*0c0b2b49SDavid du Colombier #include <pool.h>
9*0c0b2b49SDavid du Colombier #include <tos.h>
10*0c0b2b49SDavid du Colombier #include <bootexec.h>
11*0c0b2b49SDavid du Colombier #include "init.h"
12*0c0b2b49SDavid du Colombier 
13*0c0b2b49SDavid du Colombier enum {
14*0c0b2b49SDavid du Colombier 	/* space for syscall args, return PC, top-of-stack struct */
15*0c0b2b49SDavid du Colombier 	Stkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
16*0c0b2b49SDavid du Colombier };
17*0c0b2b49SDavid du Colombier 
18*0c0b2b49SDavid du Colombier typedef struct mipsexec Mipsexec;
19*0c0b2b49SDavid du Colombier 
20*0c0b2b49SDavid du Colombier #define	MAXCONF		64
21*0c0b2b49SDavid du Colombier #define CONFBUFLEN	4096
22*0c0b2b49SDavid du Colombier #define MAXBOOTENV	256
23*0c0b2b49SDavid du Colombier 
24*0c0b2b49SDavid du Colombier /* only for reboot */
25*0c0b2b49SDavid du Colombier #define BOOTARGS	((char*)(CONFADDR))
26*0c0b2b49SDavid du Colombier #define BOOTARGSLEN	CONFBUFLEN
27*0c0b2b49SDavid du Colombier #define CONFARGVLEN	(MAXCONF*BY2WD)
28*0c0b2b49SDavid du Colombier 
29*0c0b2b49SDavid du Colombier /* args passed by boot loader for main(), addr in 32 bit */
30*0c0b2b49SDavid du Colombier int		_argc;
31*0c0b2b49SDavid du Colombier long	*_argv;
32*0c0b2b49SDavid du Colombier long	*_env;
33*0c0b2b49SDavid du Colombier static char *bootenvname[MAXBOOTENV];
34*0c0b2b49SDavid du Colombier static char *bootenvval[MAXBOOTENV];
35*0c0b2b49SDavid du Colombier static int 	nenv;
36*0c0b2b49SDavid du Colombier 
37*0c0b2b49SDavid du Colombier /* plan9.ini */
38*0c0b2b49SDavid du Colombier static char confbuf[CONFBUFLEN];
39*0c0b2b49SDavid du Colombier static char *confname[MAXCONF];
40*0c0b2b49SDavid du Colombier static char *confval[MAXCONF];
41*0c0b2b49SDavid du Colombier static int	nconf;
42*0c0b2b49SDavid du Colombier 
43*0c0b2b49SDavid du Colombier /*
44*0c0b2b49SDavid du Colombier  * Option arguments from the command line.
45*0c0b2b49SDavid du Colombier  * oargv[0] is the boot file.
46*0c0b2b49SDavid du Colombier  */
47*0c0b2b49SDavid du Colombier static int oargc;
48*0c0b2b49SDavid du Colombier static char* oargv[20];
49*0c0b2b49SDavid du Colombier static char oargb[128];
50*0c0b2b49SDavid du Colombier static int oargblen;
51*0c0b2b49SDavid du Colombier 
52*0c0b2b49SDavid du Colombier static uintptr sp;		/* XXX - must go - user stack of init proc */
53*0c0b2b49SDavid du Colombier 
54*0c0b2b49SDavid du Colombier /*
55*0c0b2b49SDavid du Colombier  * software tlb simulation
56*0c0b2b49SDavid du Colombier  */
57*0c0b2b49SDavid du Colombier static Softtlb stlb[MAXMACH][STLBSIZE];
58*0c0b2b49SDavid du Colombier 
59*0c0b2b49SDavid du Colombier Mach	*machaddr[MAXMACH];
60*0c0b2b49SDavid du Colombier Conf	conf;
61*0c0b2b49SDavid du Colombier ulong	memsize;
62*0c0b2b49SDavid du Colombier FPsave	initfp;
63*0c0b2b49SDavid du Colombier 
64*0c0b2b49SDavid du Colombier int normalprint;
65*0c0b2b49SDavid du Colombier ulong cpufreq;
66*0c0b2b49SDavid du Colombier 
67*0c0b2b49SDavid du Colombier /*
68*0c0b2b49SDavid du Colombier  *  initialize a processor's mach structure.  each processor does this
69*0c0b2b49SDavid du Colombier  *  for itself.
70*0c0b2b49SDavid du Colombier  */
71*0c0b2b49SDavid du Colombier void
machinit(void)72*0c0b2b49SDavid du Colombier machinit(void)
73*0c0b2b49SDavid du Colombier {
74*0c0b2b49SDavid du Colombier 	/* Ensure CU1 is off */
75*0c0b2b49SDavid du Colombier 	clrfpintr();
76*0c0b2b49SDavid du Colombier 
77*0c0b2b49SDavid du Colombier 	m->stb = &stlb[m->machno][0];
78*0c0b2b49SDavid du Colombier 
79*0c0b2b49SDavid du Colombier 	clockinit();
80*0c0b2b49SDavid du Colombier }
81*0c0b2b49SDavid du Colombier 
82*0c0b2b49SDavid du Colombier static void
optionsinit(char * s)83*0c0b2b49SDavid du Colombier optionsinit(char* s)
84*0c0b2b49SDavid du Colombier {
85*0c0b2b49SDavid du Colombier 	strecpy(oargb, oargb+sizeof(oargb), s);
86*0c0b2b49SDavid du Colombier 
87*0c0b2b49SDavid du Colombier 	oargblen = strlen(oargb);
88*0c0b2b49SDavid du Colombier 	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
89*0c0b2b49SDavid du Colombier 	oargv[oargc] = nil;
90*0c0b2b49SDavid du Colombier }
91*0c0b2b49SDavid du Colombier 
92*0c0b2b49SDavid du Colombier void
plan9iniinit(void)93*0c0b2b49SDavid du Colombier plan9iniinit(void)
94*0c0b2b49SDavid du Colombier {
95*0c0b2b49SDavid du Colombier 	char *cp;
96*0c0b2b49SDavid du Colombier 	int i;
97*0c0b2b49SDavid du Colombier 
98*0c0b2b49SDavid du Colombier 	nconf = 0;
99*0c0b2b49SDavid du Colombier 	if(_argv != nil){
100*0c0b2b49SDavid du Colombier 		memmove(confbuf, (char*)_argv[0], sizeof(confbuf));
101*0c0b2b49SDavid du Colombier 		for(i=1; i<_argc && nconf<MAXCONF; i++){
102*0c0b2b49SDavid du Colombier 			_argv[i] += (long)confbuf - _argv[0];
103*0c0b2b49SDavid du Colombier 			if(*(char*)_argv[i] == '#')
104*0c0b2b49SDavid du Colombier 				continue;
105*0c0b2b49SDavid du Colombier 			cp = strchr((char*)_argv[i], '=');
106*0c0b2b49SDavid du Colombier 			if(cp == nil)
107*0c0b2b49SDavid du Colombier 				continue;
108*0c0b2b49SDavid du Colombier 			*cp++ = '\0';
109*0c0b2b49SDavid du Colombier 			confname[nconf] = (char*)_argv[i];
110*0c0b2b49SDavid du Colombier 			confval[nconf] = cp;
111*0c0b2b49SDavid du Colombier 			nconf++;
112*0c0b2b49SDavid du Colombier 		}
113*0c0b2b49SDavid du Colombier 	}
114*0c0b2b49SDavid du Colombier 
115*0c0b2b49SDavid du Colombier 	nenv = 0;
116*0c0b2b49SDavid du Colombier 	if(_env != nil)
117*0c0b2b49SDavid du Colombier 		for(i=0; (char*)_env[i] != nil && nenv<MAXBOOTENV; i++){
118*0c0b2b49SDavid du Colombier 			if(*(char*)_env[i] == '#')
119*0c0b2b49SDavid du Colombier 				continue;
120*0c0b2b49SDavid du Colombier 			cp = strchr((char*)_env[i], '=');
121*0c0b2b49SDavid du Colombier 			if(cp == nil)
122*0c0b2b49SDavid du Colombier 				continue;
123*0c0b2b49SDavid du Colombier 			*cp++ = '\0';
124*0c0b2b49SDavid du Colombier 			bootenvname[nenv] = (char*)_env[i];
125*0c0b2b49SDavid du Colombier 			bootenvval[nenv] = cp;
126*0c0b2b49SDavid du Colombier 			nenv++;
127*0c0b2b49SDavid du Colombier 		}
128*0c0b2b49SDavid du Colombier }
129*0c0b2b49SDavid du Colombier 
130*0c0b2b49SDavid du Colombier static int
findconf(char * name)131*0c0b2b49SDavid du Colombier findconf(char *name)
132*0c0b2b49SDavid du Colombier {
133*0c0b2b49SDavid du Colombier 	int i;
134*0c0b2b49SDavid du Colombier 
135*0c0b2b49SDavid du Colombier 	for(i = 0; i < nconf; i++)
136*0c0b2b49SDavid du Colombier 		if(cistrcmp(confname[i], name) == 0)
137*0c0b2b49SDavid du Colombier 			return i;
138*0c0b2b49SDavid du Colombier 	return -1;
139*0c0b2b49SDavid du Colombier }
140*0c0b2b49SDavid du Colombier 
141*0c0b2b49SDavid du Colombier char*
getconf(char * name)142*0c0b2b49SDavid du Colombier getconf(char *name)
143*0c0b2b49SDavid du Colombier {
144*0c0b2b49SDavid du Colombier 	int i;
145*0c0b2b49SDavid du Colombier 
146*0c0b2b49SDavid du Colombier 	i = findconf(name);
147*0c0b2b49SDavid du Colombier 	if(i >= 0)
148*0c0b2b49SDavid du Colombier 		return confval[i];
149*0c0b2b49SDavid du Colombier 	return nil;
150*0c0b2b49SDavid du Colombier }
151*0c0b2b49SDavid du Colombier 
152*0c0b2b49SDavid du Colombier static int
findbootenv(char * name)153*0c0b2b49SDavid du Colombier findbootenv(char *name)
154*0c0b2b49SDavid du Colombier {
155*0c0b2b49SDavid du Colombier 	int i;
156*0c0b2b49SDavid du Colombier 
157*0c0b2b49SDavid du Colombier 	for(i = 0; i < nenv; i++)
158*0c0b2b49SDavid du Colombier 		if(cistrcmp(bootenvname[i], name) == 0)
159*0c0b2b49SDavid du Colombier 			return i;
160*0c0b2b49SDavid du Colombier 	return -1;
161*0c0b2b49SDavid du Colombier }
162*0c0b2b49SDavid du Colombier 
163*0c0b2b49SDavid du Colombier static char*
getbootenv(char * name)164*0c0b2b49SDavid du Colombier getbootenv(char *name)
165*0c0b2b49SDavid du Colombier {
166*0c0b2b49SDavid du Colombier 	int i;
167*0c0b2b49SDavid du Colombier 
168*0c0b2b49SDavid du Colombier 	i = findbootenv(name);
169*0c0b2b49SDavid du Colombier 	if(i >= 0)
170*0c0b2b49SDavid du Colombier 		return bootenvval[i];
171*0c0b2b49SDavid du Colombier 	return nil;
172*0c0b2b49SDavid du Colombier }
173*0c0b2b49SDavid du Colombier 
174*0c0b2b49SDavid du Colombier void
confinit(void)175*0c0b2b49SDavid du Colombier confinit(void)
176*0c0b2b49SDavid du Colombier {
177*0c0b2b49SDavid du Colombier 	char *p;
178*0c0b2b49SDavid du Colombier 	int i;
179*0c0b2b49SDavid du Colombier 	ulong kpages, ktop;
180*0c0b2b49SDavid du Colombier 	ulong maxmem, highmemsize;
181*0c0b2b49SDavid du Colombier 
182*0c0b2b49SDavid du Colombier 	/* memory size */
183*0c0b2b49SDavid du Colombier 	memsize = MEMSIZE;
184*0c0b2b49SDavid du Colombier 	if((p = getbootenv("memsize")) != nil)
185*0c0b2b49SDavid du Colombier 		memsize = strtoul(p, 0, 0) * MB;
186*0c0b2b49SDavid du Colombier 	highmemsize = 0;
187*0c0b2b49SDavid du Colombier 	if((p = getbootenv("highmemsize")) != nil)
188*0c0b2b49SDavid du Colombier 		highmemsize = strtoul(p, 0, 0) * MB;
189*0c0b2b49SDavid du Colombier 	if((p = getconf("*maxmem")) != nil){
190*0c0b2b49SDavid du Colombier 		maxmem = strtoul(p, 0, 0);
191*0c0b2b49SDavid du Colombier 		memsize = MIN(memsize, maxmem);
192*0c0b2b49SDavid du Colombier 		maxmem -= memsize;
193*0c0b2b49SDavid du Colombier 		highmemsize = MIN(highmemsize, maxmem);
194*0c0b2b49SDavid du Colombier 		if(memsize < 16*MB)		/* sanity */
195*0c0b2b49SDavid du Colombier 			memsize = 16*MB;
196*0c0b2b49SDavid du Colombier 	}
197*0c0b2b49SDavid du Colombier 
198*0c0b2b49SDavid du Colombier 	/* set up other configuration parameters */
199*0c0b2b49SDavid du Colombier 	conf.nproc = 2000;
200*0c0b2b49SDavid du Colombier 	conf.nswap = 262144;
201*0c0b2b49SDavid du Colombier 	conf.nswppo = 4096;
202*0c0b2b49SDavid du Colombier 	conf.nimage = 200;
203*0c0b2b49SDavid du Colombier 
204*0c0b2b49SDavid du Colombier 	/*
205*0c0b2b49SDavid du Colombier 	 *  divide memory to user pages and kernel.
206*0c0b2b49SDavid du Colombier 	 */
207*0c0b2b49SDavid du Colombier 	conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
208*0c0b2b49SDavid du Colombier 	conf.mem[0].npage = memsize/BY2PG - ktop/BY2PG;
209*0c0b2b49SDavid du Colombier 
210*0c0b2b49SDavid du Colombier 	conf.mem[1].base = HIGHMEM;
211*0c0b2b49SDavid du Colombier 	conf.mem[1].npage = highmemsize/BY2PG;
212*0c0b2b49SDavid du Colombier 
213*0c0b2b49SDavid du Colombier 	conf.npage = 0;
214*0c0b2b49SDavid du Colombier 	for(i=0; i<nelem(conf.mem); i++)
215*0c0b2b49SDavid du Colombier 		conf.npage += conf.mem[i].npage;
216*0c0b2b49SDavid du Colombier 
217*0c0b2b49SDavid du Colombier 	kpages = conf.npage - (conf.npage*80)/100;
218*0c0b2b49SDavid du Colombier 	if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
219*0c0b2b49SDavid du Colombier 		kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
220*0c0b2b49SDavid du Colombier 		kpages += (conf.nproc*KSTACK)/BY2PG;
221*0c0b2b49SDavid du Colombier 	}
222*0c0b2b49SDavid du Colombier 	conf.upages = conf.npage - kpages;
223*0c0b2b49SDavid du Colombier 	conf.ialloc = (kpages/2)*BY2PG;
224*0c0b2b49SDavid du Colombier 
225*0c0b2b49SDavid du Colombier 	kpages *= BY2PG;
226*0c0b2b49SDavid du Colombier 	kpages -= conf.upages*sizeof(Page)
227*0c0b2b49SDavid du Colombier 		+ conf.nproc*sizeof(Proc)
228*0c0b2b49SDavid du Colombier 		+ conf.nimage*sizeof(Image)
229*0c0b2b49SDavid du Colombier 		+ conf.nswap
230*0c0b2b49SDavid du Colombier 		+ conf.nswppo*sizeof(Page);
231*0c0b2b49SDavid du Colombier 	mainmem->maxsize = kpages;
232*0c0b2b49SDavid du Colombier 
233*0c0b2b49SDavid du Colombier 	/*
234*0c0b2b49SDavid du Colombier 	 *  set up CPU's mach structure
235*0c0b2b49SDavid du Colombier 	 *  cpu0's was zeroed in main() and our stack is in Mach, so don't zero it.
236*0c0b2b49SDavid du Colombier 	 */
237*0c0b2b49SDavid du Colombier 	m->machno = 0;
238*0c0b2b49SDavid du Colombier 	m->hz = cpufreq;		/* initial guess at MHz */
239*0c0b2b49SDavid du Colombier 	m->speed = m->hz / Mhz;
240*0c0b2b49SDavid du Colombier 	conf.nmach = 1;
241*0c0b2b49SDavid du Colombier 
242*0c0b2b49SDavid du Colombier 	conf.nuart = 1;
243*0c0b2b49SDavid du Colombier 	conf.copymode = 0;		/* copy on write */
244*0c0b2b49SDavid du Colombier }
245*0c0b2b49SDavid du Colombier 
246*0c0b2b49SDavid du Colombier void
procrestore(Proc * p)247*0c0b2b49SDavid du Colombier procrestore(Proc *p)
248*0c0b2b49SDavid du Colombier {
249*0c0b2b49SDavid du Colombier 	uvlong t;
250*0c0b2b49SDavid du Colombier 
251*0c0b2b49SDavid du Colombier 	if(p->kp)
252*0c0b2b49SDavid du Colombier 		return;
253*0c0b2b49SDavid du Colombier 	cycles(&t);
254*0c0b2b49SDavid du Colombier 	p->pcycles -= t;
255*0c0b2b49SDavid du Colombier }
256*0c0b2b49SDavid du Colombier 
257*0c0b2b49SDavid du Colombier /*
258*0c0b2b49SDavid du Colombier  *  Save the mach dependent part of the process state.
259*0c0b2b49SDavid du Colombier  */
260*0c0b2b49SDavid du Colombier void
procsave(Proc * p)261*0c0b2b49SDavid du Colombier procsave(Proc *p)
262*0c0b2b49SDavid du Colombier {
263*0c0b2b49SDavid du Colombier 	uvlong t;
264*0c0b2b49SDavid du Colombier 
265*0c0b2b49SDavid du Colombier 	cycles(&t);
266*0c0b2b49SDavid du Colombier 	p->pcycles += t;
267*0c0b2b49SDavid du Colombier 	//fpuprocsave(); // XXX
268*0c0b2b49SDavid du Colombier }
269*0c0b2b49SDavid du Colombier 
270*0c0b2b49SDavid du Colombier static void
fmtinit(void)271*0c0b2b49SDavid du Colombier fmtinit(void)
272*0c0b2b49SDavid du Colombier {
273*0c0b2b49SDavid du Colombier 	printinit();
274*0c0b2b49SDavid du Colombier 	quotefmtinstall();
275*0c0b2b49SDavid du Colombier 	/* ipreset installs these when chandevreset runs */
276*0c0b2b49SDavid du Colombier 	fmtinstall('i', eipfmt);
277*0c0b2b49SDavid du Colombier 	fmtinstall('I', eipfmt);
278*0c0b2b49SDavid du Colombier 	fmtinstall('E', eipfmt);
279*0c0b2b49SDavid du Colombier 	fmtinstall('V', eipfmt);
280*0c0b2b49SDavid du Colombier 	fmtinstall('M', eipfmt);
281*0c0b2b49SDavid du Colombier }
282*0c0b2b49SDavid du Colombier 
283*0c0b2b49SDavid du Colombier /*
284*0c0b2b49SDavid du Colombier  *  setup MIPS trap vectors
285*0c0b2b49SDavid du Colombier  */
286*0c0b2b49SDavid du Colombier void
vecinit(void)287*0c0b2b49SDavid du Colombier vecinit(void)
288*0c0b2b49SDavid du Colombier {
289*0c0b2b49SDavid du Colombier 	memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
290*0c0b2b49SDavid du Colombier 	memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
291*0c0b2b49SDavid du Colombier 	memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
292*0c0b2b49SDavid du Colombier 	memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
293*0c0b2b49SDavid du Colombier 	/* 0x200 not used in looongson 2e */
294*0c0b2b49SDavid du Colombier 	icflush((ulong*)UTLBMISS, 4*1024);
295*0c0b2b49SDavid du Colombier 
296*0c0b2b49SDavid du Colombier 	setstatus(getstatus() & ~BEV);
297*0c0b2b49SDavid du Colombier }
298*0c0b2b49SDavid du Colombier 
299*0c0b2b49SDavid du Colombier static void
prcpuid(void)300*0c0b2b49SDavid du Colombier prcpuid(void)
301*0c0b2b49SDavid du Colombier {
302*0c0b2b49SDavid du Colombier 	ulong cpuid, cfg;
303*0c0b2b49SDavid du Colombier 	char *cpu;
304*0c0b2b49SDavid du Colombier 
305*0c0b2b49SDavid du Colombier 	cpuid = prid();
306*0c0b2b49SDavid du Colombier 	cfg = getconfig();
307*0c0b2b49SDavid du Colombier 	if (((cpuid>>16) & MASK(8)) == 0)		/* vendor */
308*0c0b2b49SDavid du Colombier 		cpu = "old mips";
309*0c0b2b49SDavid du Colombier 	else if (((cpuid>>16) & MASK(8)) == 1)
310*0c0b2b49SDavid du Colombier 		switch ((cpuid>>8) & MASK(8)) {		/* processor */
311*0c0b2b49SDavid du Colombier 		case 0x93:
312*0c0b2b49SDavid du Colombier 			cpu = "mips 24k";
313*0c0b2b49SDavid du Colombier 			break;
314*0c0b2b49SDavid du Colombier 		case 0x96:
315*0c0b2b49SDavid du Colombier 			cpu = "mips 24ke";
316*0c0b2b49SDavid du Colombier 			break;
317*0c0b2b49SDavid du Colombier 		default:
318*0c0b2b49SDavid du Colombier 			cpu = "mips";
319*0c0b2b49SDavid du Colombier 			break;
320*0c0b2b49SDavid du Colombier 		}
321*0c0b2b49SDavid du Colombier 	else
322*0c0b2b49SDavid du Colombier 		cpu = "other mips";
323*0c0b2b49SDavid du Colombier 	delay(200);
324*0c0b2b49SDavid du Colombier 	print("cpu%d: %ldMHz %s %se 0x%ulx v%ld.%ld rev %ld has fpu\n",
325*0c0b2b49SDavid du Colombier 		m->machno, m->hz / Mhz, cpu, cfg & (1<<15)? "b": "l",
326*0c0b2b49SDavid du Colombier 		(cpuid>>8) & MASK(8), (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3),
327*0c0b2b49SDavid du Colombier 		cpuid & MASK(2));
328*0c0b2b49SDavid du Colombier 	delay(200);
329*0c0b2b49SDavid du Colombier 
330*0c0b2b49SDavid du Colombier 	print("cpu%d: %d tlb entries, using %dK pages\n", m->machno,
331*0c0b2b49SDavid du Colombier 		64, BY2PG/1024);
332*0c0b2b49SDavid du Colombier 	delay(50);
333*0c0b2b49SDavid du Colombier 	print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
334*0c0b2b49SDavid du Colombier 		32 << ((cfg>>9) & MASK(3)));
335*0c0b2b49SDavid du Colombier 	delay(50);
336*0c0b2b49SDavid du Colombier 	print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
337*0c0b2b49SDavid du Colombier 		32 << ((cfg>>6) & MASK(3)));
338*0c0b2b49SDavid du Colombier 	delay(500);
339*0c0b2b49SDavid du Colombier }
340*0c0b2b49SDavid du Colombier 
341*0c0b2b49SDavid du Colombier static int
ckpagemask(ulong mask,ulong size)342*0c0b2b49SDavid du Colombier ckpagemask(ulong mask, ulong size)
343*0c0b2b49SDavid du Colombier {
344*0c0b2b49SDavid du Colombier 	int s;
345*0c0b2b49SDavid du Colombier 	ulong pm;
346*0c0b2b49SDavid du Colombier 
347*0c0b2b49SDavid du Colombier 	s = splhi();
348*0c0b2b49SDavid du Colombier 	setpagemask(mask);
349*0c0b2b49SDavid du Colombier 	pm = getpagemask();
350*0c0b2b49SDavid du Colombier 	splx(s);
351*0c0b2b49SDavid du Colombier 	if(pm != mask){
352*0c0b2b49SDavid du Colombier 		iprint("page size %ldK not supported on this cpu; "
353*0c0b2b49SDavid du Colombier 			"mask %#lux read back as %#lux\n", size/1024, mask, pm);
354*0c0b2b49SDavid du Colombier 		return -1;
355*0c0b2b49SDavid du Colombier 	}
356*0c0b2b49SDavid du Colombier 	return 0;
357*0c0b2b49SDavid du Colombier }
358*0c0b2b49SDavid du Colombier 
359*0c0b2b49SDavid du Colombier void
init0(void)360*0c0b2b49SDavid du Colombier init0(void)
361*0c0b2b49SDavid du Colombier {
362*0c0b2b49SDavid du Colombier 	char buf[128];
363*0c0b2b49SDavid du Colombier 	int i;
364*0c0b2b49SDavid du Colombier 
365*0c0b2b49SDavid du Colombier 	up->nerrlab = 0;
366*0c0b2b49SDavid du Colombier 
367*0c0b2b49SDavid du Colombier 	spllo();
368*0c0b2b49SDavid du Colombier 
369*0c0b2b49SDavid du Colombier 	/*
370*0c0b2b49SDavid du Colombier 	 * These are o.k. because rootinit is null.
371*0c0b2b49SDavid du Colombier 	 * Then early kproc's will have a root and dot.
372*0c0b2b49SDavid du Colombier 	 */
373*0c0b2b49SDavid du Colombier 	up->slash = namec("#/", Atodir, 0, 0);
374*0c0b2b49SDavid du Colombier 	pathclose(up->slash->path);
375*0c0b2b49SDavid du Colombier 	up->slash->path = newpath("/");
376*0c0b2b49SDavid du Colombier 	up->dot = cclone(up->slash);
377*0c0b2b49SDavid du Colombier 
378*0c0b2b49SDavid du Colombier 	chandevinit();
379*0c0b2b49SDavid du Colombier 
380*0c0b2b49SDavid du Colombier 	if(!waserror()){
381*0c0b2b49SDavid du Colombier 		ksetenv("cputype", "spim64", 0);
382*0c0b2b49SDavid du Colombier 		snprint(buf, sizeof buf, "spim64 %s loongson 2f", conffile);
383*0c0b2b49SDavid du Colombier 		ksetenv("terminal", buf, 0);
384*0c0b2b49SDavid du Colombier 		if(cpuserver)
385*0c0b2b49SDavid du Colombier 			ksetenv("service", "cpu", 0);
386*0c0b2b49SDavid du Colombier 		else
387*0c0b2b49SDavid du Colombier 			ksetenv("service", "terminal", 0);
388*0c0b2b49SDavid du Colombier //		ksetenv("nobootprompt", "local!/boot/bzroot", 0); // for bzroot
389*0c0b2b49SDavid du Colombier 		ksetenv("nvram", "/boot/nvram", 0);
390*0c0b2b49SDavid du Colombier 		/* convert plan9.ini variables to #e and #ec */
391*0c0b2b49SDavid du Colombier 		for(i = 0; i < nconf; i++) {
392*0c0b2b49SDavid du Colombier 			if(*confname[i] == '*')
393*0c0b2b49SDavid du Colombier 				continue;
394*0c0b2b49SDavid du Colombier 			ksetenv(confname[i], confval[i], 0);
395*0c0b2b49SDavid du Colombier 			ksetenv(confname[i], confval[i], 1);
396*0c0b2b49SDavid du Colombier 		}
397*0c0b2b49SDavid du Colombier 		poperror();
398*0c0b2b49SDavid du Colombier 	}
399*0c0b2b49SDavid du Colombier 	kproc("alarm", alarmkproc, 0);
400*0c0b2b49SDavid du Colombier //	i8250console();
401*0c0b2b49SDavid du Colombier 	touser(sp);
402*0c0b2b49SDavid du Colombier }
403*0c0b2b49SDavid du Colombier 
404*0c0b2b49SDavid du Colombier static void
bootargs(uintptr base)405*0c0b2b49SDavid du Colombier bootargs(uintptr base)
406*0c0b2b49SDavid du Colombier {
407*0c0b2b49SDavid du Colombier 	int i;
408*0c0b2b49SDavid du Colombier 	uintptr ssize;
409*0c0b2b49SDavid du Colombier 	char **av, *p;
410*0c0b2b49SDavid du Colombier 
411*0c0b2b49SDavid du Colombier 	/*
412*0c0b2b49SDavid du Colombier 	 * Push the boot args onto the stack.
413*0c0b2b49SDavid du Colombier 	 * The initial value of the user stack must be such
414*0c0b2b49SDavid du Colombier 	 * that the total used is larger than the maximum size
415*0c0b2b49SDavid du Colombier 	 * of the argument list checked in syscall.
416*0c0b2b49SDavid du Colombier 	 */
417*0c0b2b49SDavid du Colombier 	i = oargblen+1;
418*0c0b2b49SDavid du Colombier 	p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));
419*0c0b2b49SDavid du Colombier 	memmove(p, oargb, i);
420*0c0b2b49SDavid du Colombier 
421*0c0b2b49SDavid du Colombier 	/*
422*0c0b2b49SDavid du Colombier 	 * Now push the argv pointers.
423*0c0b2b49SDavid du Colombier 	 * The code jumped to by touser in l.s expects arguments
424*0c0b2b49SDavid du Colombier 	 *	main(char* argv0, ...)
425*0c0b2b49SDavid du Colombier 	 * and calls
426*0c0b2b49SDavid du Colombier 	 * 	startboot("/boot/boot", &argv0)
427*0c0b2b49SDavid du Colombier 	 * not the usual (int argc, char* argv[])
428*0c0b2b49SDavid du Colombier 	 */
429*0c0b2b49SDavid du Colombier 	av = (char**)(p - (oargc+1)*sizeof(char*));
430*0c0b2b49SDavid du Colombier 	ssize = base + BY2PG - PTR2UINT(av);
431*0c0b2b49SDavid du Colombier 	for(i = 0; i < oargc; i++)
432*0c0b2b49SDavid du Colombier 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
433*0c0b2b49SDavid du Colombier 	*av = nil;
434*0c0b2b49SDavid du Colombier 	sp = USTKTOP - ssize;
435*0c0b2b49SDavid du Colombier }
436*0c0b2b49SDavid du Colombier 
437*0c0b2b49SDavid du Colombier void
userinit(void)438*0c0b2b49SDavid du Colombier userinit(void)
439*0c0b2b49SDavid du Colombier {
440*0c0b2b49SDavid du Colombier 	Proc *p;
441*0c0b2b49SDavid du Colombier 	KMap *k;
442*0c0b2b49SDavid du Colombier 	Page *pg;
443*0c0b2b49SDavid du Colombier 	Segment *s;
444*0c0b2b49SDavid du Colombier 
445*0c0b2b49SDavid du Colombier 	p = newproc();
446*0c0b2b49SDavid du Colombier 	p->pgrp = newpgrp();
447*0c0b2b49SDavid du Colombier 	p->egrp = smalloc(sizeof(Egrp));
448*0c0b2b49SDavid du Colombier 	p->egrp->ref = 1;
449*0c0b2b49SDavid du Colombier 	p->fgrp = dupfgrp(nil);
450*0c0b2b49SDavid du Colombier 	p->rgrp = newrgrp();
451*0c0b2b49SDavid du Colombier 	p->procmode = 0640;
452*0c0b2b49SDavid du Colombier 
453*0c0b2b49SDavid du Colombier 	kstrdup(&eve, "");
454*0c0b2b49SDavid du Colombier 	kstrdup(&p->text, "*init*");
455*0c0b2b49SDavid du Colombier 	kstrdup(&p->user, eve);
456*0c0b2b49SDavid du Colombier 
457*0c0b2b49SDavid du Colombier 	p->fpstate = FPinit;
458*0c0b2b49SDavid du Colombier 	p->fpsave.fpstatus = initfp.fpstatus;
459*0c0b2b49SDavid du Colombier 
460*0c0b2b49SDavid du Colombier 	/*
461*0c0b2b49SDavid du Colombier 	 * Kernel Stack
462*0c0b2b49SDavid du Colombier 	 */
463*0c0b2b49SDavid du Colombier 	p->sched.pc = (uintptr)init0;
464*0c0b2b49SDavid du Colombier 	p->sched.sp = (uintptr)p->kstack+KSTACK-Stkheadroom;
465*0c0b2b49SDavid du Colombier 	p->sched.sp = STACKALIGN(p->sched.sp);
466*0c0b2b49SDavid du Colombier 
467*0c0b2b49SDavid du Colombier 	/*
468*0c0b2b49SDavid du Colombier 	 * User Stack
469*0c0b2b49SDavid du Colombier 	 *
470*0c0b2b49SDavid du Colombier 	 * Technically, newpage can't be called here because it
471*0c0b2b49SDavid du Colombier 	 * should only be called when in a user context as it may
472*0c0b2b49SDavid du Colombier 	 * try to sleep if there are no pages available, but that
473*0c0b2b49SDavid du Colombier 	 * shouldn't be the case here.
474*0c0b2b49SDavid du Colombier 	 */
475*0c0b2b49SDavid du Colombier 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
476*0c0b2b49SDavid du Colombier 	p->seg[SSEG] = s;
477*0c0b2b49SDavid du Colombier 	pg = newpage(1, 0, USTKTOP-BY2PG);
478*0c0b2b49SDavid du Colombier 	memset(pg->cachectl, PG_DATFLUSH, sizeof(pg->cachectl));
479*0c0b2b49SDavid du Colombier 	segpage(s, pg);
480*0c0b2b49SDavid du Colombier 	k = kmap(pg);
481*0c0b2b49SDavid du Colombier 	bootargs(VA(k));
482*0c0b2b49SDavid du Colombier 	kunmap(k);
483*0c0b2b49SDavid du Colombier 
484*0c0b2b49SDavid du Colombier 	/*
485*0c0b2b49SDavid du Colombier 	 * Text
486*0c0b2b49SDavid du Colombier 	 */
487*0c0b2b49SDavid du Colombier 	s = newseg(SG_TEXT, UTZERO, 1);
488*0c0b2b49SDavid du Colombier 	s->flushme++;
489*0c0b2b49SDavid du Colombier 	p->seg[TSEG] = s;
490*0c0b2b49SDavid du Colombier 	pg = newpage(1, 0, UTZERO);
491*0c0b2b49SDavid du Colombier 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
492*0c0b2b49SDavid du Colombier 	segpage(s, pg);
493*0c0b2b49SDavid du Colombier 	k = kmap(s->map[0]->pages[0]);
494*0c0b2b49SDavid du Colombier 	memset((void*)VA(k), 0, BY2PG);
495*0c0b2b49SDavid du Colombier 	memmove((ulong*)VA(k), initcode, sizeof initcode);
496*0c0b2b49SDavid du Colombier 	kunmap(k);
497*0c0b2b49SDavid du Colombier 
498*0c0b2b49SDavid du Colombier 	ready(p);
499*0c0b2b49SDavid du Colombier }
500*0c0b2b49SDavid du Colombier 
501*0c0b2b49SDavid du Colombier /* called from rebootcmd() */
502*0c0b2b49SDavid du Colombier int
parsemipsboothdr(Chan * c,ulong magic,Execvals * evp)503*0c0b2b49SDavid du Colombier parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
504*0c0b2b49SDavid du Colombier {
505*0c0b2b49SDavid du Colombier 	long extra;
506*0c0b2b49SDavid du Colombier 	Mipsexec me;
507*0c0b2b49SDavid du Colombier 
508*0c0b2b49SDavid du Colombier 	/*
509*0c0b2b49SDavid du Colombier 	 * BOOT_MAGIC is sometimes defined like this:
510*0c0b2b49SDavid du Colombier 	 * #define BOOT_MAGIC	(0x160<<16) || magic == ((0x160<<16)|3)
511*0c0b2b49SDavid du Colombier 	 * so we can only use it in a fairly stylized manner.
512*0c0b2b49SDavid du Colombier 	 */
513*0c0b2b49SDavid du Colombier 	if(magic == BOOT_MAGIC) {
514*0c0b2b49SDavid du Colombier 		c->offset = 0;			/* back up */
515*0c0b2b49SDavid du Colombier 		readn(c, &me, sizeof me);
516*0c0b2b49SDavid du Colombier 		/* if binary is -H1, read an extra long */
517*0c0b2b49SDavid du Colombier 		if (l2be(me.amagic) == 0407 && me.nscns == 0)
518*0c0b2b49SDavid du Colombier 			readn(c, &extra, sizeof extra);
519*0c0b2b49SDavid du Colombier 		evp->entry = l2be(me.mentry);
520*0c0b2b49SDavid du Colombier 		evp->textsize = l2be(me.tsize);
521*0c0b2b49SDavid du Colombier 		evp->datasize = l2be(me.dsize);
522*0c0b2b49SDavid du Colombier 		return 0;
523*0c0b2b49SDavid du Colombier 	} else
524*0c0b2b49SDavid du Colombier 		return -1;
525*0c0b2b49SDavid du Colombier }
526*0c0b2b49SDavid du Colombier 
527*0c0b2b49SDavid du Colombier void
main(void)528*0c0b2b49SDavid du Colombier main(void)
529*0c0b2b49SDavid du Colombier {
530*0c0b2b49SDavid du Colombier 	extern char edata[], end[];
531*0c0b2b49SDavid du Colombier 
532*0c0b2b49SDavid du Colombier 	m = (Mach*)MACHADDR;
533*0c0b2b49SDavid du Colombier 	memset(m, 0, sizeof(Mach));		/* clear Mach */
534*0c0b2b49SDavid du Colombier 	m->machno = 0;
535*0c0b2b49SDavid du Colombier 	machaddr[m->machno] = m;
536*0c0b2b49SDavid du Colombier 	up = nil;
537*0c0b2b49SDavid du Colombier 	memset(edata, 0, end-edata);	/* clear bss */
538*0c0b2b49SDavid du Colombier 
539*0c0b2b49SDavid du Colombier 	optionsinit("/boot/boot boot");
540*0c0b2b49SDavid du Colombier 	plan9iniinit();
541*0c0b2b49SDavid du Colombier 	confinit();
542*0c0b2b49SDavid du Colombier 	savefpregs(&initfp);
543*0c0b2b49SDavid du Colombier 
544*0c0b2b49SDavid du Colombier 	machinit();
545*0c0b2b49SDavid du Colombier 	active.exiting = 0;
546*0c0b2b49SDavid du Colombier 	active.machs = 1;
547*0c0b2b49SDavid du Colombier 
548*0c0b2b49SDavid du Colombier 	kmapinit();
549*0c0b2b49SDavid du Colombier 	xinit();
550*0c0b2b49SDavid du Colombier 	screeninit();
551*0c0b2b49SDavid du Colombier 
552*0c0b2b49SDavid du Colombier 	ckpagemask(PGSZ, BY2PG);
553*0c0b2b49SDavid du Colombier 	tlbinit();
554*0c0b2b49SDavid du Colombier 	machwire();
555*0c0b2b49SDavid du Colombier 
556*0c0b2b49SDavid du Colombier 	timersinit();
557*0c0b2b49SDavid du Colombier 	fmtinit();
558*0c0b2b49SDavid du Colombier 	vecinit();
559*0c0b2b49SDavid du Colombier 
560*0c0b2b49SDavid du Colombier 	normalprint = 1;
561*0c0b2b49SDavid du Colombier 	print("\nPlan 9\n");
562*0c0b2b49SDavid du Colombier 	prcpuid();
563*0c0b2b49SDavid du Colombier 	if(PTECACHABILITY == PTENONCOHERWT)
564*0c0b2b49SDavid du Colombier 		print("caches configured as write-through\n");
565*0c0b2b49SDavid du Colombier //	xsummary();
566*0c0b2b49SDavid du Colombier 
567*0c0b2b49SDavid du Colombier 	i8259init();
568*0c0b2b49SDavid du Colombier 	kbdinit();
569*0c0b2b49SDavid du Colombier 	if(conf.monitor)
570*0c0b2b49SDavid du Colombier 		swcursorinit();
571*0c0b2b49SDavid du Colombier 
572*0c0b2b49SDavid du Colombier 	pageinit();
573*0c0b2b49SDavid du Colombier 	procinit0();
574*0c0b2b49SDavid du Colombier 	initseg();
575*0c0b2b49SDavid du Colombier 	links();
576*0c0b2b49SDavid du Colombier 	chandevreset();
577*0c0b2b49SDavid du Colombier 
578*0c0b2b49SDavid du Colombier 	swapinit();
579*0c0b2b49SDavid du Colombier 	userinit();
580*0c0b2b49SDavid du Colombier 	parseboothdr = parsemipsboothdr;
581*0c0b2b49SDavid du Colombier 	schedinit();
582*0c0b2b49SDavid du Colombier 	panic("schedinit returned");
583*0c0b2b49SDavid du Colombier }
584*0c0b2b49SDavid du Colombier 
585*0c0b2b49SDavid du Colombier static void
writeconf(void)586*0c0b2b49SDavid du Colombier writeconf(void)
587*0c0b2b49SDavid du Colombier {
588*0c0b2b49SDavid du Colombier 	char *p, *q;
589*0c0b2b49SDavid du Colombier 	int n;
590*0c0b2b49SDavid du Colombier 
591*0c0b2b49SDavid du Colombier 	p = getconfenv();
592*0c0b2b49SDavid du Colombier 
593*0c0b2b49SDavid du Colombier 	if(waserror()) {
594*0c0b2b49SDavid du Colombier 		free(p);
595*0c0b2b49SDavid du Colombier 		nexterror();
596*0c0b2b49SDavid du Colombier 	}
597*0c0b2b49SDavid du Colombier 
598*0c0b2b49SDavid du Colombier 	/* convert to name=value\0 format */
599*0c0b2b49SDavid du Colombier 	_argc = 1;		/* skip _argv[0] */
600*0c0b2b49SDavid du Colombier 	_argv = (void*)CONFARGV;
601*0c0b2b49SDavid du Colombier 	_argv[0] = (long)BOOTARGS;
602*0c0b2b49SDavid du Colombier 	for(q=p; *q; q++) {
603*0c0b2b49SDavid du Colombier 		_argv[_argc] = (long)((uintptr)BOOTARGS + (q - p));
604*0c0b2b49SDavid du Colombier 		_argc++;
605*0c0b2b49SDavid du Colombier 		q += strlen(q);
606*0c0b2b49SDavid du Colombier 		*q = '=';
607*0c0b2b49SDavid du Colombier 		q += strlen(q);
608*0c0b2b49SDavid du Colombier 	}
609*0c0b2b49SDavid du Colombier 	n = q - p + 1;
610*0c0b2b49SDavid du Colombier 	_env = &_argv[_argc];
611*0c0b2b49SDavid du Colombier 
612*0c0b2b49SDavid du Colombier 	if(n >= BOOTARGSLEN || (uintptr)_env >= CONFARGV + CONFARGVLEN)
613*0c0b2b49SDavid du Colombier 		error("kernel configuration too large");
614*0c0b2b49SDavid du Colombier 	memmove(BOOTARGS, p, n);
615*0c0b2b49SDavid du Colombier 	memset(BOOTARGS + n, '\0', BOOTARGSLEN - n);
616*0c0b2b49SDavid du Colombier 	memset(_env, 0, CONFARGV + CONFARGVLEN - (uintptr)_env);
617*0c0b2b49SDavid du Colombier 
618*0c0b2b49SDavid du Colombier 	poperror();
619*0c0b2b49SDavid du Colombier 	free(p);
620*0c0b2b49SDavid du Colombier }
621*0c0b2b49SDavid du Colombier 
622*0c0b2b49SDavid du Colombier static void
shutdown(int ispanic)623*0c0b2b49SDavid du Colombier shutdown(int ispanic)
624*0c0b2b49SDavid du Colombier {
625*0c0b2b49SDavid du Colombier 	int ms, once;
626*0c0b2b49SDavid du Colombier 
627*0c0b2b49SDavid du Colombier 	ilock(&active);
628*0c0b2b49SDavid du Colombier 	if(ispanic)
629*0c0b2b49SDavid du Colombier 		active.ispanic = ispanic;
630*0c0b2b49SDavid du Colombier 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
631*0c0b2b49SDavid du Colombier 		active.ispanic = 0;
632*0c0b2b49SDavid du Colombier 	once = active.machs & (1<<m->machno);
633*0c0b2b49SDavid du Colombier 	/*
634*0c0b2b49SDavid du Colombier 	 * setting exiting will make hzclock() on each processor call exit(0),
635*0c0b2b49SDavid du Colombier 	 * which calls shutdown(0) and idles non-bootstrap cpus and returns
636*0c0b2b49SDavid du Colombier 	 * on bootstrap processors (to permit a reboot).  clearing our bit
637*0c0b2b49SDavid du Colombier 	 * in machs avoids calling exit(0) from hzclock() on this processor.
638*0c0b2b49SDavid du Colombier 	 */
639*0c0b2b49SDavid du Colombier 	active.machs &= ~(1<<m->machno);
640*0c0b2b49SDavid du Colombier 	active.exiting = 1;
641*0c0b2b49SDavid du Colombier 	iunlock(&active);
642*0c0b2b49SDavid du Colombier 
643*0c0b2b49SDavid du Colombier 	if(once) {
644*0c0b2b49SDavid du Colombier 		delay(m->machno*1000);		/* stagger them */
645*0c0b2b49SDavid du Colombier 		iprint("cpu%d: exiting\n", m->machno);
646*0c0b2b49SDavid du Colombier 	}
647*0c0b2b49SDavid du Colombier 	spllo();
648*0c0b2b49SDavid du Colombier 	for(ms = MAXMACH * 1000; ms > 0; ms -= TK2MS(2)){
649*0c0b2b49SDavid du Colombier 		delay(TK2MS(2));
650*0c0b2b49SDavid du Colombier 		if(active.machs == 0 && consactive() == 0)
651*0c0b2b49SDavid du Colombier 			break;
652*0c0b2b49SDavid du Colombier 	}
653*0c0b2b49SDavid du Colombier 	delay(100);
654*0c0b2b49SDavid du Colombier }
655*0c0b2b49SDavid du Colombier 
656*0c0b2b49SDavid du Colombier void
exit(int ispanic)657*0c0b2b49SDavid du Colombier exit(int ispanic)
658*0c0b2b49SDavid du Colombier {
659*0c0b2b49SDavid du Colombier 	int timer;
660*0c0b2b49SDavid du Colombier 
661*0c0b2b49SDavid du Colombier 	delay(1000);
662*0c0b2b49SDavid du Colombier 	shutdown(ispanic);
663*0c0b2b49SDavid du Colombier 	timer = 0;
664*0c0b2b49SDavid du Colombier 	while(active.machs || consactive()) {
665*0c0b2b49SDavid du Colombier 		if(timer++ > 400)
666*0c0b2b49SDavid du Colombier 			break;
667*0c0b2b49SDavid du Colombier 		delay(10);
668*0c0b2b49SDavid du Colombier 	}
669*0c0b2b49SDavid du Colombier 	delay(1000);
670*0c0b2b49SDavid du Colombier 	splhi();
671*0c0b2b49SDavid du Colombier 
672*0c0b2b49SDavid du Colombier 	setstatus(BEV);
673*0c0b2b49SDavid du Colombier 	coherence();
674*0c0b2b49SDavid du Colombier 
675*0c0b2b49SDavid du Colombier 	iprint("exit: awaiting reset\n");
676*0c0b2b49SDavid du Colombier 	delay(1000);			/* await a reset */
677*0c0b2b49SDavid du Colombier 
678*0c0b2b49SDavid du Colombier 	if(!active.ispanic) {
679*0c0b2b49SDavid du Colombier 		iprint("exit: jumping to rom\n");
680*0c0b2b49SDavid du Colombier 		*Reset |= Rstcpucold;		/* cpu cold reset */
681*0c0b2b49SDavid du Colombier 	}
682*0c0b2b49SDavid du Colombier 
683*0c0b2b49SDavid du Colombier 	iprint("exit: looping\n");
684*0c0b2b49SDavid du Colombier 	for(;;);
685*0c0b2b49SDavid du Colombier }
686*0c0b2b49SDavid du Colombier 
687*0c0b2b49SDavid du Colombier /*
688*0c0b2b49SDavid du Colombier  * the new kernel is already loaded at address `code'
689*0c0b2b49SDavid du Colombier  * of size `size' and entry point `entry'.
690*0c0b2b49SDavid du Colombier  */
691*0c0b2b49SDavid du Colombier void
reboot(void * entry,void * code,ulong size)692*0c0b2b49SDavid du Colombier reboot(void *entry, void *code, ulong size)
693*0c0b2b49SDavid du Colombier {
694*0c0b2b49SDavid du Colombier 	void (*f)(ulong, ulong, ulong, ulong);
695*0c0b2b49SDavid du Colombier 
696*0c0b2b49SDavid du Colombier 	writeconf();
697*0c0b2b49SDavid du Colombier 
698*0c0b2b49SDavid du Colombier 	/*
699*0c0b2b49SDavid du Colombier 	 * the boot processor is cpu0.  execute this function on it
700*0c0b2b49SDavid du Colombier 	 * so that the new kernel has the same cpu0.
701*0c0b2b49SDavid du Colombier 	 */
702*0c0b2b49SDavid du Colombier 	if(m->machno != 0) {
703*0c0b2b49SDavid du Colombier 		procwired(up, 0);
704*0c0b2b49SDavid du Colombier 		sched();
705*0c0b2b49SDavid du Colombier 	}
706*0c0b2b49SDavid du Colombier 	if(m->machno != 0)
707*0c0b2b49SDavid du Colombier 		print("on cpu%d (not 0)!\n", m->machno);
708*0c0b2b49SDavid du Colombier 
709*0c0b2b49SDavid du Colombier 	if(code == nil || entry == nil)
710*0c0b2b49SDavid du Colombier 		exit(1);
711*0c0b2b49SDavid du Colombier 
712*0c0b2b49SDavid du Colombier 	shutdown(0);
713*0c0b2b49SDavid du Colombier 
714*0c0b2b49SDavid du Colombier 	/*
715*0c0b2b49SDavid du Colombier 	 * should be the only processor running now
716*0c0b2b49SDavid du Colombier 	 */
717*0c0b2b49SDavid du Colombier 	iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
718*0c0b2b49SDavid du Colombier 	iprint("code[0] = %#lux\n", *(ulong *)code);
719*0c0b2b49SDavid du Colombier 
720*0c0b2b49SDavid du Colombier 	/* turn off buffered serial console */
721*0c0b2b49SDavid du Colombier 	serialoq = nil;
722*0c0b2b49SDavid du Colombier 	kprintoq = nil;
723*0c0b2b49SDavid du Colombier 	screenputs = nil;
724*0c0b2b49SDavid du Colombier 
725*0c0b2b49SDavid du Colombier 	/* shutdown devices */
726*0c0b2b49SDavid du Colombier 	chandevshutdown();
727*0c0b2b49SDavid du Colombier 
728*0c0b2b49SDavid du Colombier 	splhi();
729*0c0b2b49SDavid du Colombier 	intrshutdown();
730*0c0b2b49SDavid du Colombier 
731*0c0b2b49SDavid du Colombier 	/* setup reboot trampoline function */
732*0c0b2b49SDavid du Colombier 	f = (void*)REBOOTADDR;
733*0c0b2b49SDavid du Colombier //	memmove(f, rebootcode, sizeof(rebootcode));
734*0c0b2b49SDavid du Colombier //	icflush(f, sizeof(rebootcode));
735*0c0b2b49SDavid du Colombier 
736*0c0b2b49SDavid du Colombier 	setstatus(BEV);		/* also, kernel mode, no interrupts */
737*0c0b2b49SDavid du Colombier 	coherence();
738*0c0b2b49SDavid du Colombier 
739*0c0b2b49SDavid du Colombier 	/* off we go - never to return */
740*0c0b2b49SDavid du Colombier 	(*f)((ulong)entry, (ulong)code, size, _argc);
741*0c0b2b49SDavid du Colombier 
742*0c0b2b49SDavid du Colombier 	panic("loaded kernel returned!");
743*0c0b2b49SDavid du Colombier }
744*0c0b2b49SDavid du Colombier 
745*0c0b2b49SDavid du Colombier /*
746*0c0b2b49SDavid du Colombier  * stub for ../port/devpnp.c
747*0c0b2b49SDavid du Colombier  */
748*0c0b2b49SDavid du Colombier int
isaconfig(char * class,int ctlrno,ISAConf * isa)749*0c0b2b49SDavid du Colombier isaconfig(char *class, int ctlrno, ISAConf *isa)
750*0c0b2b49SDavid du Colombier {
751*0c0b2b49SDavid du Colombier 	USED(class, ctlrno, isa);
752*0c0b2b49SDavid du Colombier 	return 0;
753*0c0b2b49SDavid du Colombier }
754