#include "ureg.h"
#include "init.h"
#include "pool.h"
+#include "reboot.h"
/*
* Where configuration info is left for the loaded programme.
extern void (*i8237alloc)(void);
+static void
+multibootargs(void)
+{
+ extern ulong multibootptr;
+ ulong *multiboot;
+ char *cp, *ep;
+ ulong *m, l;
+
+ if(multibootptr == 0)
+ return;
+
+ multiboot = (ulong*)KADDR(multibootptr);
+ /* command line */
+ if((multiboot[0] & (1<<2)) != 0)
+ strncpy(BOOTLINE, KADDR(multiboot[4]), BOOTLINELEN-1);
+
+ cp = BOOTARGS;
+ ep = cp + BOOTARGSLEN-1;
+
+ /* memory map */
+ if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){
+ cp = seprint(cp, ep, "*e820=");
+ m = KADDR(multiboot[12]);
+ while(m[0] >= 20 && m[0] <= l-4){
+ uvlong base, size;
+ m++;
+ base = ((uvlong)m[0] | (uvlong)m[1]<<32);
+ size = ((uvlong)m[2] | (uvlong)m[3]<<32);
+ cp = seprint(cp, ep, "%.1lux %.16llux %.16llux ",
+ m[4] & 0xF, base, base+size);
+ l -= m[-1]+4;
+ m = (ulong*)((uintptr)m + m[-1]);
+ }
+ cp[-1] = '\n';
+ }
+
+ /* plan9.ini passed as the first module */
+ if((multiboot[0] & (1<<3)) != 0 && multiboot[5] > 0){
+ m = KADDR(multiboot[6]);
+ l = m[1] - m[0];
+ m = KADDR(m[0]);
+ if(cp+l > ep)
+ l = ep - cp;
+ memmove(cp, m, l);
+ cp += l;
+ }
+ *cp = 0;
+}
+
static void
options(void)
{
long i, n;
char *cp, *line[MAXCONF], *p, *q;
- // multibootargs();
+ multibootargs();
/*
* parse configuration args from dos file plan9.ini
return 0;
}
+static void
+writeconf(void)
+{
+ char *p, *q;
+ int n;
+
+ p = getconfenv();
+
+ if(waserror()) {
+ free(p);
+ nexterror();
+ }
+
+ /* convert to name=value\n format */
+ for(q=p; *q; q++) {
+ q += strlen(q);
+ *q = '=';
+ q += strlen(q);
+ *q = '\n';
+ }
+ n = q - p + 1;
+ if(n >= BOOTARGSLEN)
+ error("kernel configuration too large");
+ memset(BOOTLINE, 0, BOOTLINELEN);
+ memmove(BOOTARGS, p, n);
+ poperror();
+ free(p);
+}
+
void
confinit(void)
{
int i, userpcnt;
ulong kpages;
+ if(p = getconf("service")){
+ if(strcmp(p, "cpu") == 0)
+ cpuserver = 1;
+ else if(strcmp(p,"terminal") == 0)
+ cpuserver = 0;
+ }
+
if(p = getconf("*kernelpercent"))
userpcnt = 100 - strtol(p, 0, 0);
else
if(userpcnt < 10)
userpcnt = 70;
kpages = conf.npage - (conf.npage*userpcnt)/100;
-
- /*
- * Hack for the big boys. Only good while physmem < 4GB.
- * Give the kernel fixed max + enough to allocate the
- * page pool.
- * This is an overestimate as conf.upages < conf.npages.
- * The patch of nimage is a band-aid, scanning the whole
- * page list in imagereclaim just takes too long.
- */
- if(getconf("*imagemaxmb") == 0)
- if(kpages > (64*MB + conf.npage*sizeof(Page))/BY2PG){
- kpages = (64*MB + conf.npage*sizeof(Page))/BY2PG;
- conf.nimage = 2000;
- kpages += (conf.nproc*KSTACK)/BY2PG;
- }
} else {
if(userpcnt < 10) {
if(conf.npage*BY2PG < 16*MB)
* (probably ~300KB).
*/
kpages *= BY2PG;
- kpages -= conf.upages*sizeof(Page)
- + conf.nproc*sizeof(Proc)
+ kpages -= conf.nproc*sizeof(Proc)
+ conf.nimage*sizeof(Image)
+ conf.nswap
+ conf.nswppo*sizeof(Page*);
}
}
+/*
+ * The palloc.pages array can be a large chunk out of the 2GB
+ * window above KZERO, so we allocate the array from
+ * upages and map in the VMAP window before pageinit()
+ */
+static void
+preallocpages(void)
+{
+ Pallocmem *pm;
+ uintptr va, base, top;
+ vlong size;
+ ulong np;
+ int i;
+
+ np = 0;
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ np += pm->npage;
+ }
+ size = (uvlong)np * BY2PG;
+ size += sizeof(Page) + BY2PG; /* round up */
+ size = (size / (sizeof(Page) + BY2PG)) * sizeof(Page);
+ size = ROUND(size, PGLSZ(1));
+
+ for(i=0; i<nelem(palloc.mem); i++){
+ pm = &palloc.mem[i];
+ base = ROUND(pm->base, PGLSZ(1));
+ top = pm->base + (uvlong)pm->npage * BY2PG;
+ if((base + size) <= VMAPSIZE && (vlong)(top - base) >= size){
+ va = base + VMAP;
+ pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTEVALID, va, size);
+ palloc.pages = (Page*)va;
+ pm->base = base + size;
+ pm->npage = (top - pm->base)/BY2PG;
+ break;
+ }
+ }
+}
void
machinit(void)
p->sched.pc = (uintptr)init0;
p->sched.sp = (uintptr)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
+ /* temporarily set up for kmap() */
+ up = p;
+
/*
* User Stack
*/
memmove(v, initcode, sizeof initcode);
kunmap(v);
+ /* free kmap */
+ mmurelease(p);
+ up = nil;
+
ready(p);
}
mach0init();
options();
ioinit();
- // i8250console();
+ i8250console();
quotefmtinstall();
screeninit();
+ print("\nPlan 9\n");
trapinit0();
kbdinit();
i8253init();
links();
conf.monitor = 1;
chandevreset();
+ preallocpages();
pageinit();
swapinit();
userinit();
delay(5*60*1000);
else
delay(10000);
- }else
- delay(1000);
+ }
}
void
}
void
-reboot(void*, void*, ulong)
+reboot(void *entry, void *code, ulong size)
{
- exit(0);
-}
+ void (*f)(uintptr, uintptr, ulong);
-void
-idlehands(void)
-{
- extern int nrdy;
-
- if(conf.nmach == 1)
- halt();
- else if(m->cpuidcx & Monitor)
- mwait(&nrdy);
- else if(idle_spin == 0)
- halt();
+ writeconf();
+
+ /*
+ * the boot processor is cpu0. execute this function on it
+ * so that the new kernel has the same cpu0. this only matters
+ * because the hardware has a notion of which processor was the
+ * boot processor and we look at it at start up.
+ */
+ if (m->machno != 0) {
+ procwired(up, 0);
+ sched();
+ }
+ shutdown(0);
+
+ iprint("shutting down...\n");
+ delay(200);
+
+ splhi();
+
+ /* turn off buffered serial console */
+ serialoq = nil;
+
+ /* shutdown devices */
+ chandevshutdown();
+ arch->introff();
+
+ /*
+ * This allows the reboot code to turn off the page mapping
+ */
+ *mmuwalk(m->pml4, 0, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
+ *mmuwalk(m->pml4, 0, 2, 0) = *mmuwalk(m->pml4, KZERO, 2, 0);
+ mmuflushtlb();
+
+ /* setup reboot trampoline function */
+ f = (void*)REBOOTADDR;
+ memmove(f, rebootcode, sizeof(rebootcode));
+
+ /* off we go - never to return */
+ coherence();
+ (*f)((uintptr)entry & ~0xF0000000UL, (uintptr)PADDR(code), size);
}
/*
mathnote(up->fpsave.fsw, up->fpsave.rip);
}
+/*
+ * SIMD error
+ */
+static void
+simderror(Ureg *ureg, void*)
+{
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc);
+}
+
/*
* math coprocessor emulation fault
*/
_fninit();
_fwait();
_fldcw(0x0232);
- /*
- * TODO: sse exceptions
- * _ldmxcsr(m->mxcsr);
- *
- */
+ _ldmxcsr(0x1900);
up->fpstate = FPactive;
break;
case FPinactive:
intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
trapenable(VectorCNA, mathemu, 0, "mathemu");
trapenable(VectorCSO, mathover, 0, "mathover");
+ trapenable(VectorSIMD, simderror, 0, "simderror");
}
void
*/
mmuflushtlb();
}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
- char cc[32], *p;
- int i;
-
- snprint(cc, sizeof cc, "%s%d", class, ctlrno);
- p = getconf(cc);
- if(p == nil)
- return 0;
-
- isa->type = "";
- isa->nopt = tokenize(p, isa->opt, NISAOPT);
- for(i = 0; i < isa->nopt; i++){
- p = isa->opt[i];
- if(cistrncmp(p, "type=", 5) == 0)
- isa->type = p + 5;
- else if(cistrncmp(p, "port=", 5) == 0)
- isa->port = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "irq=", 4) == 0)
- isa->irq = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "dma=", 4) == 0)
- isa->dma = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "mem=", 4) == 0)
- isa->mem = strtoul(p+4, &p, 0);
- else if(cistrncmp(p, "size=", 5) == 0)
- isa->size = strtoul(p+5, &p, 0);
- else if(cistrncmp(p, "freq=", 5) == 0)
- isa->freq = strtoul(p+5, &p, 0);
- }
- return 1;
-}