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 "../ip/ip.h"
10 #include <tos.h>
11 #include <bootexec.h>
12 #include "reboot.h"
13
14 enum {
15 /* space for syscall args, return PC, top-of-stack struct */
16 Stkheadroom = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
17 };
18
19 typedef struct mipsexec Mipsexec;
20
21 /*
22 * Option arguments from the command line.
23 * oargv[0] is the boot file.
24 */
25 static int oargc;
26 static char* oargv[20];
27 static char oargb[128];
28 static int oargblen;
29
30 static uintptr sp; /* XXX - must go - user stack of init proc */
31
32 /*
33 * software tlb simulation
34 */
35 static Softtlb stlb[MAXMACH][STLBSIZE];
36
37 Conf conf;
38 FPsave initfp;
39
40 int normalprint;
41
42 char *
getconf(char *)43 getconf(char *)
44 {
45 return nil; /* stub */
46 }
47
48 static void
optionsinit(char * s)49 optionsinit(char* s)
50 {
51 strecpy(oargb, oargb+sizeof(oargb), s);
52
53 oargblen = strlen(oargb);
54 oargc = tokenize(oargb, oargv, nelem(oargv)-1);
55 oargv[oargc] = nil;
56 }
57
58 static void
prcpuid(void)59 prcpuid(void)
60 {
61 ulong cpuid, cfg1;
62 char *cpu;
63
64 cpuid = prid();
65 if (((cpuid>>16) & MASK(8)) == 0) /* vendor */
66 cpu = "old mips";
67 else if (((cpuid>>16) & MASK(8)) == 1)
68 switch ((cpuid>>8) & MASK(8)) { /* processor */
69 case 0x93:
70 cpu = "mips 24k";
71 break;
72 case 0x96:
73 cpu = "mips 24ke";
74 break;
75 default:
76 cpu = "mips";
77 break;
78 }
79 else
80 cpu = "other mips";
81 delay(20);
82 print("cpu%d: %ldMHz %s %se v%ld.%ld rev %ld, ",
83 m->machno, m->hz / Mhz, cpu, getconfig() & (1<<15)? "b": "l",
84 (cpuid>>5) & MASK(3), (cpuid>>2) & MASK(3), cpuid & MASK(2));
85 delay(200);
86 cfg1 = getconfig1();
87 print("%s fpu\n", (cfg1 & 1? "has": "no"));
88 print("cpu%d: %ld tlb entries, using %dK pages\n", m->machno,
89 ((cfg1>>25) & MASK(6)) + 1, BY2PG/1024);
90 delay(50);
91 print("cpu%d: l1 i cache: %d sets 4 ways 32 bytes/line\n", m->machno,
92 64 << ((cfg1>>22) & MASK(3)));
93 delay(50);
94 print("cpu%d: l1 d cache: %d sets 4 ways 32 bytes/line\n", m->machno,
95 64 << ((cfg1>>13) & MASK(3)));
96 delay(500);
97 if (0)
98 print("cpu%d: cycle counter res = %ld\n",
99 m->machno, gethwreg3());
100 }
101
102 static void
fmtinit(void)103 fmtinit(void)
104 {
105 printinit();
106 quotefmtinstall();
107 /* ipreset installs these when chandevreset runs */
108 fmtinstall('i', eipfmt);
109 fmtinstall('I', eipfmt);
110 fmtinstall('E', eipfmt);
111 fmtinstall('V', eipfmt);
112 fmtinstall('M', eipfmt);
113 }
114
115 static int
ckpagemask(ulong mask,ulong size)116 ckpagemask(ulong mask, ulong size)
117 {
118 int s;
119 ulong pm;
120
121 s = splhi();
122 setpagemask(mask);
123 pm = getpagemask();
124 splx(s);
125 if(pm != mask){
126 iprint("page size %ldK not supported on this cpu; "
127 "mask %#lux read back as %#lux\n", size/1024, mask, pm);
128 return -1;
129 }
130 return 0;
131 }
132
133 /* called from rebootcmd() */
134 int
parsemipsboothdr(Chan * c,ulong magic,Execvals * evp)135 parsemipsboothdr(Chan *c, ulong magic, Execvals *evp)
136 {
137 long extra;
138 Mipsexec me;
139
140 /*
141 * BOOT_MAGIC is sometimes defined like this:
142 * #define BOOT_MAGIC (0x160<<16) || magic == ((0x160<<16)|3)
143 * so we can only use it in a fairly stylized manner.
144 */
145 if(magic == BOOT_MAGIC) {
146 c->offset = 0; /* back up */
147 readn(c, &me, sizeof me);
148 /* if binary is -H1, read an extra long */
149 if (l2be(me.amagic) == 0407 && me.nscns == 0)
150 readn(c, &extra, sizeof extra);
151 evp->entry = l2be(me.mentry);
152 evp->textsize = l2be(me.tsize);
153 evp->datasize = l2be(me.dsize);
154 return 0;
155 } else
156 return -1;
157 }
158
159 void
main(void)160 main(void)
161 {
162 stopwdog(); /* tranquilise the dog */
163 optionsinit("/boot/boot boot");
164 confinit();
165 savefpregs(&initfp);
166
167 machinit(); /* calls clockinit */
168 active.exiting = 0;
169 active.machs = 1;
170
171 kmapinit();
172 xinit();
173
174 timersinit();
175 fmtinit();
176 vecinit();
177
178 normalprint = 1;
179 print("\nPlan 9\n");
180 prcpuid();
181 if (PTECACHABILITY == PTENONCOHERWT)
182 print("caches configured as write-through\n");
183 if (0)
184 xsummary();
185
186 ckpagemask(PGSZ, BY2PG);
187 tlbinit();
188 machwire();
189 pageinit();
190 procinit0();
191 initseg();
192 links();
193 chandevreset();
194
195 swapinit();
196 userinit();
197 sicwdog();
198 parseboothdr = parsemipsboothdr;
199 schedinit();
200 panic("schedinit returned");
201 }
202
203 /*
204 * initialize a processor's mach structure. each processor does this
205 * for itself.
206 */
207 void
machinit(void)208 machinit(void)
209 {
210 /* Ensure CU1 is off */
211 clrfpintr();
212
213 m->stb = &stlb[m->machno][0];
214
215 clockinit();
216 }
217
218 /*
219 * setup MIPS trap vectors
220 */
221 void
vecinit(void)222 vecinit(void)
223 {
224 memmove((ulong*)UTLBMISS, (ulong*)vector0, 0x80);
225 memmove((ulong*)XEXCEPTION, (ulong*)vector0, 0x80);
226 memmove((ulong*)CACHETRAP, (ulong*)vector100, 0x80);
227 memmove((ulong*)EXCEPTION, (ulong*)vector180, 0x80);
228 memmove((ulong*)(KSEG0+0x200), (ulong*)vector180, 0x80);
229 icflush((ulong*)UTLBMISS, 4*1024);
230
231 setstatus(getstatus() & ~BEV);
232 }
233
234 void
init0(void)235 init0(void)
236 {
237 char buf[128];
238
239 up->nerrlab = 0;
240
241 spllo();
242
243 /*
244 * These are o.k. because rootinit is null.
245 * Then early kproc's will have a root and dot.
246 */
247 up->slash = namec("#/", Atodir, 0, 0);
248 pathclose(up->slash->path);
249 up->slash->path = newpath("/");
250 up->dot = cclone(up->slash);
251
252 chandevinit();
253
254 if(!waserror()){
255 ksetenv("cputype", "mips", 0);
256 snprint(buf, sizeof buf, "mips %s rb450g", conffile);
257 ksetenv("terminal", buf, 0);
258 if(cpuserver)
259 ksetenv("service", "cpu", 0);
260 else
261 ksetenv("service", "terminal", 0);
262 /*
263 * we don't have a good way to read our cfg file in
264 * RouterBOOT, so set the configuration here.
265 */
266 ksetenv("nobootprompt", "tcp", 0);
267 ksetenv("nvram", "/boot/nvram", 0);
268 poperror();
269 }
270 kproc("alarm", alarmkproc, 0);
271 i8250console();
272 touser(sp);
273 }
274
275 FPsave initfp;
276
277 static void
bootargs(uintptr base)278 bootargs(uintptr base)
279 {
280 int i;
281 ulong ssize;
282 char **av, *p;
283
284 /*
285 * Push the boot args onto the stack.
286 * The initial value of the user stack must be such
287 * that the total used is larger than the maximum size
288 * of the argument list checked in syscall.
289 */
290 i = oargblen+1;
291 p = UINT2PTR(STACKALIGN(base + BY2PG - Stkheadroom - i));
292 memmove(p, oargb, i);
293
294 /*
295 * Now push the argv pointers.
296 * The code jumped to by touser in lproc.s expects arguments
297 * main(char* argv0, ...)
298 * and calls
299 * startboot("/boot/boot", &argv0)
300 * not the usual (int argc, char* argv[])
301 */
302 av = (char**)(p - (oargc+1)*sizeof(char*));
303 ssize = base + BY2PG - PTR2UINT(av);
304 for(i = 0; i < oargc; i++)
305 *av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
306 *av = nil;
307 sp = USTKTOP - ssize;
308 }
309
310 void
userinit(void)311 userinit(void)
312 {
313 Proc *p;
314 KMap *k;
315 Page *pg;
316 Segment *s;
317
318 p = newproc();
319 p->pgrp = newpgrp();
320 p->egrp = smalloc(sizeof(Egrp));
321 p->egrp->ref = 1;
322 p->fgrp = dupfgrp(nil);
323 p->rgrp = newrgrp();
324 p->procmode = 0640;
325
326 kstrdup(&eve, "");
327 kstrdup(&p->text, "*init*");
328 kstrdup(&p->user, eve);
329
330 p->fpstate = FPinit;
331 p->fpsave.fpstatus = initfp.fpstatus;
332
333 /*
334 * Kernel Stack
335 */
336 p->sched.pc = (ulong)init0;
337 p->sched.sp = (ulong)p->kstack+KSTACK-Stkheadroom;
338 p->sched.sp = STACKALIGN(p->sched.sp);
339
340 /*
341 * User Stack
342 *
343 * Technically, newpage can't be called here because it
344 * should only be called when in a user context as it may
345 * try to sleep if there are no pages available, but that
346 * shouldn't be the case here.
347 */
348 s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
349 p->seg[SSEG] = s;
350 pg = newpage(1, 0, USTKTOP-BY2PG);
351 segpage(s, pg);
352 k = kmap(pg);
353 bootargs(VA(k));
354 kunmap(k);
355
356 /*
357 * Text
358 */
359 s = newseg(SG_TEXT, UTZERO, 1);
360 s->flushme++;
361 p->seg[TSEG] = s;
362 pg = newpage(1, 0, UTZERO);
363 memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
364 segpage(s, pg);
365 k = kmap(s->map[0]->pages[0]);
366 memset((void *)VA(k), 0, BY2PG);
367 memmove((ulong*)VA(k), initcode, sizeof initcode);
368 kunmap(k);
369
370 ready(p);
371 }
372
373 void
procrestore(Proc * p)374 procrestore(Proc *p)
375 {
376 uvlong t;
377
378 if(p->kp)
379 return;
380 cycles(&t);
381 p->pcycles -= t;
382 }
383
384 /*
385 * Save the mach dependent part of the process state.
386 */
387 void
procsave(Proc * p)388 procsave(Proc *p)
389 {
390 uvlong t;
391
392 cycles(&t);
393 p->pcycles += t;
394 /* no fpu, so no fp state to save */
395 }
396
397 static void
writeconf(void)398 writeconf(void)
399 {
400 char *p, *q;
401 int n;
402
403 p = getconfenv();
404
405 if(waserror()) {
406 free(p);
407 nexterror();
408 }
409
410 /* convert to name=value\n format */
411 for(q=p; *q; q++) {
412 q += strlen(q);
413 *q = '=';
414 q += strlen(q);
415 *q = '\n';
416 }
417 n = q - p + 1;
418 #ifdef BOOTARGS_EXIST
419 if(n >= BOOTARGSLEN)
420 error("kernel configuration too large");
421 memmove(BOOTARGS, p, n);
422 memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
423 #endif
424 USED(n);
425 poperror();
426 free(p);
427 }
428
429 static void
shutdown(int ispanic)430 shutdown(int ispanic)
431 {
432 int ms, once;
433
434 ilock(&active);
435 if(ispanic)
436 active.ispanic = ispanic;
437 else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
438 active.ispanic = 0;
439 once = active.machs & (1<<m->machno);
440 /*
441 * setting exiting will make hzclock() on each processor call exit(0),
442 * which calls shutdown(0) and idles non-bootstrap cpus and returns
443 * on bootstrap processors (to permit a reboot). clearing our bit
444 * in machs avoids calling exit(0) from hzclock() on this processor.
445 */
446 active.machs &= ~(1<<m->machno);
447 active.exiting = 1;
448 iunlock(&active);
449
450 if(once) {
451 delay(m->machno*1000); /* stagger them */
452 iprint("cpu%d: exiting\n", m->machno);
453 }
454 spllo();
455 ms = MAXMACH * 1000;
456 for(; ms > 0; ms -= TK2MS(2)){
457 delay(TK2MS(2));
458 if(active.machs == 0 && consactive() == 0)
459 break;
460 }
461 delay(100);
462 }
463
464 /*
465 * the new kernel is already loaded at address `code'
466 * of size `size' and entry point `entry'.
467 */
468 void
reboot(void * entry,void * code,ulong size)469 reboot(void *entry, void *code, ulong size)
470 {
471 void (*f)(ulong, ulong, ulong);
472
473 writeconf();
474
475 /*
476 * the boot processor is cpu0. execute this function on it
477 * so that the new kernel has the same cpu0.
478 */
479 if (m->machno != 0) {
480 procwired(up, 0);
481 sched();
482 }
483 if (m->machno != 0)
484 print("on cpu%d (not 0)!\n", m->machno);
485
486 shutdown(0);
487
488 /*
489 * should be the only processor running now
490 */
491 // iprint("reboot: entry %#p code %#p size %ld\n", entry, code, size);
492 // iprint("code[0] = %#lux\n", *(ulong *)code);
493
494 /* turn off buffered serial console */
495 serialoq = nil;
496 kprintoq = nil;
497 screenputs = nil;
498
499 /* shutdown devices */
500 chandevshutdown();
501
502 /* call off the dog */
503 clockshutdown();
504
505 splhi();
506 intrshutdown();
507
508 /* is the watchdog tied into the usb machinery? */
509 // *Reset |= Rstusbohcidll | Rstusbhost | Rstusbphy;
510 // Rstge0mac | Rstge0phy |
511 // Rstge1mac | Rstge1phy;
512
513 /* setup reboot trampoline function */
514 f = (void*)REBOOTADDR;
515 memmove(f, rebootcode, sizeof(rebootcode));
516 icflush(f, sizeof(rebootcode));
517
518 setstatus(BEV); /* also, kernel mode, no interrupts */
519 coherence();
520
521 /* off we go - never to return */
522 (*f)((ulong)entry, (ulong)code, size);
523
524 panic("loaded kernel returned!");
525 }
526
527 void
exit(int type)528 exit(int type)
529 {
530 int timer;
531 void (*fnp)(void);
532
533 stopwdog();
534
535 delay(1000);
536 lock(&active);
537 active.machs &= ~(1<<m->machno);
538 active.exiting = 1;
539 unlock(&active);
540 spllo();
541
542 print("cpu %d exiting\n", m->machno);
543 timer = 0;
544 while(active.machs || consactive()) {
545 if(timer++ > 400)
546 break;
547 delay(10);
548 }
549 delay(1000);
550 splhi();
551 USED(type);
552
553 setstatus(BEV);
554 coherence();
555
556 iprint("exit: awaiting reset\n");
557 wdogreset(); /* wake the dog with v. short timeout */
558
559 // *Reset |= Rstfullchip;
560 // *Reset |= Rstcpucold;
561
562 delay(1000); /* await a reset */
563
564 iprint("exit: jumping to rom\n");
565 fnp = (void (*)(void))ROM;
566 (*fnp)();
567
568 iprint("exit: looping\n");
569 for (;;)
570 ;
571 }
572
573 void
idlehands(void)574 idlehands(void)
575 {
576 stopwdog();
577 idle();
578 sicwdog(); /* wake the dog */
579 }
580
581 void
confinit(void)582 confinit(void)
583 {
584 ulong kpages, ktop;
585
586 /*
587 * divide memory twixt user pages and kernel.
588 */
589 conf.mem[0].base = ktop = PADDR(PGROUND((ulong)end));
590 /* fixed memory on routerboard */
591 conf.mem[0].npage = MEMSIZE/BY2PG - ktop/BY2PG;
592 conf.npage = conf.mem[0].npage;
593 conf.nuart = 1;
594
595 kpages = conf.npage - (conf.npage*80)/100;
596 if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
597 kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
598 kpages += (conf.nproc*KSTACK)/BY2PG;
599 }
600 conf.upages = conf.npage - kpages;
601 conf.ialloc = (kpages/2)*BY2PG;
602
603 kpages *= BY2PG;
604 kpages -= conf.upages*sizeof(Page)
605 + conf.nproc*sizeof(Proc)
606 + conf.nimage*sizeof(Image)
607 + conf.nswap
608 + conf.nswppo*sizeof(Page);
609 mainmem->maxsize = kpages;
610
611 /*
612 * set up CPU's mach structure
613 * cpu0's was zeroed in l.s and our stack is in Mach, so don't zero it.
614 */
615 m->machno = 0;
616 m->speed = 680; /* initial guess at MHz, for rb450g */
617 m->hz = m->speed * Mhz;
618 conf.nmach = 1;
619
620 /* set up other configuration parameters */
621 conf.nproc = 2000;
622 conf.nswap = 262144;
623 conf.nswppo = 4096;
624 conf.nimage = 200;
625
626 conf.copymode = 0; /* copy on write */
627 }
628