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