]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ppc/main.c
kernel: reduce Page structure size by changing Page.cachectl[]
[plan9front.git] / sys / src / 9 / 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         pg->txtflush = ~0;
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         cycles(&p->kentry);
289         p->pcycles = -p->kentry;
290 }
291
292 void
293 procfork(Proc *p)
294 {
295         p->kentry = up->kentry;
296         p->pcycles = -p->kentry;
297 }
298
299 void
300 procrestore(Proc *p)
301 {
302         uvlong t;
303
304         if(p->kp)
305                 return;
306         cycles(&t);
307         p->pcycles -= t;
308         p->kentry += t;
309 }
310
311 /*
312  *  Save the mach dependent part of the process state.
313  */
314 void
315 procsave(Proc *p)
316 {
317         uvlong t;
318
319         cycles(&t);
320         p->pcycles += t;
321         p->kentry -= t;
322         if(p->fpstate == FPactive){
323                 if(p->state != Moribund)
324                         fpsave(&up->fpsave);
325                 p->fpstate = FPinactive;
326         }
327 }
328
329 void
330 confinit(void)
331 {
332         char *p;
333         int userpcnt;
334         ulong pa, kpages;
335         /* passed in from ROM monitor: */
336
337         if(p = getconf("service")){
338                 if(strcmp(p, "cpu") == 0)
339                         cpuserver = 1;
340                 else if(strcmp(p,"terminal") == 0)
341                         cpuserver = 0;
342         }
343
344         if(p = getconf("*kernelpercent"))
345                 userpcnt = 100 - strtol(p, 0, 0);
346         else
347                 userpcnt = 0;
348
349         pa = PGROUND(PADDR(end));
350
351         /* Blast Board specific */
352         conf.mem[0].npage = (MEM1SIZE - pa)/BY2PG;
353         conf.mem[0].base = pa;
354         
355         conf.mem[1].npage = MEM2SIZE/BY2PG;
356         conf.mem[1].base = MEM2BASE;
357
358         conf.npage = conf.mem[0].npage + conf.mem[1].npage;
359
360         conf.nmach = 1;
361         conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
362         if(cpuserver)
363                 conf.nproc *= 3;
364         if(conf.nproc > 2000)
365                 conf.nproc = 2000;
366         conf.nimage = 200;
367         conf.nswap = conf.nproc*80;
368         conf.nswppo = 4096;
369         conf.copymode = 0;                      /* copy on write */
370
371         if(cpuserver) {
372                 if(userpcnt < 10)
373                         userpcnt = 70;
374                 kpages = conf.npage - (conf.npage*userpcnt)/100;
375
376                 /*
377                  * Hack for the big boys. Only good while physmem < 4GB.
378                  * Give the kernel a max. of 16MB + enough to allocate the
379                  * page pool.
380                  * This is an overestimate as conf.upages < conf.npages.
381                  * The patch of nimage is a band-aid, scanning the whole
382                  * page list in imagereclaim just takes too long.
383                  */
384                 if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
385                         kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
386                         conf.nimage = 2000;
387                         kpages += (conf.nproc*KSTACK)/BY2PG;
388                 }
389         } else {
390                 if(userpcnt < 10) {
391                         if(conf.npage*BY2PG < 16*MB)
392                                 userpcnt = 40;
393                         else
394                                 userpcnt = 60;
395                 }
396                 kpages = conf.npage - (conf.npage*userpcnt)/100;
397
398                 /*
399                  * Make sure terminals with low memory get at least
400                  * 4MB on the first Image chunk allocation.
401                  */
402                 if(conf.npage*BY2PG < 16*MB)
403                         imagmem->minarena = 4*1024*1024;
404         }
405         conf.upages = conf.npage - kpages;
406         conf.ialloc = (kpages/2)*BY2PG;
407
408         /*
409          * Guess how much is taken by the large permanent
410          * datastructures. Mntcache and Mntrpc are not accounted for.
411          */
412         kpages *= BY2PG;
413         kpages -= conf.upages*sizeof(Page)
414                 + conf.nproc*sizeof(Proc)
415                 + conf.nimage*sizeof(Image)
416                 + conf.nswap
417                 + conf.nswppo*sizeof(Page*);
418         mainmem->maxsize = kpages;
419         if(!cpuserver){
420                 /*
421                  * give terminals lots of image memory, too; the dynamic
422                  * allocation will balance the load properly, hopefully.
423                  * be careful with 32-bit overflow.
424                  */
425                 imagmem->maxsize = kpages;
426         }
427
428 //      conf.monitor = 1;       /* BUG */
429 }
430
431 static int
432 getcfields(char* lp, char** fields, int n, char* sep)
433 {
434         int i;
435
436         for(i = 0; lp && *lp && i < n; i++){
437                 while(*lp && strchr(sep, *lp) != 0)
438                         *lp++ = 0;
439                 if(*lp == 0)
440                         break;
441                 fields[i] = lp;
442                 while(*lp && strchr(sep, *lp) == 0){
443                         if(*lp == '\\' && *(lp+1) == '\n')
444                                 *lp++ = ' ';
445                         lp++;
446                 }
447         }
448
449         return i;
450 }
451
452 int
453 isaconfig(char *class, int ctlrno, ISAConf *isa)
454 {
455         int i;
456         char cc[KNAMELEN], *p;
457
458         sprint(cc, "%s%d", class, ctlrno);
459
460         p = getconf(cc);
461         if(p == 0)
462                 return 0;
463         isa->nopt = tokenize(p, isa->opt, NISAOPT);
464         for(i = 0; i < isa->nopt; i++){
465                 p = isa->opt[i];
466                 if(cistrncmp(p, "type=", 5) == 0)
467                         isa->type = p + 5;
468                 else if(cistrncmp(p, "port=", 5) == 0)
469                         isa->port = strtoul(p+5, &p, 0);
470                 else if(cistrncmp(p, "irq=", 4) == 0)
471                         isa->irq = strtoul(p+4, &p, 0);
472                 else if(cistrncmp(p, "dma=", 4) == 0)
473                         isa->dma = strtoul(p+4, &p, 0);
474                 else if(cistrncmp(p, "mem=", 4) == 0)
475                         isa->mem = strtoul(p+4, &p, 0);
476                 else if(cistrncmp(p, "size=", 5) == 0)
477                         isa->size = strtoul(p+5, &p, 0);
478                 else if(cistrncmp(p, "freq=", 5) == 0)
479                         isa->freq = strtoul(p+5, &p, 0);
480         }
481         return 1;
482 }
483
484 int
485 cistrcmp(char *a, char *b)
486 {
487         int ac, bc;
488
489         for(;;){
490                 ac = *a++;
491                 bc = *b++;
492         
493                 if(ac >= 'A' && ac <= 'Z')
494                         ac = 'a' + (ac - 'A');
495                 if(bc >= 'A' && bc <= 'Z')
496                         bc = 'a' + (bc - 'A');
497                 ac -= bc;
498                 if(ac)
499                         return ac;
500                 if(bc == 0)
501                         break;
502         }
503         return 0;
504 }
505
506 int
507 cistrncmp(char *a, char *b, int n)
508 {
509         unsigned ac, bc;
510
511         while(n > 0){
512                 ac = *a++;
513                 bc = *b++;
514                 n--;
515
516                 if(ac >= 'A' && ac <= 'Z')
517                         ac = 'a' + (ac - 'A');
518                 if(bc >= 'A' && bc <= 'Z')
519                         bc = 'a' + (bc - 'A');
520
521                 ac -= bc;
522                 if(ac)
523                         return ac;
524                 if(bc == 0)
525                         break;
526         }
527
528         return 0;
529 }