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