2 #include "../port/lib.h"
15 #define BOOTARGS (xenstart->cmd_line)
16 #define BOOTARGSLEN (sizeof xenstart->cmd_line)
20 /* space for syscall args, return PC, top-of-stack struct */
21 Ustkheadroom = sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
25 char *confname[MAXCONF];
26 char *confval[MAXCONF];
28 uchar *sp; /* user stack of init proc */
35 char *cp, *line[MAXCONF], *p, *q;
38 * parse configuration args from dos file plan9.ini
40 cp = BOOTARGS; /* where b.com leaves its config */
41 cp[BOOTARGSLEN-1] = 0;
44 * Strip out '\r', change '\t' -> ' '.
56 n = getfields(cp, line, MAXCONF, 1, "\n");
57 for(i = 0; i < n; i++){
60 cp = strchr(line[i], '=');
64 confname[nconf] = line[i];
80 print("\nPlan 9 (%s)\n", xenstart->magic);
83 // meminit() is not for us
91 if(arch->intrinit) /* launches other processors on an mp */
116 MACHP(0) = (Mach*)CPU0MACH;
117 m->pdb = (ulong*)xenstart->pt_base;
133 memset(m, 0, sizeof(Mach));
139 * For polled uart output at boot, need
140 * a default delay constant. 100000 should
141 * be enough for a while. Cpuidentify will
142 * calculate the real value later.
144 m->loopconst = 100000;
145 m->cpumhz = 1000; // XXX!
147 HYPERVISOR_shared_info = (shared_info_t*)mmumapframe(XENSHARED, (xenstart->shared_info)>>PGSHIFT);
149 // XXX m->shared = &HYPERVISOR_shared_info->vcpu_data[m->machno];
156 char buf[2*KNAMELEN];
163 * These are o.k. because rootinit is null.
164 * Then early kproc's will have a root and dot.
166 up->slash = namec("#/", Atodir, 0, 0);
167 pathclose(up->slash->path);
168 up->slash->path = newpath("/");
169 up->dot = cclone(up->slash);
174 snprint(buf, sizeof(buf), "%s %s", arch->id, conffile);
175 ksetenv("terminal", buf, 0);
176 ksetenv("cputype", "386", 0);
178 ksetenv("service", "cpu", 0);
180 ksetenv("service", "terminal", 0);
181 ksetenv("readparts", "1", 0);
182 for(i = 0; i < nconf; i++){
183 if(confname[i][0] != '*')
184 ksetenv(confname[i], confval[i], 0);
185 ksetenv(confname[i], confval[i], 1);
190 kproc("alarm", alarmkproc, 0);
204 p->egrp = smalloc(sizeof(Egrp));
206 p->fgrp = dupfgrp(nil);
211 kstrdup(&p->text, "*init*");
212 kstrdup(&p->user, eve);
220 * N.B. make sure there's enough space for syscall to check
222 * 4 bytes for gotolabel's return PC
224 p->sched.pc = (ulong)init0;
225 p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
230 s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
232 pg = newpage(1, 0, USTKTOP-BY2PG);
241 s = newseg(SG_TEXT, UTZERO, 1);
244 pg = newpage(1, 0, UTZERO);
247 k = kmap(s->map[0]->pages[0]);
248 memmove((ulong*)VA(k), initcode, sizeof initcode);
271 sp = (uchar*)base + BY2PG - Ustkheadroom;
274 av[ac++] = pusharg("boot");
275 av[ac++] = pusharg("-D");
277 /* 4 byte word align stack */
278 sp = (uchar*)((ulong)sp & ~3);
280 /* build argc, argv on stack */
281 sp -= (ac+1)*sizeof(sp);
283 for(i = 0; i < ac; i++)
284 *lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
286 sp += (USTKTOP - BY2PG) - base - sizeof(ulong);
294 for(i = 0; i < nconf; i++)
295 if(cistrcmp(confname[i], name) == 0)
313 /* convert to name=value\n format */
322 error("kernel configuration too large");
323 memmove(BOOTARGS, p, n);
335 for(i = 0; i < nconf; i++)
336 print("%s=%s\n", confname[i], confval[i]);
338 * all ram above xentop is free, but must be mappable
339 * to virt addrs less than VIRT_START.
341 kpages = PADDR(hypervisor_virt_start)>>PGSHIFT;
342 if(xenstart->nr_pages <= kpages)
343 kpages = xenstart->nr_pages;
345 print("Warning: Plan 9 / Xen limitation - "
346 "using only %lud of %lud available RAM pages\n",
347 kpages, xenstart->nr_pages);
348 xentop = PGROUND(PADDR(xentop));
349 conf.mem[0].npage = kpages - (xentop>>PGSHIFT);
350 conf.mem[0].base = xentop;
352 if(p = getconf("*kernelpercent"))
353 userpcnt = 100 - strtol(p, 0, 0);
358 for(i=0; i<nelem(conf.mem); i++)
359 conf.npage += conf.mem[i].npage;
361 conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
364 if(conf.nproc > 2000)
367 conf.nswap = conf.nproc*80;
373 kpages = conf.npage - (conf.npage*userpcnt)/100;
376 * Hack for the big boys. Only good while physmem < 4GB.
377 * Give the kernel fixed max + enough to allocate the
379 * This is an overestimate as conf.upages < conf.npages.
380 * The patch of nimage is a band-aid, scanning the whole
381 * page list in imagereclaim just takes too long.
383 if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
384 kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
386 kpages += (conf.nproc*KSTACK)/BY2PG;
390 if(conf.npage*BY2PG < 16*MB)
395 kpages = conf.npage - (conf.npage*userpcnt)/100;
398 * Make sure terminals with low memory get at least
399 * 4MB on the first Image chunk allocation.
401 if(conf.npage*BY2PG < 16*MB)
402 imagmem->minarena = 4*1024*1024;
406 * can't go past the end of virtual memory
407 * (ulong)-KZERO is 2^32 - KZERO
409 if(kpages > ((ulong)-KZERO)/BY2PG)
410 kpages = ((ulong)-KZERO)/BY2PG;
412 conf.upages = conf.npage - kpages;
413 conf.ialloc = (kpages/2)*BY2PG;
416 * Guess how much is taken by the large permanent
417 * datastructures. Mntcache and Mntrpc are not accounted for.
420 kpages -= conf.upages*sizeof(Page)
421 + conf.nproc*sizeof(Proc)
422 + conf.nimage*sizeof(Image)
424 + conf.nswppo*sizeof(Page*);
425 mainmem->maxsize = kpages;
428 * give terminals lots of image memory, too; the dynamic
429 * allocation will balance the load properly, hopefully.
430 * be careful with 32-bit overflow.
432 imagmem->maxsize = kpages;
436 static char* mathmsg[] =
438 nil, /* handled below */
439 "denormalized operand",
451 char *msg, note[ERRMAX];
453 status = up->fpsave->status;
456 * Some attention should probably be paid here to the
457 * exception masks and error summary.
459 msg = "unknown exception";
460 for(i = 1; i <= 5; i++){
461 if(!((1<<i) & status))
469 msg = "stack overflow";
471 msg = "stack underflow";
473 msg = "invalid operation";
475 snprint(note, sizeof note, "sys: fp: %s fppc=0x%lux status=0x%lux",
476 msg, up->fpsave->pc, status);
477 postnote(up, 1, note, NDebug);
481 * math coprocessor error
484 matherror(Ureg *ur, void*)
487 * a write cycle to port 0xF0 clears the interrupt latch attached
488 * to the error# line from the 387
490 if(!(m->cpuiddx & 0x01))
494 * save floating point state to check out error
500 panic("fp: status %ux fppc=0x%lux pc=0x%lux",
501 up->fpsave->status, up->fpsave->pc, ur->pc);
505 * math coprocessor emulation fault
508 mathemu(Ureg *ureg, void*)
510 if(up->fpstate & FPillegal){
511 /* someone did floating point in a note handler */
512 postnote(up, 1, "sys: floating point in note handler", NDebug);
518 while(up->fpsave == nil)
519 up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
520 up->fpstate = FPactive;
524 * Before restoring the state, check for any pending
525 * exceptions, there's no way to restore the state without
526 * generating an unmasked exception.
527 * More attention should probably be paid here to the
528 * exception masks and error summary.
530 if((up->fpsave->status & ~up->fpsave->control) & 0x07F){
534 fprestore(up->fpsave);
535 up->fpstate = FPactive;
538 panic("math emu pid %ld %s pc 0x%lux",
539 up->pid, up->text, ureg->pc);
545 * math coprocessor segment overrun
548 mathover(Ureg*, void*)
550 pexit("math overrun", 0);
556 trapenable(VectorCERR, matherror, 0, "matherror");
557 //if(X86FAMILY(m->cpuidax) == 3)
558 // intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
559 trapenable(VectorCNA, mathemu, 0, "mathemu");
560 trapenable(VectorCSO, mathover, 0, "mathover");
564 * set up floating point for a new process
578 p->kentry = up->kentry;
579 p->pcycles = -p->kentry;
581 /* save floating point state */
583 switch(up->fpstate & ~FPillegal){
586 up->fpstate = FPinactive;
588 while(p->fpsave == nil)
589 p->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
590 memmove(p->fpsave, up->fpsave, sizeof(FPsave));
591 p->fpstate = FPinactive;
608 * Save the mach dependent part of the process state.
617 if(p->fpstate == FPactive){
618 if(p->state == Moribund)
622 * Fpsave() stores without handling pending
623 * unmasked exeptions. Postnote() can't be called
624 * here as sleep() already has up->rlock, so
625 * the handling of pending exceptions is delayed
626 * until the process runs again and generates an
627 * emulation fault to activate the FPU.
631 p->fpstate = FPinactive;
635 * While this processor is in the scheduler, the process could run
636 * on another processor and exit, returning the page tables to
637 * the free list where they could be reallocated and overwritten.
638 * When this processor eventually has to get an entry from the
639 * trashed page tables it will crash.
641 * If there's only one processor, this can't happen.
642 * You might think it would be a win not to do this in that case,
643 * especially on VMware, but it turns out not to matter.
649 reboot(void *entry, void *code, ulong size)
651 void (*f)(ulong, ulong, ulong);
658 /* turn off buffered serial console */
661 /* shutdown devices */
664 /* reboot(0, ...) on Xen causes domU shutdown */
666 HYPERVISOR_shutdown(0);
670 /* setup reboot trampoline function */
671 f = (void*)REBOOTADDR;
672 memmove(f, rebootcode, sizeof(rebootcode));
674 /* off we go - never to return */
675 (*f)(PADDR(entry), PADDR(code), size);