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