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