xref: /plan9-contrib/sys/src/9/vt4/main.c (revision d6dfd9ef91cf0fa8514a249d5f2a550978c19369)
1*d6dfd9efSDavid du Colombier #include "u.h"
2*d6dfd9efSDavid du Colombier #include "../port/lib.h"
3*d6dfd9efSDavid du Colombier #include "mem.h"
4*d6dfd9efSDavid du Colombier #include "dat.h"
5*d6dfd9efSDavid du Colombier #include "fns.h"
6*d6dfd9efSDavid du Colombier #include "../ip/ip.h"
7*d6dfd9efSDavid du Colombier 
8*d6dfd9efSDavid du Colombier #include <pool.h>
9*d6dfd9efSDavid du Colombier #include <tos.h>
10*d6dfd9efSDavid du Colombier 
11*d6dfd9efSDavid du Colombier #include "qtm.h"
12*d6dfd9efSDavid du Colombier 
13*d6dfd9efSDavid du Colombier #include "init.h"
14*d6dfd9efSDavid du Colombier 
15*d6dfd9efSDavid du Colombier #define	MAXCONF		32
16*d6dfd9efSDavid du Colombier 
17*d6dfd9efSDavid du Colombier ulong dverify = 0x01020304;
18*d6dfd9efSDavid du Colombier ulong bverify;
19*d6dfd9efSDavid du Colombier int securemem;
20*d6dfd9efSDavid du Colombier Conf conf;
21*d6dfd9efSDavid du Colombier 
22*d6dfd9efSDavid du Colombier /*
23*d6dfd9efSDavid du Colombier  * Option arguments from the command line.
24*d6dfd9efSDavid du Colombier  * oargv[0] is the boot file.
25*d6dfd9efSDavid du Colombier  * Optionsinit() is called from multiboot()
26*d6dfd9efSDavid du Colombier  * or some other machine-dependent place
27*d6dfd9efSDavid du Colombier  * to set it all up.
28*d6dfd9efSDavid du Colombier  */
29*d6dfd9efSDavid du Colombier static int oargc;
30*d6dfd9efSDavid du Colombier static char* oargv[20];
31*d6dfd9efSDavid du Colombier static char oargb[128];
32*d6dfd9efSDavid du Colombier static int oargblen;
33*d6dfd9efSDavid du Colombier static char oenv[4096];
34*d6dfd9efSDavid du Colombier 
35*d6dfd9efSDavid du Colombier static uintptr sp;		/* XXX - must go - user stack of init proc */
36*d6dfd9efSDavid du Colombier 
37*d6dfd9efSDavid du Colombier static char confname[MAXCONF][KNAMELEN];
38*d6dfd9efSDavid du Colombier static char *confval[MAXCONF];
39*d6dfd9efSDavid du Colombier static int nconf;
40*d6dfd9efSDavid du Colombier 
41*d6dfd9efSDavid du Colombier static void
mypanic(Pool * p,char * fmt,...)42*d6dfd9efSDavid du Colombier mypanic(Pool *p, char *fmt, ...)
43*d6dfd9efSDavid du Colombier {
44*d6dfd9efSDavid du Colombier 	USED(p, fmt);
45*d6dfd9efSDavid du Colombier 	print("malloc panic\n");
46*d6dfd9efSDavid du Colombier 	delay(1000);
47*d6dfd9efSDavid du Colombier 	splhi();
48*d6dfd9efSDavid du Colombier 	for (;;)
49*d6dfd9efSDavid du Colombier 		;
50*d6dfd9efSDavid du Colombier }
51*d6dfd9efSDavid du Colombier 
52*d6dfd9efSDavid du Colombier void
machninit(int machno)53*d6dfd9efSDavid du Colombier machninit(int machno)
54*d6dfd9efSDavid du Colombier {
55*d6dfd9efSDavid du Colombier 	if (machno >= MAXMACH)
56*d6dfd9efSDavid du Colombier 		panic("machno %d >= MAXMACH %d", machno, MAXMACH);
57*d6dfd9efSDavid du Colombier 	conf.nmach++;
58*d6dfd9efSDavid du Colombier 	m = MACHP(machno);
59*d6dfd9efSDavid du Colombier 	memset(m, 0, sizeof(Mach));
60*d6dfd9efSDavid du Colombier 	m->machno = machno;
61*d6dfd9efSDavid du Colombier 	m->cputype = getpvr()>>16;   /* OWN[0:11] and PCF[12:15] fields */
62*d6dfd9efSDavid du Colombier 	m->delayloop = 20000;	/* initial estimate only; set by clockinit */
63*d6dfd9efSDavid du Colombier  	m->perf.period = 1;
64*d6dfd9efSDavid du Colombier 	/* other values set by archreset */
65*d6dfd9efSDavid du Colombier }
66*d6dfd9efSDavid du Colombier 
67*d6dfd9efSDavid du Colombier void
cpuidprint(void)68*d6dfd9efSDavid du Colombier cpuidprint(void)
69*d6dfd9efSDavid du Colombier {
70*d6dfd9efSDavid du Colombier 	char name[64];
71*d6dfd9efSDavid du Colombier 
72*d6dfd9efSDavid du Colombier 	cputype2name(name, sizeof name);
73*d6dfd9efSDavid du Colombier 	print("cpu%d: %ldMHz PowerPC %s\n", m->machno, m->cpuhz/1000000, name);
74*d6dfd9efSDavid du Colombier }
75*d6dfd9efSDavid du Colombier 
76*d6dfd9efSDavid du Colombier void
mach0init(void)77*d6dfd9efSDavid du Colombier mach0init(void)
78*d6dfd9efSDavid du Colombier {
79*d6dfd9efSDavid du Colombier 	conf.nmach = 0;
80*d6dfd9efSDavid du Colombier 
81*d6dfd9efSDavid du Colombier 	machninit(0);
82*d6dfd9efSDavid du Colombier 
83*d6dfd9efSDavid du Colombier 	active.machs = 1;
84*d6dfd9efSDavid du Colombier 	active.exiting = 0;
85*d6dfd9efSDavid du Colombier }
86*d6dfd9efSDavid du Colombier 
87*d6dfd9efSDavid du Colombier static void
setconf(char * name,char * val)88*d6dfd9efSDavid du Colombier setconf(char *name, char *val)
89*d6dfd9efSDavid du Colombier {
90*d6dfd9efSDavid du Colombier 	strncpy(confname[nconf], name, KNAMELEN);
91*d6dfd9efSDavid du Colombier 	kstrdup(&confval[nconf], val);
92*d6dfd9efSDavid du Colombier 	nconf++;
93*d6dfd9efSDavid du Colombier }
94*d6dfd9efSDavid du Colombier 
95*d6dfd9efSDavid du Colombier static void
plan9iniinit(void)96*d6dfd9efSDavid du Colombier plan9iniinit(void)
97*d6dfd9efSDavid du Colombier {
98*d6dfd9efSDavid du Colombier 	/* virtex configuration */
99*d6dfd9efSDavid du Colombier 	setconf("nvram", "/boot/nvram");
100*d6dfd9efSDavid du Colombier 	setconf("nvroff", "0");
101*d6dfd9efSDavid du Colombier 	setconf("nvrlen", "512");
102*d6dfd9efSDavid du Colombier 
103*d6dfd9efSDavid du Colombier 	setconf("aoeif", "ether0");
104*d6dfd9efSDavid du Colombier 	setconf("aoedev", "e!#æ/aoe/1.0");
105*d6dfd9efSDavid du Colombier }
106*d6dfd9efSDavid du Colombier 
107*d6dfd9efSDavid du Colombier char*
getenv(char * name,char * buf,int n)108*d6dfd9efSDavid du Colombier getenv(char* name, char* buf, int n)
109*d6dfd9efSDavid du Colombier {
110*d6dfd9efSDavid du Colombier 	char *e, *p, *q;
111*d6dfd9efSDavid du Colombier 
112*d6dfd9efSDavid du Colombier 	p = oenv;
113*d6dfd9efSDavid du Colombier 	while(*p != 0){
114*d6dfd9efSDavid du Colombier 		if((e = strchr(p, '=')) == nil)
115*d6dfd9efSDavid du Colombier 			break;
116*d6dfd9efSDavid du Colombier 		for(q = name; p < e; p++){
117*d6dfd9efSDavid du Colombier 			if(*p != *q)
118*d6dfd9efSDavid du Colombier 				break;
119*d6dfd9efSDavid du Colombier 			q++;
120*d6dfd9efSDavid du Colombier 		}
121*d6dfd9efSDavid du Colombier 		if(p == e && *q == 0){
122*d6dfd9efSDavid du Colombier 			strecpy(buf, buf+n, e+1);
123*d6dfd9efSDavid du Colombier 			return buf;
124*d6dfd9efSDavid du Colombier 		}
125*d6dfd9efSDavid du Colombier 		p += strlen(p)+1;
126*d6dfd9efSDavid du Colombier 	}
127*d6dfd9efSDavid du Colombier 
128*d6dfd9efSDavid du Colombier 	return nil;
129*d6dfd9efSDavid du Colombier }
130*d6dfd9efSDavid du Colombier 
131*d6dfd9efSDavid du Colombier static void
optionsinit(char * s)132*d6dfd9efSDavid du Colombier optionsinit(char* s)
133*d6dfd9efSDavid du Colombier {
134*d6dfd9efSDavid du Colombier 	char *o;
135*d6dfd9efSDavid du Colombier 
136*d6dfd9efSDavid du Colombier 	o = strecpy(oargb, oargb+sizeof(oargb), s)+1;
137*d6dfd9efSDavid du Colombier 	if(getenv("bootargs", o, o - oargb) != nil)
138*d6dfd9efSDavid du Colombier 		*(o-1) = ' ';
139*d6dfd9efSDavid du Colombier 
140*d6dfd9efSDavid du Colombier 	oargblen = strlen(oargb);
141*d6dfd9efSDavid du Colombier 	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
142*d6dfd9efSDavid du Colombier 	oargv[oargc] = nil;
143*d6dfd9efSDavid du Colombier }
144*d6dfd9efSDavid du Colombier 
145*d6dfd9efSDavid du Colombier void
main(void)146*d6dfd9efSDavid du Colombier main(void)
147*d6dfd9efSDavid du Colombier {
148*d6dfd9efSDavid du Colombier 	int machno;
149*d6dfd9efSDavid du Colombier 
150*d6dfd9efSDavid du Colombier 	/* entry to main pushed stuff onto the stack. */
151*d6dfd9efSDavid du Colombier 
152*d6dfd9efSDavid du Colombier //	memset(edata, 0, (ulong)end-(ulong)edata);
153*d6dfd9efSDavid du Colombier 
154*d6dfd9efSDavid du Colombier 	machno = getpir();
155*d6dfd9efSDavid du Colombier 	if (machno > 0)
156*d6dfd9efSDavid du Colombier 		startcpu(machno);
157*d6dfd9efSDavid du Colombier 
158*d6dfd9efSDavid du Colombier //	dcrcompile();
159*d6dfd9efSDavid du Colombier 	if (dverify != 0x01020304) {
160*d6dfd9efSDavid du Colombier 		uartlputs("data segment not initialised\n");
161*d6dfd9efSDavid du Colombier 		panic("data segment not initialised");
162*d6dfd9efSDavid du Colombier 	}
163*d6dfd9efSDavid du Colombier 	if (bverify != 0) {
164*d6dfd9efSDavid du Colombier 		uartlputs("bss segment not zeroed\n");
165*d6dfd9efSDavid du Colombier 		panic("bss segment not zeroed");
166*d6dfd9efSDavid du Colombier 	}
167*d6dfd9efSDavid du Colombier 	mach0init();
168*d6dfd9efSDavid du Colombier 	archreset();
169*d6dfd9efSDavid du Colombier 	quotefmtinstall();
170*d6dfd9efSDavid du Colombier 	optionsinit("/boot/boot boot");
171*d6dfd9efSDavid du Colombier //	archconsole();
172*d6dfd9efSDavid du Colombier 
173*d6dfd9efSDavid du Colombier 	meminit();
174*d6dfd9efSDavid du Colombier 	confinit();
175*d6dfd9efSDavid du Colombier 	mmuinit();
176*d6dfd9efSDavid du Colombier 	xinit();			/* xinit would print if it could */
177*d6dfd9efSDavid du Colombier 	trapinit();
178*d6dfd9efSDavid du Colombier 	qtminit();
179*d6dfd9efSDavid du Colombier 	ioinit();
180*d6dfd9efSDavid du Colombier 	uncinit();
181*d6dfd9efSDavid du Colombier 	printinit();
182*d6dfd9efSDavid du Colombier 	uartliteconsole();
183*d6dfd9efSDavid du Colombier 
184*d6dfd9efSDavid du Colombier 	mainmem->flags |= POOL_ANTAGONISM;
185*d6dfd9efSDavid du Colombier 	mainmem->panic = mypanic;
186*d6dfd9efSDavid du Colombier 	ethermedium.maxtu = 1512;   /* must be multiple of 4 for temac's dma */
187*d6dfd9efSDavid du Colombier 
188*d6dfd9efSDavid du Colombier //	print("\n\nPlan 9k H\n");	/* already printed by l.s */
189*d6dfd9efSDavid du Colombier 	plan9iniinit();
190*d6dfd9efSDavid du Colombier 	timersinit();
191*d6dfd9efSDavid du Colombier 	clockinit();
192*d6dfd9efSDavid du Colombier 
193*d6dfd9efSDavid du Colombier 	dma0init();			/* does not start kprocs; see init0 */
194*d6dfd9efSDavid du Colombier 	fpuinit();
195*d6dfd9efSDavid du Colombier 	procinit0();
196*d6dfd9efSDavid du Colombier 	initseg();
197*d6dfd9efSDavid du Colombier 	links();
198*d6dfd9efSDavid du Colombier 
199*d6dfd9efSDavid du Colombier 	chandevreset();
200*d6dfd9efSDavid du Colombier 	okprint = 1;			/* only now can we print */
201*d6dfd9efSDavid du Colombier 	barriers();
202*d6dfd9efSDavid du Colombier 	dcflush((uintptr)&okprint, sizeof okprint);
203*d6dfd9efSDavid du Colombier 
204*d6dfd9efSDavid du Colombier 	cpuidprint();
205*d6dfd9efSDavid du Colombier 
206*d6dfd9efSDavid du Colombier 	print("%d Hz clock", HZ);
207*d6dfd9efSDavid du Colombier 	print("; memory size %,ud (%#ux)\n", (uint)memsz, (uint)memsz);
208*d6dfd9efSDavid du Colombier 
209*d6dfd9efSDavid du Colombier 	pageinit();
210*d6dfd9efSDavid du Colombier 	swapinit();
211*d6dfd9efSDavid du Colombier 	userinit();
212*d6dfd9efSDavid du Colombier 	active.thunderbirdsarego = 1;
213*d6dfd9efSDavid du Colombier 	dcflush((uintptr)&active.thunderbirdsarego,
214*d6dfd9efSDavid du Colombier 		sizeof active.thunderbirdsarego);
215*d6dfd9efSDavid du Colombier 	schedinit();
216*d6dfd9efSDavid du Colombier 	/* no return */
217*d6dfd9efSDavid du Colombier 	panic("schedinit returned");
218*d6dfd9efSDavid du Colombier }
219*d6dfd9efSDavid du Colombier 
220*d6dfd9efSDavid du Colombier void
confinit(void)221*d6dfd9efSDavid du Colombier confinit(void)
222*d6dfd9efSDavid du Colombier {
223*d6dfd9efSDavid du Colombier 	char *p;
224*d6dfd9efSDavid du Colombier 	int i, userpcnt;
225*d6dfd9efSDavid du Colombier 	ulong kpages;
226*d6dfd9efSDavid du Colombier 
227*d6dfd9efSDavid du Colombier 	if(p = getconf("*kernelpercent"))
228*d6dfd9efSDavid du Colombier 		userpcnt = 100 - strtol(p, 0, 0);
229*d6dfd9efSDavid du Colombier 	else
230*d6dfd9efSDavid du Colombier 		userpcnt = 85;
231*d6dfd9efSDavid du Colombier 
232*d6dfd9efSDavid du Colombier 	conf.npage = 0;
233*d6dfd9efSDavid du Colombier 	for(i=0; i<nelem(conf.mem); i++)
234*d6dfd9efSDavid du Colombier 		conf.npage += conf.mem[i].npage;
235*d6dfd9efSDavid du Colombier 
236*d6dfd9efSDavid du Colombier 	/* see machninit for nmach setting */
237*d6dfd9efSDavid du Colombier 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
238*d6dfd9efSDavid du Colombier 	if(conf.nproc > 2000)
239*d6dfd9efSDavid du Colombier 		conf.nproc = 2000;
240*d6dfd9efSDavid du Colombier 	conf.nimage = 200;
241*d6dfd9efSDavid du Colombier 	conf.nswap = conf.nproc*80;
242*d6dfd9efSDavid du Colombier 	conf.nswppo = 4096;
243*d6dfd9efSDavid du Colombier 	conf.copymode = 0;			/* copy on write */
244*d6dfd9efSDavid du Colombier 
245*d6dfd9efSDavid du Colombier 	if(userpcnt < 10)
246*d6dfd9efSDavid du Colombier 		userpcnt = 60;
247*d6dfd9efSDavid du Colombier 	kpages = conf.npage - (conf.npage*userpcnt)/100;
248*d6dfd9efSDavid du Colombier 
249*d6dfd9efSDavid du Colombier 	conf.upages = conf.npage - kpages;
250*d6dfd9efSDavid du Colombier 	conf.ialloc = (kpages/2)*BY2PG;
251*d6dfd9efSDavid du Colombier 
252*d6dfd9efSDavid du Colombier 	kpages *= BY2PG;
253*d6dfd9efSDavid du Colombier 	kpages -= conf.upages*sizeof(Page)
254*d6dfd9efSDavid du Colombier 		+ conf.nproc*sizeof(Proc)
255*d6dfd9efSDavid du Colombier 		+ conf.nimage*sizeof(Image)
256*d6dfd9efSDavid du Colombier 		+ conf.nswap
257*d6dfd9efSDavid du Colombier 		+ conf.nswppo*sizeof(Page);
258*d6dfd9efSDavid du Colombier 	mainmem->maxsize = kpages;
259*d6dfd9efSDavid du Colombier }
260*d6dfd9efSDavid du Colombier 
261*d6dfd9efSDavid du Colombier void
init0(void)262*d6dfd9efSDavid du Colombier init0(void)
263*d6dfd9efSDavid du Colombier {
264*d6dfd9efSDavid du Colombier 	int i;
265*d6dfd9efSDavid du Colombier 	char buf[2*KNAMELEN];
266*d6dfd9efSDavid du Colombier 
267*d6dfd9efSDavid du Colombier 	assert(up != nil);
268*d6dfd9efSDavid du Colombier 	up->nerrlab = 0;
269*d6dfd9efSDavid du Colombier 	barriers();
270*d6dfd9efSDavid du Colombier 	intrack(~0);
271*d6dfd9efSDavid du Colombier 	clrmchk();
272*d6dfd9efSDavid du Colombier 	barriers();
273*d6dfd9efSDavid du Colombier 	spllo();
274*d6dfd9efSDavid du Colombier 
275*d6dfd9efSDavid du Colombier 	/*
276*d6dfd9efSDavid du Colombier 	 * These are o.k. because rootinit is null.
277*d6dfd9efSDavid du Colombier 	 * Then early kproc's will have a root and dot.
278*d6dfd9efSDavid du Colombier 	 */
279*d6dfd9efSDavid du Colombier 	up->slash = namec("#/", Atodir, 0, 0);
280*d6dfd9efSDavid du Colombier 	pathclose(up->slash->path);
281*d6dfd9efSDavid du Colombier 	up->slash->path = newpath("/");
282*d6dfd9efSDavid du Colombier 	up->dot = cclone(up->slash);
283*d6dfd9efSDavid du Colombier 
284*d6dfd9efSDavid du Colombier 	dmainit();			/* starts dma kprocs */
285*d6dfd9efSDavid du Colombier 	devtabinit();
286*d6dfd9efSDavid du Colombier 
287*d6dfd9efSDavid du Colombier 	if(!waserror()){
288*d6dfd9efSDavid du Colombier 		snprint(buf, sizeof(buf), "power %s", conffile);
289*d6dfd9efSDavid du Colombier 		ksetenv("terminal", buf, 0);
290*d6dfd9efSDavid du Colombier 		ksetenv("cputype", "power", 0);
291*d6dfd9efSDavid du Colombier 		if(cpuserver)
292*d6dfd9efSDavid du Colombier 			ksetenv("service", "cpu", 0);
293*d6dfd9efSDavid du Colombier 		else
294*d6dfd9efSDavid du Colombier 			ksetenv("service", "terminal", 0);
295*d6dfd9efSDavid du Colombier 
296*d6dfd9efSDavid du Colombier 		/* virtex configuration */
297*d6dfd9efSDavid du Colombier 		ksetenv("nvram", "/boot/nvram", 0);
298*d6dfd9efSDavid du Colombier 		ksetenv("nvroff", "0", 0);
299*d6dfd9efSDavid du Colombier 		ksetenv("nvrlen", "512", 0);
300*d6dfd9efSDavid du Colombier 
301*d6dfd9efSDavid du Colombier 		ksetenv("nobootprompt", "tcp", 0);
302*d6dfd9efSDavid du Colombier 
303*d6dfd9efSDavid du Colombier 		poperror();
304*d6dfd9efSDavid du Colombier 	}
305*d6dfd9efSDavid du Colombier 	for(i = 0; i < nconf; i++){
306*d6dfd9efSDavid du Colombier 		if(confval[i] == nil)
307*d6dfd9efSDavid du Colombier 			continue;
308*d6dfd9efSDavid du Colombier 		if(confname[i][0] != '*'){
309*d6dfd9efSDavid du Colombier 			if(!waserror()){
310*d6dfd9efSDavid du Colombier 				ksetenv(confname[i], confval[i], 0);
311*d6dfd9efSDavid du Colombier 				poperror();
312*d6dfd9efSDavid du Colombier 			}
313*d6dfd9efSDavid du Colombier 		}
314*d6dfd9efSDavid du Colombier 		if(!waserror()){
315*d6dfd9efSDavid du Colombier 			ksetenv(confname[i], confval[i], 1);
316*d6dfd9efSDavid du Colombier 			poperror();
317*d6dfd9efSDavid du Colombier 		}
318*d6dfd9efSDavid du Colombier 	}
319*d6dfd9efSDavid du Colombier 
320*d6dfd9efSDavid du Colombier 	kproc("alarm", alarmkproc, 0);
321*d6dfd9efSDavid du Colombier 	if (securemem)
322*d6dfd9efSDavid du Colombier 	 	kproc("mutate", mutateproc, 0);
323*d6dfd9efSDavid du Colombier 	else
324*d6dfd9efSDavid du Colombier 		print("no secure memory found\n");
325*d6dfd9efSDavid du Colombier 
326*d6dfd9efSDavid du Colombier 	/*
327*d6dfd9efSDavid du Colombier 	 * The initial value of the user stack must be such
328*d6dfd9efSDavid du Colombier 	 * that the total used is larger than the maximum size
329*d6dfd9efSDavid du Colombier 	 * of the argument list checked in syscall.
330*d6dfd9efSDavid du Colombier 	 */
331*d6dfd9efSDavid du Colombier 	sync();
332*d6dfd9efSDavid du Colombier 	isync();
333*d6dfd9efSDavid du Colombier 	touser(sp);
334*d6dfd9efSDavid du Colombier }
335*d6dfd9efSDavid du Colombier 
336*d6dfd9efSDavid du Colombier static void
bootargs(uintptr base)337*d6dfd9efSDavid du Colombier bootargs(uintptr base)
338*d6dfd9efSDavid du Colombier {
339*d6dfd9efSDavid du Colombier 	int i;
340*d6dfd9efSDavid du Colombier 	ulong ssize;
341*d6dfd9efSDavid du Colombier 	char **av, *p;
342*d6dfd9efSDavid du Colombier 
343*d6dfd9efSDavid du Colombier 	/*
344*d6dfd9efSDavid du Colombier 	 * Push the boot args onto the stack.
345*d6dfd9efSDavid du Colombier 	 * The initial value of the user stack must be such
346*d6dfd9efSDavid du Colombier 	 * that the total used is larger than the maximum size
347*d6dfd9efSDavid du Colombier 	 * of the argument list checked in syscall.
348*d6dfd9efSDavid du Colombier 	 */
349*d6dfd9efSDavid du Colombier 	i = oargblen+1;
350*d6dfd9efSDavid du Colombier 	p = UINT2PTR(STACKALIGN(base + BY2PG - sizeof(up->s.args) - i));
351*d6dfd9efSDavid du Colombier 	memmove(p, oargb, i);
352*d6dfd9efSDavid du Colombier 
353*d6dfd9efSDavid du Colombier 	/*
354*d6dfd9efSDavid du Colombier 	 * Now push argc and the argv pointers.
355*d6dfd9efSDavid du Colombier 	 * This isn't strictly correct as the code jumped to by
356*d6dfd9efSDavid du Colombier 	 * touser in init9.s calls startboot (port/initcode.c) which
357*d6dfd9efSDavid du Colombier 	 * expects arguments
358*d6dfd9efSDavid du Colombier 	 * 	startboot(char *argv0, char **argv)
359*d6dfd9efSDavid du Colombier 	 * not the usual (int argc, char* argv[]), but argv0 is
360*d6dfd9efSDavid du Colombier 	 * unused so it doesn't matter (at the moment...).
361*d6dfd9efSDavid du Colombier 	 */
362*d6dfd9efSDavid du Colombier 	av = (char**)(p - (oargc+2)*sizeof(char*));
363*d6dfd9efSDavid du Colombier 	ssize = base + BY2PG - PTR2UINT(av);
364*d6dfd9efSDavid du Colombier 	*av++ = (char*)oargc;
365*d6dfd9efSDavid du Colombier 	for(i = 0; i < oargc; i++)
366*d6dfd9efSDavid du Colombier 		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
367*d6dfd9efSDavid du Colombier 	*av = nil;
368*d6dfd9efSDavid du Colombier 
369*d6dfd9efSDavid du Colombier 	/*
370*d6dfd9efSDavid du Colombier 	 * Leave space for the return PC of the
371*d6dfd9efSDavid du Colombier 	 * caller of initcode.
372*d6dfd9efSDavid du Colombier 	 */
373*d6dfd9efSDavid du Colombier 	sp = USTKTOP - ssize - sizeof(void*);
374*d6dfd9efSDavid du Colombier }
375*d6dfd9efSDavid du Colombier 
376*d6dfd9efSDavid du Colombier void
userinit(void)377*d6dfd9efSDavid du Colombier userinit(void)
378*d6dfd9efSDavid du Colombier {
379*d6dfd9efSDavid du Colombier 	Proc *p;
380*d6dfd9efSDavid du Colombier 	Segment *s;
381*d6dfd9efSDavid du Colombier 	KMap *k;
382*d6dfd9efSDavid du Colombier 	Page *pg;
383*d6dfd9efSDavid du Colombier 
384*d6dfd9efSDavid du Colombier 	/* no processes yet */
385*d6dfd9efSDavid du Colombier 	up = nil;
386*d6dfd9efSDavid du Colombier 
387*d6dfd9efSDavid du Colombier 	p = newproc();
388*d6dfd9efSDavid du Colombier 	p->pgrp = newpgrp();
389*d6dfd9efSDavid du Colombier 	p->egrp = smalloc(sizeof(Egrp));
390*d6dfd9efSDavid du Colombier 	p->egrp->ref = 1;
391*d6dfd9efSDavid du Colombier 	p->fgrp = dupfgrp(nil);
392*d6dfd9efSDavid du Colombier 	p->rgrp = newrgrp();
393*d6dfd9efSDavid du Colombier 	p->procmode = 0640;
394*d6dfd9efSDavid du Colombier 
395*d6dfd9efSDavid du Colombier 	kstrdup(&eve, "");
396*d6dfd9efSDavid du Colombier 	kstrdup(&p->text, "*init*");
397*d6dfd9efSDavid du Colombier 	kstrdup(&p->user, eve);
398*d6dfd9efSDavid du Colombier 
399*d6dfd9efSDavid du Colombier 	/*
400*d6dfd9efSDavid du Colombier 	 * Kernel Stack
401*d6dfd9efSDavid du Colombier 	 */
402*d6dfd9efSDavid du Colombier 	p->sched.pc = PTR2UINT(init0);
403*d6dfd9efSDavid du Colombier 	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
404*d6dfd9efSDavid du Colombier 	p->sched.sp = STACKALIGN(p->sched.sp);
405*d6dfd9efSDavid du Colombier 
406*d6dfd9efSDavid du Colombier 	/*
407*d6dfd9efSDavid du Colombier 	 * User Stack
408*d6dfd9efSDavid du Colombier 	 *
409*d6dfd9efSDavid du Colombier 	 * Technically, newpage can't be called here because it
410*d6dfd9efSDavid du Colombier 	 * should only be called when in a user context as it may
411*d6dfd9efSDavid du Colombier 	 * try to sleep if there are no pages available, but that
412*d6dfd9efSDavid du Colombier 	 * shouldn't be the case here.
413*d6dfd9efSDavid du Colombier 	 */
414*d6dfd9efSDavid du Colombier 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
415*d6dfd9efSDavid du Colombier 	p->seg[SSEG] = s;
416*d6dfd9efSDavid du Colombier 	pg = newpage(1, 0, USTKTOP-BY2PG);
417*d6dfd9efSDavid du Colombier 	segpage(s, pg);
418*d6dfd9efSDavid du Colombier 	k = kmap(pg);
419*d6dfd9efSDavid du Colombier 	bootargs(VA(k));
420*d6dfd9efSDavid du Colombier 	kunmap(k);
421*d6dfd9efSDavid du Colombier 
422*d6dfd9efSDavid du Colombier 	/*
423*d6dfd9efSDavid du Colombier 	 * Text
424*d6dfd9efSDavid du Colombier 	 */
425*d6dfd9efSDavid du Colombier 	s = newseg(SG_TEXT, UTZERO, 1);
426*d6dfd9efSDavid du Colombier 	s->flushme++;
427*d6dfd9efSDavid du Colombier 	p->seg[TSEG] = s;
428*d6dfd9efSDavid du Colombier 	pg = newpage(1, 0, UTZERO);
429*d6dfd9efSDavid du Colombier 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
430*d6dfd9efSDavid du Colombier 	segpage(s, pg);
431*d6dfd9efSDavid du Colombier 	k = kmap(s->map[0]->pages[0]);
432*d6dfd9efSDavid du Colombier 	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
433*d6dfd9efSDavid du Colombier 	sync();
434*d6dfd9efSDavid du Colombier 	kunmap(k);
435*d6dfd9efSDavid du Colombier 
436*d6dfd9efSDavid du Colombier 	ready(p);
437*d6dfd9efSDavid du Colombier }
438*d6dfd9efSDavid du Colombier 
439*d6dfd9efSDavid du Colombier /*
440*d6dfd9efSDavid du Colombier  * power-saving wait for interrupt when nothing ready.
441*d6dfd9efSDavid du Colombier  * ../port/proc.c should really call this splhi itself
442*d6dfd9efSDavid du Colombier  * to avoid the race avoided here by the call to anyready
443*d6dfd9efSDavid du Colombier  */
444*d6dfd9efSDavid du Colombier void
idlehands(void)445*d6dfd9efSDavid du Colombier idlehands(void)
446*d6dfd9efSDavid du Colombier {
447*d6dfd9efSDavid du Colombier 	int s, oldbits;
448*d6dfd9efSDavid du Colombier 
449*d6dfd9efSDavid du Colombier 	/* we only use one processor, no matter what */
450*d6dfd9efSDavid du Colombier //	if (conf.nmach > 1)
451*d6dfd9efSDavid du Colombier //		return;
452*d6dfd9efSDavid du Colombier 	s = splhi();
453*d6dfd9efSDavid du Colombier 	if(!anyready()) {
454*d6dfd9efSDavid du Colombier 		oldbits = lightstate(Ledidle);
455*d6dfd9efSDavid du Colombier 		putmsr(getmsr() | MSR_WE | MSR_EE | MSR_CE); /* MSR_DE too? */
456*d6dfd9efSDavid du Colombier 		lightstate(oldbits);
457*d6dfd9efSDavid du Colombier 	}
458*d6dfd9efSDavid du Colombier 	splx(s);
459*d6dfd9efSDavid du Colombier }
460*d6dfd9efSDavid du Colombier 
461*d6dfd9efSDavid du Colombier /*
462*d6dfd9efSDavid du Colombier  *  set mach dependent process state for a new process
463*d6dfd9efSDavid du Colombier  */
464*d6dfd9efSDavid du Colombier void
procsetup(Proc * p)465*d6dfd9efSDavid du Colombier procsetup(Proc* p)
466*d6dfd9efSDavid du Colombier {
467*d6dfd9efSDavid du Colombier 	fpusysprocsetup(p);
468*d6dfd9efSDavid du Colombier }
469*d6dfd9efSDavid du Colombier 
470*d6dfd9efSDavid du Colombier /*
471*d6dfd9efSDavid du Colombier  *  Save the mach dependent part of the process state.
472*d6dfd9efSDavid du Colombier  */
473*d6dfd9efSDavid du Colombier void
procsave(Proc * p)474*d6dfd9efSDavid du Colombier procsave(Proc *p)
475*d6dfd9efSDavid du Colombier {
476*d6dfd9efSDavid du Colombier 	fpuprocsave(p);
477*d6dfd9efSDavid du Colombier }
478*d6dfd9efSDavid du Colombier 
479*d6dfd9efSDavid du Colombier void
shutdown(int ispanic)480*d6dfd9efSDavid du Colombier shutdown(int ispanic)
481*d6dfd9efSDavid du Colombier {
482*d6dfd9efSDavid du Colombier 	int ms, once;
483*d6dfd9efSDavid du Colombier 
484*d6dfd9efSDavid du Colombier 	lock(&active);
485*d6dfd9efSDavid du Colombier 	if(ispanic)
486*d6dfd9efSDavid du Colombier 		active.ispanic = ispanic;
487*d6dfd9efSDavid du Colombier 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
488*d6dfd9efSDavid du Colombier 		active.ispanic = 0;
489*d6dfd9efSDavid du Colombier 	once = active.machs & (1<<m->machno);
490*d6dfd9efSDavid du Colombier 	active.machs &= ~(1<<m->machno);
491*d6dfd9efSDavid du Colombier 	active.exiting = 1;
492*d6dfd9efSDavid du Colombier 	unlock(&active);
493*d6dfd9efSDavid du Colombier 
494*d6dfd9efSDavid du Colombier 	if(once)
495*d6dfd9efSDavid du Colombier 		print("cpu%d: exiting\n", m->machno);
496*d6dfd9efSDavid du Colombier 	spllo();
497*d6dfd9efSDavid du Colombier 	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
498*d6dfd9efSDavid du Colombier 		delay(TK2MS(2));
499*d6dfd9efSDavid du Colombier 		if(active.machs == 0 && consactive() == 0)
500*d6dfd9efSDavid du Colombier 			break;
501*d6dfd9efSDavid du Colombier 	}
502*d6dfd9efSDavid du Colombier 
503*d6dfd9efSDavid du Colombier #ifdef notdef
504*d6dfd9efSDavid du Colombier 	if(active.ispanic && m->machno == 0){
505*d6dfd9efSDavid du Colombier 		if(cpuserver)
506*d6dfd9efSDavid du Colombier 			delay(30000);
507*d6dfd9efSDavid du Colombier 		else
508*d6dfd9efSDavid du Colombier 			for(;;)
509*d6dfd9efSDavid du Colombier 				halt();
510*d6dfd9efSDavid du Colombier 	}
511*d6dfd9efSDavid du Colombier 	else
512*d6dfd9efSDavid du Colombier #endif /* notdef */
513*d6dfd9efSDavid du Colombier 		delay(1000);
514*d6dfd9efSDavid du Colombier }
515*d6dfd9efSDavid du Colombier 
516*d6dfd9efSDavid du Colombier void
writeconf(void)517*d6dfd9efSDavid du Colombier writeconf(void)
518*d6dfd9efSDavid du Colombier {
519*d6dfd9efSDavid du Colombier 	char *p, *q;
520*d6dfd9efSDavid du Colombier 	int n;
521*d6dfd9efSDavid du Colombier 
522*d6dfd9efSDavid du Colombier 	p = getconfenv();
523*d6dfd9efSDavid du Colombier 
524*d6dfd9efSDavid du Colombier 	if(waserror()) {
525*d6dfd9efSDavid du Colombier 		free(p);
526*d6dfd9efSDavid du Colombier 		nexterror();
527*d6dfd9efSDavid du Colombier 	}
528*d6dfd9efSDavid du Colombier 
529*d6dfd9efSDavid du Colombier 	/* convert to name=value\n format */
530*d6dfd9efSDavid du Colombier 	for(q=p; *q; q++) {
531*d6dfd9efSDavid du Colombier 		q += strlen(q);
532*d6dfd9efSDavid du Colombier 		*q = '=';
533*d6dfd9efSDavid du Colombier 		q += strlen(q);
534*d6dfd9efSDavid du Colombier 		*q = '\n';
535*d6dfd9efSDavid du Colombier 	}
536*d6dfd9efSDavid du Colombier 	n = q - p + 1;
537*d6dfd9efSDavid du Colombier 	if(n >= BOOTARGSLEN)
538*d6dfd9efSDavid du Colombier 		error("kernel configuration too large");
539*d6dfd9efSDavid du Colombier 	memset(BOOTLINE, 0, BOOTLINELEN);	/* zero 9load boot line */
540*d6dfd9efSDavid du Colombier 	memmove(BOOTARGS, p, n);
541*d6dfd9efSDavid du Colombier 	poperror();
542*d6dfd9efSDavid du Colombier 	free(p);
543*d6dfd9efSDavid du Colombier }
544*d6dfd9efSDavid du Colombier 
545*d6dfd9efSDavid du Colombier void
archreboot(void)546*d6dfd9efSDavid du Colombier archreboot(void)
547*d6dfd9efSDavid du Colombier {
548*d6dfd9efSDavid du Colombier 	splhi();
549*d6dfd9efSDavid du Colombier 	iprint("reboot requested; going into wait state\n");
550*d6dfd9efSDavid du Colombier 	for(;;)
551*d6dfd9efSDavid du Colombier 		putmsr(getmsr() | MSR_WE);
552*d6dfd9efSDavid du Colombier }
553*d6dfd9efSDavid du Colombier 
554*d6dfd9efSDavid du Colombier void
exit(int ispanic)555*d6dfd9efSDavid du Colombier exit(int ispanic)
556*d6dfd9efSDavid du Colombier {
557*d6dfd9efSDavid du Colombier 	shutdown(ispanic);
558*d6dfd9efSDavid du Colombier 	archreboot();
559*d6dfd9efSDavid du Colombier }
560*d6dfd9efSDavid du Colombier 
561*d6dfd9efSDavid du Colombier static int
findconf(char * name)562*d6dfd9efSDavid du Colombier findconf(char *name)
563*d6dfd9efSDavid du Colombier {
564*d6dfd9efSDavid du Colombier 	int i;
565*d6dfd9efSDavid du Colombier 
566*d6dfd9efSDavid du Colombier 	for(i = 0; i < nconf; i++)
567*d6dfd9efSDavid du Colombier 		if(cistrcmp(confname[i], name) == 0)
568*d6dfd9efSDavid du Colombier 			return i;
569*d6dfd9efSDavid du Colombier 	return -1;
570*d6dfd9efSDavid du Colombier }
571*d6dfd9efSDavid du Colombier 
572*d6dfd9efSDavid du Colombier void
addconf(char * name,char * val)573*d6dfd9efSDavid du Colombier addconf(char *name, char *val)
574*d6dfd9efSDavid du Colombier {
575*d6dfd9efSDavid du Colombier 	int i;
576*d6dfd9efSDavid du Colombier 
577*d6dfd9efSDavid du Colombier 	i = findconf(name);
578*d6dfd9efSDavid du Colombier 	if(i < 0){
579*d6dfd9efSDavid du Colombier 		if(val == nil || nconf >= MAXCONF)
580*d6dfd9efSDavid du Colombier 			return;
581*d6dfd9efSDavid du Colombier 		i = nconf++;
582*d6dfd9efSDavid du Colombier 		strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
583*d6dfd9efSDavid du Colombier 	}
584*d6dfd9efSDavid du Colombier 	confval[i] = val;
585*d6dfd9efSDavid du Colombier }
586*d6dfd9efSDavid du Colombier 
587*d6dfd9efSDavid du Colombier char*
getconf(char * name)588*d6dfd9efSDavid du Colombier getconf(char *name)
589*d6dfd9efSDavid du Colombier {
590*d6dfd9efSDavid du Colombier 	int i;
591*d6dfd9efSDavid du Colombier 
592*d6dfd9efSDavid du Colombier 	i = findconf(name);
593*d6dfd9efSDavid du Colombier 	if(i >= 0)
594*d6dfd9efSDavid du Colombier 		return confval[i];
595*d6dfd9efSDavid du Colombier 	return nil;
596*d6dfd9efSDavid du Colombier }
597*d6dfd9efSDavid du Colombier 
598*d6dfd9efSDavid du Colombier void
dump(void * vaddr,int words)599*d6dfd9efSDavid du Colombier dump(void *vaddr, int words)
600*d6dfd9efSDavid du Colombier {
601*d6dfd9efSDavid du Colombier 	ulong *addr;
602*d6dfd9efSDavid du Colombier 
603*d6dfd9efSDavid du Colombier 	addr = vaddr;
604*d6dfd9efSDavid du Colombier 	while (words-- > 0)
605*d6dfd9efSDavid du Colombier 		print("%.8lux%c", *addr++, words % 8 == 0? '\n': ' ');
606*d6dfd9efSDavid du Colombier }
607