#include "reboot.h"
Mach *m;
-
-/*
- * Where configuration info is left for the loaded programme.
- * This will turn into a structure as more is done by the boot loader
- * (e.g. why parse the .ini file twice?).
- * There are 3584 bytes available at CONFADDR.
- */
-#define BOOTLINE ((char*)CONFADDR)
-#define BOOTLINELEN 64
-#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
-#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
-#define MAXCONF 64
-
-char bootdisk[KNAMELEN];
Conf conf;
-char *confname[MAXCONF];
-char *confval[MAXCONF];
-int nconf;
-uchar *sp; /* user stack of init proc */
+
int delaylink;
int idle_spin;
-static void
-multibootargs(void)
-{
- char *cp, *ep;
- ulong *m, l;
-
- extern ulong *multiboot;
-
- if(multiboot == nil)
- return;
-
- /* 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*)((ulong)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();
-
- /*
- * parse configuration args from dos file plan9.ini
- */
- cp = BOOTARGS; /* where b.com leaves its config */
- cp[BOOTARGSLEN-1] = 0;
-
- /*
- * Strip out '\r', change '\t' -> ' '.
- */
- p = cp;
- for(q = cp; *q; q++){
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
- *p = 0;
-
- n = getfields(cp, line, MAXCONF, 1, "\n");
- for(i = 0; i < n; i++){
- if(*line[i] == '#')
- continue;
- cp = strchr(line[i], '=');
- if(cp == nil)
- continue;
- *cp++ = '\0';
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
-}
-
-extern void mmuinit0(void);
extern void (*i8237alloc)(void);
+extern void bootscreeninit(void);
+extern void multibootdebug(void);
void
main(void)
{
mach0init();
- options();
+ bootargsinit();
ioinit();
i8250console();
quotefmtinstall();
screeninit();
print("\nPlan 9\n");
-
+
trapinit0();
- mmuinit0();
-
- kbdinit();
i8253init();
cpuidentify();
meminit();
confinit();
- archinit();
xinit();
+ archinit();
+ bootscreeninit();
if(i8237alloc != nil)
i8237alloc();
trapinit();
arch->intrinit();
timersinit();
mathinit();
- kbdenable();
if(arch->clockenable)
arch->clockenable();
procinit0();
pcimatch(0, 0, 0);
}else
links();
- conf.monitor = 1;
chandevreset();
pageinit();
- swapinit();
userinit();
- active.thunderbirdsarego = 1;
schedinit();
}
machinit();
- active.machs = 1;
+ active.machs[0] = 1;
active.exiting = 0;
- active.rebooting = 0;
}
void
void
init0(void)
{
- int i;
- char buf[2*KNAMELEN];
+ char buf[2*KNAMELEN], **sp;
up->nerrlab = 0;
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
- for(i = 0; i < nconf; i++){
- if(confname[i][0] != '*')
- ksetenv(confname[i], confval[i], 0);
- ksetenv(confname[i], confval[i], 1);
- }
+ setconfenv();
poperror();
}
kproc("alarm", alarmkproc, 0);
+
+ sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
+ sp[3] = sp[2] = nil;
+ strcpy(sp[1] = (char*)&sp[4], "boot");
+ sp[0] = nil;
touser(sp);
}
s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
p->seg[SSEG] = s;
pg = newpage(0, 0, USTKTOP-BY2PG);
+ segpage(s, pg);
v = tmpmap(pg);
memset(v, 0, BY2PG);
- segpage(s, pg);
- bootargs(v);
tmpunmap(v);
/*
s->flushme++;
p->seg[TSEG] = s;
pg = newpage(0, 0, UTZERO);
- memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ pg->txtflush = ~0;
segpage(s, pg);
v = tmpmap(pg);
memset(v, 0, BY2PG);
ready(p);
}
-uchar *
-pusharg(char *p)
-{
- int n;
-
- n = strlen(p)+1;
- sp -= n;
- memmove(sp, p, n);
- return sp;
-}
-
-void
-bootargs(void *base)
-{
- int i, ac;
- uchar *av[32];
- uchar **lsp;
- char *cp = BOOTLINE;
- char buf[64];
-
- sp = (uchar*)base + BY2PG - sizeof(Tos);
-
- ac = 0;
- av[ac++] = pusharg("boot");
-
- /* when boot is changed to only use rc, this code can go away */
- cp[BOOTLINELEN-1] = 0;
- buf[0] = 0;
- if(strncmp(cp, "fd", 2) == 0){
- sprint(buf, "local!#f/fd%lddisk", strtol(cp+2, 0, 0));
- av[ac++] = pusharg(buf);
- } else if(strncmp(cp, "sd", 2) == 0){
- sprint(buf, "local!#S/sd%c%c/fs", *(cp+2), *(cp+3));
- av[ac++] = pusharg(buf);
- } else if(strncmp(cp, "ether", 5) == 0)
- av[ac++] = pusharg("-n");
-
- /* 4 byte word align stack */
- sp = (uchar*)((ulong)sp & ~3);
-
- /* build argc, argv on stack */
- sp -= (ac+1)*sizeof(sp);
- lsp = (uchar**)sp;
- for(i = 0; i < ac; i++)
- lsp[i] = av[i] + ((USTKTOP - BY2PG) - (ulong)base);
- lsp[i] = 0;
- sp += (USTKTOP - BY2PG) - (ulong)base;
- sp -= BY2WD;
-}
-
-char*
-getconf(char *name)
-{
- int i;
-
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- return confval[i];
- 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)
{
if(userpcnt < 10)
userpcnt = 70;
kpages = conf.npage - (conf.npage*userpcnt)/100;
+ conf.nimage = conf.nproc;
/*
* Hack for the big boys. Only good while physmem < 4GB.
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 {
/*
* Guess how much is taken by the large permanent
- * datastructures. Mntcache and Mntrpc are not accounted for
- * (probably ~300KB).
+ * datastructures. Mntcache and Mntrpc are not accounted for.
*/
kpages *= BY2PG;
kpages -= conf.upages*sizeof(Page)
}
/*
- * we keep FPsave structure in sse format emulating FXSAVE / FXRSTOR
+ * we keep FPsave structure in SSE format emulating FXSAVE / FXRSTOR
* instructions for legacy x87 fpu.
- *
- * Note that fpx87restore() and fpxsserestore() do modify the FPsave
- * data structure for conversion / realignment shuffeling. this means
- * that p->fpsave is only valid when p->fpstate == FPinactive.
*/
void
fpx87save(FPsave *fps)
fpx87restore0(fps);
}
-/*
- * sse fp save and restore buffers have to be 16-byte (FPalign) aligned,
- * so we shuffle the data up and down as needed or make copies.
- */
-void
-fpssesave(FPsave *fps)
-{
- FPsave *afps;
-
- afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
- fpssesave0(afps);
- if(fps != afps) /* not aligned? shuffle down from aligned buffer */
- memmove(fps, afps, sizeof(FPssestate) - FPalign);
-}
-
-void
-fpsserestore(FPsave *fps)
-{
- FPsave *afps;
-
- afps = (FPsave *)ROUND(((uintptr)fps), FPalign);
- if(fps != afps) /* shuffle up to make aligned */
- memmove(afps, fps, sizeof(FPssestate) - FPalign);
- fpsserestore0(afps);
-}
-
static char* mathmsg[] =
{
nil, /* handled below */
/*
* get floating point state to check out error
*/
- fpenv(&up->fpsave);
- mathnote(up->fpsave.status, up->fpsave.pc);
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ mathnote(up->fpsave->fsw, up->fpsave->fpuip);
+}
+
+/*
+ * SIMD error
+ */
+static void
+simderror(Ureg *ureg, void*)
+{
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ mathnote(up->fpsave->mxcsr & 0x3f, ureg->pc);
}
/*
switch(up->fpstate){
case FPinit:
fpinit();
+ if(fpsave == fpssesave)
+ ldmxcsr(0x1f80); /* no simd exceptions on 386 */
+ while(up->fpsave == nil)
+ up->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
up->fpstate = FPactive;
break;
case FPinactive:
* More attention should probably be paid here to the
* exception masks and error summary.
*/
- status = up->fpsave.fsw;
- control = up->fpsave.fcw;
+ status = up->fpsave->fsw;
+ control = up->fpsave->fcw;
if((status & ~control) & 0x07F){
- mathnote(status, up->fpsave.fpuip);
+ mathnote(status, up->fpsave->fpuip);
break;
}
- fprestore(&up->fpsave);
+ fprestore(up->fpsave);
up->fpstate = FPactive;
break;
case FPactive:
intrenable(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror");
trapenable(VectorCNA, mathemu, 0, "mathemu");
trapenable(VectorCSO, mathover, 0, "mathover");
+ trapenable(VectorSIMD, simderror, 0, "simderror");
}
/*
memset(p->gdt, 0, sizeof(p->gdt));
p->ldt = nil;
p->nldt = 0;
+
+ memset(p->dr, 0, sizeof(p->dr));
}
void
s = splhi();
switch(up->fpstate & ~FPillegal){
case FPactive:
- fpsave(&up->fpsave);
+ fpsave(up->fpsave);
up->fpstate = FPinactive;
case FPinactive:
- p->fpsave = up->fpsave;
+ while(p->fpsave == nil)
+ p->fpsave = mallocalign(sizeof(FPsave), FPalign, 0, 0);
+ memmove(p->fpsave, up->fpsave, sizeof(FPsave));
p->fpstate = FPinactive;
}
+
+ /* clear debug registers */
+ memset(p->dr, 0, sizeof(p->dr));
splx(s);
}
procrestore(Proc *p)
{
uvlong t;
+
+ if(p->dr[7] != 0){
+ m->dr7 = p->dr[7];
+ putdr(p->dr);
+ }
+
+ if(p->vmx != nil)
+ vmxprocrestore(p);
if(p->kp)
return;
procsave(Proc *p)
{
uvlong t;
+
+ /* we could just always putdr7(0) but accessing DR7 might be slow in a VM */
+ if(m->dr7 != 0){
+ m->dr7 = 0;
+ putdr7(0);
+ }
cycles(&t);
p->kentry -= t;
* until the process runs again and generates an
* emulation fault to activate the FPU.
*/
- fpsave(&p->fpsave);
+ fpsave(p->fpsave);
}
p->fpstate = FPinactive;
}
mmuflushtlb(PADDR(m->pdb));
}
-static void
-shutdown(int ispanic)
-{
- int ms, once;
-
- lock(&active);
- if(ispanic)
- active.ispanic = ispanic;
- else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
- active.ispanic = 0;
- once = active.machs & (1<<m->machno);
- /*
- * setting exiting will make hzclock() on each processor call exit(0),
- * which calls shutdown(0) and arch->reset(), which on mp systems is
- * mpshutdown, from which there is no return: the processor is idled
- * or initiates a reboot. clearing our bit in machs avoids calling
- * exit(0) from hzclock() on this processor.
- */
- active.machs &= ~(1<<m->machno);
- active.exiting = 1;
- unlock(&active);
-
- if(once)
- iprint("cpu%d: exiting\n", m->machno);
-
- /* wait for any other processors to shutdown */
- spllo();
- for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
- delay(TK2MS(2));
- if(active.machs == 0 && consactive() == 0)
- break;
- }
-
- if(active.ispanic){
- if(!cpuserver)
- for(;;)
- halt();
- if(getconf("*debug"))
- delay(5*60*1000);
- else
- delay(10000);
- }
-}
-
void
reboot(void *entry, void *code, ulong size)
{
ulong *pdb;
writeconf();
+ vmxshutdown();
/*
* the boot processor is cpu0. execute this function on it
procwired(up, 0);
sched();
}
-
- lock(&active);
- active.rebooting = 1;
- unlock(&active);
-
- shutdown(0);
-
- /*
- * should be the only processor running now
- */
- if (m->machno != 0)
- iprint("on cpu%d (not 0)!\n", m->machno);
- if (active.machs)
- iprint("still have active ap processors!\n");
-
- iprint("shutting down...\n");
- delay(200);
+ cpushutdown();
splhi();
void
-exit(int ispanic)
+exit(int)
{
- shutdown(ispanic);
+ cpushutdown();
arch->reset();
}