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