xref: /plan9/sys/src/9/mtx/main.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"io.h"
7 #include	"init.h"
8 #include	"pool.h"
9 
10 Conf	conf;
11 FPsave	initfp;
12 
13 void
main(void)14 main(void)
15 {
16 	memset(edata, 0, (ulong)end-(ulong)edata);
17 	conf.nmach = 1;
18 	machinit();
19 	ioinit();
20 	i8250console();
21 	quotefmtinstall();
22 	print("\nPlan 9\n");
23 	confinit();
24 	xinit();
25 	raveninit();
26 	trapinit();
27 	printinit();
28 	cpuidprint();
29 	mmuinit();
30 	hwintrinit();
31 	clockinit();
32 	kbdinit();
33 	procinit0();
34 	initseg();
35 	timersinit();
36 	links();
37 	chandevreset();
38 	pageinit();
39 	swapinit();
40 	fpsave(&initfp);
41 	initfp.fpscr = 0;
42 	userinit();
43 	schedinit();
44 }
45 
46 void
machinit(void)47 machinit(void)
48 {
49 	memset(m, 0, sizeof(Mach));
50 	m->cputype = getpvr()>>16;
51 
52 	/*
53 	 * For polled uart output at boot, need
54 	 * a default delay constant. 100000 should
55 	 * be enough for a while. Cpuidentify will
56 	 * calculate the real value later.
57 	 */
58 	m->loopconst = 100000;
59 
60 	/* turn on caches */
61 	puthid0(gethid0() | BIT(16) | BIT(17));
62 
63 	active.machs = 1;
64 	active.exiting = 0;
65 }
66 
67 void
cpuidprint(void)68 cpuidprint(void)
69 {
70 	char *id;
71 
72 	id = "unknown PowerPC";
73 	switch(m->cputype) {
74 	case 9:
75 		id = "PowerPC 604e";
76 		break;
77 	}
78 	print("cpu0: %s\n", id);
79 }
80 
81 static struct
82 {
83 	char	*name;
84 	char *val;
85 }
86 plan9ini[] =
87 {
88 	{ "console", "0" },
89 	{ "ether0", "type=2114x" },
90 };
91 
92 char*
getconf(char * name)93 getconf(char *name)
94 {
95 	int i;
96 
97 	for(i = 0; i < nelem(plan9ini); i++)
98 		if(cistrcmp(name, plan9ini[i].name) == 0)
99 			return plan9ini[i].val;
100 	return nil;
101 }
102 
103 void
init0(void)104 init0(void)
105 {
106 //	char **p, *q, name[KNAMELEN];
107 //	int n;
108 	char buf[2*KNAMELEN];
109 
110 	up->nerrlab = 0;
111 
112 	spllo();
113 
114 	/*
115 	 * These are o.k. because rootinit is null.
116 	 * Then early kproc's will have a root and dot.
117 	 */
118 	up->slash = namec("#/", Atodir, 0, 0);
119 	pathclose(up->slash->path);
120 	up->slash->path = newpath("/");
121 	up->dot = cclone(up->slash);
122 
123 	chandevinit();
124 
125 	if(!waserror()){
126 		snprint(buf, sizeof(buf), "power %s mtx", conffile);
127 		ksetenv("terminal", buf, 0);
128 		ksetenv("cputype", "power", 0);
129 		if(cpuserver)
130 			ksetenv("service", "cpu", 0);
131 		else
132 			ksetenv("service", "terminal", 0);
133 
134 /*
135 		for(p = confenv; *p; p++) {
136 			q = strchr(p[0], '=');
137 			if(q == 0)
138 				continue;
139 			n = q-p[0];
140 			if(n >= KNAMELEN)
141 				n = KNAMELEN-1;
142 			memmove(name, p[0], n);
143 			name[n] = 0;
144 			if(name[0] != '*')
145 				ksetenv(name, q+1, 0);
146 			ksetenv(name, q+1, 1);
147 		}
148 */
149 		poperror();
150 	}
151 	kproc("alarm", alarmkproc, 0);
152 	kproc("mmusweep", mmusweep, 0);
153 	touser((void*)(USTKTOP-8));
154 }
155 
156 void
userinit(void)157 userinit(void)
158 {
159 	Proc *p;
160 	Segment *s;
161 	KMap *k;
162 	Page *pg;
163 
164 	p = newproc();
165 	p->pgrp = newpgrp();
166 	p->egrp = smalloc(sizeof(Egrp));
167 	p->egrp->ref = 1;
168 	p->fgrp = dupfgrp(nil);
169 	p->rgrp = newrgrp();
170 	p->procmode = 0640;
171 
172 	kstrdup(&eve, "");
173 	kstrdup(&p->text, "*init*");
174 	kstrdup(&p->user, eve);
175 
176 	p->fpstate = FPinit;
177 
178 	/*
179 	 * Kernel Stack
180 	 *
181 	 * N.B. The -12 for the stack pointer is important.
182 	 *	4 bytes for gotolabel's return PC
183 	 */
184 	p->sched.pc = (ulong)init0;
185 	p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
186 
187 	/*
188 	 * User Stack
189 	 */
190 	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
191 	p->seg[SSEG] = s;
192 	pg = newpage(1, 0, USTKTOP-BY2PG);
193 	segpage(s, pg);
194 
195 	/*
196 	 * Text
197 	 */
198 	s = newseg(SG_TEXT, UTZERO, 1);
199 	s->flushme++;
200 	p->seg[TSEG] = s;
201 	pg = newpage(1, 0, UTZERO);
202 	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
203 	segpage(s, pg);
204 	k = kmap(s->map[0]->pages[0]);
205 	memmove((ulong*)VA(k), initcode, sizeof initcode);
206 	kunmap(k);
207 
208 	ready(p);
209 }
210 
211 /* still to do */
212 void
reboot(void *,void *,ulong)213 reboot(void*, void*, ulong)
214 {
215 	exit(0);
216 }
217 
218 void
exit(int ispanic)219 exit(int ispanic)
220 {
221 	int ms, once;
222 
223 	lock(&active);
224 	if(ispanic)
225 		active.ispanic = ispanic;
226 	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
227 		active.ispanic = 0;
228 	once = active.machs & (1<<m->machno);
229 	active.machs &= ~(1<<m->machno);
230 	active.exiting = 1;
231 	unlock(&active);
232 
233 	if(once)
234 		print("cpu%d: exiting\n", m->machno);
235 	spllo();
236 	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
237 		delay(TK2MS(2));
238 		if(active.machs == 0 && consactive() == 0)
239 			break;
240 	}
241 
242 	if(active.ispanic && m->machno == 0){
243 		if(cpuserver)
244 			delay(10000);
245 		else if(conf.monitor)
246 			for(;;);
247 	}
248 	else
249 		delay(1000);
250 
251 	watchreset();
252 }
253 
254 /*
255  *  set up floating point for a new process
256  */
257 void
procsetup(Proc * p)258 procsetup(Proc *p)
259 {
260 	p->fpstate = FPinit;
261 }
262 
263 /*
264  *  Save the mach dependent part of the process state.
265  */
266 void
procsave(Proc * p)267 procsave(Proc *p)
268 {
269 	if(p->fpstate == FPactive){
270 		if(p->state != Moribund)
271 			fpsave(&up->fpsave);
272 		p->fpstate = FPinactive;
273 	}
274 }
275 
276 void
confinit(void)277 confinit(void)
278 {
279 	char *p;
280 	int userpcnt;
281 	ulong pa, kpages;
282 	extern ulong memsize;	/* passed in from ROM monitor */
283 
284 	if(p = getconf("*kernelpercent"))
285 		userpcnt = 100 - strtol(p, 0, 0);
286 	else
287 		userpcnt = 0;
288 
289 	pa = PGROUND(PADDR(end));
290 
291 	conf.mem[0].npage = memsize/BY2PG;
292 	conf.mem[0].base = pa;
293 	conf.npage = conf.mem[0].npage;
294 
295 	conf.nmach = 1;
296 	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
297 	if(cpuserver)
298 		conf.nproc *= 3;
299 	if(conf.nproc > 2000)
300 		conf.nproc = 2000;
301 	conf.nimage = 200;
302 	conf.nswap = conf.nproc*80;
303 	conf.nswppo = 4096;
304 	conf.copymode = 0;			/* copy on write */
305 
306 	if(cpuserver) {
307 		if(userpcnt < 10)
308 			userpcnt = 70;
309 		kpages = conf.npage - (conf.npage*userpcnt)/100;
310 
311 		/*
312 		 * Hack for the big boys. Only good while physmem < 4GB.
313 		 * Give the kernel a max. of 16MB + enough to allocate the
314 		 * page pool.
315 		 * This is an overestimate as conf.upages < conf.npages.
316 		 * The patch of nimage is a band-aid, scanning the whole
317 		 * page list in imagereclaim just takes too long.
318 		 */
319 		if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
320 			kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
321 			conf.nimage = 2000;
322 			kpages += (conf.nproc*KSTACK)/BY2PG;
323 		}
324 	} else {
325 		if(userpcnt < 10) {
326 			if(conf.npage*BY2PG < 16*MB)
327 				userpcnt = 40;
328 			else
329 				userpcnt = 60;
330 		}
331 		kpages = conf.npage - (conf.npage*userpcnt)/100;
332 
333 		/*
334 		 * Make sure terminals with low memory get at least
335 		 * 4MB on the first Image chunk allocation.
336 		 */
337 		if(conf.npage*BY2PG < 16*MB)
338 			imagmem->minarena = 4*1024*1024;
339 	}
340 	conf.upages = conf.npage - kpages;
341 	conf.ialloc = (kpages/2)*BY2PG;
342 
343 	/*
344 	 * Guess how much is taken by the large permanent
345 	 * datastructures. Mntcache and Mntrpc are not accounted for
346 	 * (probably ~300KB).
347 	 */
348 	kpages *= BY2PG;
349 	kpages -= conf.upages*sizeof(Page)
350 		+ conf.nproc*sizeof(Proc)
351 		+ conf.nimage*sizeof(Image)
352 		+ conf.nswap
353 		+ conf.nswppo*sizeof(Page);
354 	mainmem->maxsize = kpages;
355 	if(!cpuserver){
356 		/*
357 		 * give terminals lots of image memory, too; the dynamic
358 		 * allocation will balance the load properly, hopefully.
359 		 * be careful with 32-bit overflow.
360 		 */
361 		imagmem->maxsize = kpages;
362 	}
363 
364 //	conf.monitor = 1;	/* BUG */
365 }
366 
367 static int
getcfields(char * lp,char ** fields,int n,char * sep)368 getcfields(char* lp, char** fields, int n, char* sep)
369 {
370 	int i;
371 
372 	for(i = 0; lp && *lp && i < n; i++){
373 		while(*lp && strchr(sep, *lp) != 0)
374 			*lp++ = 0;
375 		if(*lp == 0)
376 			break;
377 		fields[i] = lp;
378 		while(*lp && strchr(sep, *lp) == 0){
379 			if(*lp == '\\' && *(lp+1) == '\n')
380 				*lp++ = ' ';
381 			lp++;
382 		}
383 	}
384 
385 	return i;
386 }
387 
388 int
isaconfig(char * class,int ctlrno,ISAConf * isa)389 isaconfig(char *class, int ctlrno, ISAConf *isa)
390 {
391 	int i;
392 	char cc[KNAMELEN], *p;
393 
394 	sprint(cc, "%s%d", class, ctlrno);
395 
396 	p = getconf(cc);
397 	if(p == 0)
398 		return 0;
399 	isa->nopt = tokenize(p, isa->opt, NISAOPT);
400 	for(i = 0; i < isa->nopt; i++){
401 		p = isa->opt[i];
402 		if(cistrncmp(p, "type=", 5) == 0)
403 			isa->type = p + 5;
404 		else if(cistrncmp(p, "port=", 5) == 0)
405 			isa->port = strtoul(p+5, &p, 0);
406 		else if(cistrncmp(p, "irq=", 4) == 0)
407 			isa->irq = strtoul(p+4, &p, 0);
408 		else if(cistrncmp(p, "dma=", 4) == 0)
409 			isa->dma = strtoul(p+4, &p, 0);
410 		else if(cistrncmp(p, "mem=", 4) == 0)
411 			isa->mem = strtoul(p+4, &p, 0);
412 		else if(cistrncmp(p, "size=", 5) == 0)
413 			isa->size = strtoul(p+5, &p, 0);
414 		else if(cistrncmp(p, "freq=", 5) == 0)
415 			isa->freq = strtoul(p+5, &p, 0);
416 	}
417 	return 1;
418 }
419 
420 int
cistrcmp(char * a,char * b)421 cistrcmp(char *a, char *b)
422 {
423 	int ac, bc;
424 
425 	for(;;){
426 		ac = *a++;
427 		bc = *b++;
428 
429 		if(ac >= 'A' && ac <= 'Z')
430 			ac = 'a' + (ac - 'A');
431 		if(bc >= 'A' && bc <= 'Z')
432 			bc = 'a' + (bc - 'A');
433 		ac -= bc;
434 		if(ac)
435 			return ac;
436 		if(bc == 0)
437 			break;
438 	}
439 	return 0;
440 }
441 
442 int
cistrncmp(char * a,char * b,int n)443 cistrncmp(char *a, char *b, int n)
444 {
445 	unsigned ac, bc;
446 
447 	while(n > 0){
448 		ac = *a++;
449 		bc = *b++;
450 		n--;
451 
452 		if(ac >= 'A' && ac <= 'Z')
453 			ac = 'a' + (ac - 'A');
454 		if(bc >= 'A' && bc <= 'Z')
455 			bc = 'a' + (bc - 'A');
456 
457 		ac -= bc;
458 		if(ac)
459 			return ac;
460 		if(bc == 0)
461 			break;
462 	}
463 
464 	return 0;
465 }
466