kernel: cleanup exit()/shutdown()/reboot() code

introduce cpushutdown() function that does the common
operation of initiating shutdown, returning once all
cpu's got the message and are about to shutdown. this
avoids duplicated code which isnt really machine specific.

automatic reboot on panic only when *debug= is not set
and the machine is a cpu server or has no display,
otherwise just hang.
This commit is contained in:
cinap_lenrek 2015-11-30 14:56:00 +01:00
parent 254031cf70
commit 7f3659e78f
32 changed files with 79 additions and 579 deletions

View file

@ -186,7 +186,6 @@ struct
Lock;
short machs;
short exiting;
short ispanic;
}active;
/*

View file

@ -308,123 +308,21 @@ setupboot(int halt)
cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);
}
/* from ../pc */
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
print("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
if(active.ispanic && m->machno == 0) {
if(cpuserver)
delay(10000);
else
for (;;)
continue;
} else
delay(1000);
}
/* from ../pc: */
void
reboot(void *entry, void *code, ulong size)
reboot(void *, void *, ulong)
{
// writeconf(); // pass kernel environment to next kernel
shutdown(0);
/*
* should be the only processor running now
*/
print("shutting down...\n");
delay(200);
splhi();
/* turn off buffered serial console */
serialoq = nil;
/* shutdown devices */
chandevshutdown();
#ifdef FUTURE
{
ulong *pdb;
/*
* Modify the machine page table to directly map the low 4MB of memory
* This allows the reboot code to turn off the page mapping
*/
pdb = m->pdb;
pdb[PDX(0)] = pdb[PDX(KZERO)];
mmuflushtlb(PADDR(pdb));
}
/* setup reboot trampoline function */
{
void (*f)(ulong, ulong, ulong) = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
#else
USED(entry, code, size);
#endif
print("rebooting...\n");
#ifdef FUTURE
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
}
#endif
setupboot(0); // reboot, don't halt
exit(0);
}
void
exit(int ispanic)
exit(int)
{
canlock(&active);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
spllo();
print("cpu %d exiting\n", m->machno);
do
delay(100);
while(consactive());
cpushutdown();
splhi();
delay(1000); /* give serial fifo time to finish flushing */
if (getconf("*debug") != nil) {
USED(ispanic);
delay(60*1000); /* give us time to read the screen */
}
if(arch->coredetach)
arch->coredetach();
setupboot(1); // set up to halt
for (; ; )
for (;;)
firmware();
// on PC is just:
//if (0) {
// shutdown(ispanic);
// arch->reset();
//}
}
void

View file

@ -225,7 +225,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
extern register Mach* m; /* R10 */

View file

@ -522,39 +522,13 @@ confinit(void)
}
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
iprint("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
delay(1000);
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int code)
exit(int)
{
shutdown(code);
cpushutdown();
splfhi();
archreboot();
}
@ -579,17 +553,8 @@ reboot(void *entry, void *code, ulong size)
{
void (*f)(ulong, ulong, ulong);
print("starting reboot...");
writeconf();
shutdown(0);
/*
* should be the only processor running now
*/
print("reboot entry %#lux code %#lux size %ld\n",
PADDR(entry), PADDR(code), size);
delay(100);
cpushutdown();
/* turn off buffered serial console */
serialoq = nil;
@ -612,10 +577,6 @@ reboot(void *entry, void *code, ulong size)
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
iprint("loaded kernel returned!\n");
delay(1000);
archreboot();
}
int

View file

@ -180,7 +180,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
#define MACHP(n) ((Mach *)(MACHADDR+(n)*BY2PG))

View file

@ -56,7 +56,6 @@ main(void)
void
reboot(void*, void*, ulong)
{
exit(0);
}
@ -64,13 +63,12 @@ reboot(void*, void*, ulong)
* exit kernel either on a panic or user request
*/
void
exit(int ispanic)
exit(int)
{
void (*f)(void);
USED(ispanic);
delay(1000);
cpushutdown();
splhi();
iprint("it's a wonderful day to die\n");
cacheflush();
mmuinvalidate();

View file

@ -196,7 +196,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
enum {

View file

@ -355,39 +355,13 @@ machinit(void)
up = nil;
}
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
iprint("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
delay(1000);
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int code)
exit(int)
{
shutdown(code);
cpushutdown();
splhi();
archreboot();
}
@ -401,17 +375,8 @@ reboot(void *entry, void *code, ulong size)
{
void (*f)(ulong, ulong, ulong);
iprint("starting reboot...");
writeconf();
shutdown(0);
/*
* should be the only processor running now
*/
print("shutting down...\n");
delay(200);
cpushutdown();
/* turn off buffered serial console */
serialoq = nil;
@ -430,19 +395,10 @@ reboot(void *entry, void *code, ulong size)
cacheuwbinv();
l2cacheuwb();
print("rebooting...");
iprint("entry %#lux code %#lux size %ld\n",
PADDR(entry), PADDR(code), size);
delay(100); /* wait for uart to quiesce */
/* off we go - never to return */
cacheuwbinv();
l2cacheuwb();
(*f)(PADDR(entry), PADDR(code), size);
iprint("loaded kernel returned!\n");
delay(1000);
archreboot();
}
/*

View file

@ -183,7 +183,6 @@ struct
Lock;
short machs;
short exiting;
short ispanic;
}active;
/*

View file

@ -211,42 +211,12 @@ userinit(void)
void
reboot(void*, void*, ulong)
{
exit(0);
}
void
exit(int ispanic)
exit(int)
{
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
print("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
if(active.ispanic && m->machno == 0){
if(cpuserver)
delay(10000);
else if(conf.monitor)
for(;;);
}
else
delay(1000);
cpushutdown();
watchreset();
}

View file

@ -218,7 +218,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
extern register Mach* m; /* R10 */

View file

@ -301,39 +301,13 @@ machinit(void)
up = nil;
}
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
iprint("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
delay(1000);
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int code)
exit(int)
{
shutdown(code);
cpushutdown();
splhi();
archreboot();
}
@ -380,17 +354,8 @@ reboot(void *entry, void *code, ulong size)
{
void (*f)(ulong, ulong, ulong);
print("starting reboot...");
writeconf();
shutdown(0);
/*
* should be the only processor running now
*/
print("reboot entry %#lux code %#lux size %ld\n",
PADDR(entry), PADDR(code), size);
delay(100);
cpushutdown();
/* turn off buffered serial console */
serialoq = nil;
@ -414,10 +379,6 @@ reboot(void *entry, void *code, ulong size)
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
iprint("loaded kernel returned!\n");
delay(1000);
archreboot();
}
/*

View file

@ -132,7 +132,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
extern Mach *m;

View file

@ -272,7 +272,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
int thunderbirdsarego; /* lets the added processors continue to schedinit */
}active;

View file

@ -163,7 +163,6 @@ main(void)
pcimatch(0, 0, 0);
}else
links();
conf.monitor = 1;
chandevreset();
pageinit();
swapinit();
@ -890,50 +889,6 @@ procsave(Proc *p)
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 calls
* 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)
{
@ -952,10 +907,7 @@ reboot(void *entry, void *code, ulong size)
procwired(up, 0);
sched();
}
shutdown(0);
iprint("shutting down...\n");
delay(200);
cpushutdown();
splhi();
@ -985,8 +937,8 @@ reboot(void *entry, void *code, ulong size)
void
exit(int ispanic)
exit(int)
{
shutdown(ispanic);
cpushutdown();
arch->reset();
}

View file

@ -664,6 +664,8 @@ bootscreeninit(void)
scr->cur = &swcursor;
scr->cur->enable(scr);
cursoron();
conf.monitor = 1;
}
/*

View file

@ -235,7 +235,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
int thunderbirdsarego; /* lets the added processors continue to schedinit */
}active;

View file

@ -512,7 +512,6 @@ main()
pcimatch(0, 0, 0);
}else
links();
conf.monitor = 1;
chandevreset();
preallocpages();
pageinit();
@ -522,54 +521,10 @@ main()
schedinit();
}
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 calls
* 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
exit(int ispanic)
exit(int)
{
shutdown(ispanic);
cpushutdown();
arch->reset();
}
@ -590,10 +545,7 @@ reboot(void *entry, void *code, ulong size)
procwired(up, 0);
sched();
}
shutdown(0);
iprint("shutting down...\n");
delay(200);
cpushutdown();
splhi();

View file

@ -86,10 +86,8 @@ iallocb(int size)
if(ialloc.bytes > conf.ialloc){
if((m1++%10000)==0){
if(mp++ > 1000){
active.exiting = 1;
exit(0);
}
if(mp++ > 1000)
panic("iallocb: out of memory");
iprint("iallocb: limited %lud/%lud\n",
ialloc.bytes, conf.ialloc);
}
@ -98,10 +96,8 @@ iallocb(int size)
if((b = _allocb(size)) == nil){
if((m2++%10000)==0){
if(mp++ > 1000){
active.exiting = 1;
exit(0);
}
if(mp++ > 1000)
panic("iallocb: out of memory");
iprint("iallocb: no memory %lud/%lud\n",
ialloc.bytes, conf.ialloc);
}

View file

@ -260,9 +260,15 @@ panic(char *fmt, ...)
splx(s);
prflush();
dumpstack();
if(!cpuserver)
for(;;);
exit(1);
/* reboot cpu servers and headless machines when not debugging */
if(getconf("*debug") == nil)
if(cpuserver || !conf.monitor)
exit(1);
/* otherwise, just hang */
while(islo()) idlehands();
for(;;);
}
/* libmp at least contains a few calls to sysfatal; simulate with panic */
@ -1038,3 +1044,26 @@ writebintime(char *buf, int n)
}
return n;
}
void
cpushutdown(void)
{
int ms, once;
lock(&active);
once = active.machs & (1<<m->machno);
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;
}
}

View file

@ -41,6 +41,7 @@ int cmount(Chan**, Chan*, int, char*);
void confinit(void);
int consactive(void);
void (*consdebug)(void);
void cpushutdown(void);
void copen(Chan*);
void cclunk(Chan*);
Block* concatblock(Block*);

View file

@ -103,6 +103,5 @@ rebootcmd(int argc, char *argv[])
setbootcmd(argc-1, argv+1);
reboot((void*)entry, p, size);
panic("return from reboot!");
error(Egreg);
}

View file

@ -78,24 +78,10 @@ uciallocb(int size)
Block *b;
static int m1, m2, mp;
if(0 && ucialloc.bytes > conf.ialloc){
if((m1++%10000)==0){
if(mp++ > 1000){
active.exiting = 1;
exit(0);
}
iprint("uciallocb: limited %lud/%lud\n",
ucialloc.bytes, conf.ialloc);
}
return nil;
}
if((b = _ucallocb(size)) == nil){
if(0 && (m2++%10000)==0){
if(mp++ > 1000){
active.exiting = 1;
exit(0);
}
if(mp++ > 1000)
panic("uciallocb: out of memory");
iprint("uciallocb: no memory %lud/%lud\n",
ucialloc.bytes, conf.ialloc);
}

View file

@ -191,7 +191,6 @@ struct
Lock;
short machs;
short exiting;
short ispanic;
}active;
/*

View file

@ -243,38 +243,10 @@ userinit(void)
}
void
exit(int ispanic)
exit(int)
{
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
print("cpu%d: exiting\n", m->machno);
spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
if(active.ispanic && m->machno == 0){
if(cpuserver)
delay(10000);
else if(conf.monitor)
for(;;);
}
else
delay(1000);
cpushutdown();
for(;;) idlehands();
}
/*
@ -424,8 +396,6 @@ confinit(void)
*/
imagmem->maxsize = kpages;
}
// conf.monitor = 1; /* BUG */
}
static int

View file

@ -206,7 +206,6 @@ struct
Lock;
long machs; /* bitmap of processors */
short exiting;
int ispanic;
}active;
extern register Mach *m;

View file

@ -372,10 +372,10 @@ userinit(void)
}
void
exit(int ispanic)
exit(int)
{
cpushutdown();
splhi();
while(ispanic);
arcs(0x18); /* reboot */
}

View file

@ -250,7 +250,6 @@ struct
int wfi; /* bitmap of CPUs in WFI state */
int stopped; /* bitmap of CPUs stopped */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
int thunderbirdsarego; /* lets the added processors continue to schedinit */
}active;

View file

@ -480,51 +480,13 @@ main(void)
panic("cpu%d: schedinit returned", m->machno);
}
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 idles non-bootstrap cpus and returns
* on bootstrap processors (to permit 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) {
delay(m->machno*1000); /* stagger them */
iprint("cpu%d: exiting\n", m->machno);
}
spllo();
if (m->machno == 0)
ms = 5*1000;
else
ms = 2*1000;
for(; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
delay(500);
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int code)
exit(int)
{
shutdown(code);
cpushutdown();
splhi();
if (m->machno == 0)
archreboot();
@ -576,10 +538,8 @@ isaconfig(char *class, int ctlrno, ISAConf *isa)
void
reboot(void *entry, void *code, ulong size)
{
int cpu, nmach, want, ms;
void (*f)(ulong, ulong, ulong);
nmach = conf.nmach;
writeconf();
/*
@ -590,33 +550,12 @@ reboot(void *entry, void *code, ulong size)
procwired(up, 0);
sched();
}
if (m->machno != 0)
print("on cpu%d (not 0)!\n", m->machno);
/*
* the other cpus could be holding locks that will never get
* released (e.g., in the print path) if we put them into
* reset now, so force them to shutdown gracefully first.
*/
for (want = 0, cpu = 1; cpu < navailcpus; cpu++)
want |= 1 << cpu;
active.stopped = 0;
shutdown(0);
for (ms = 15*1000; ms > 0 && active.stopped != want; ms -= 10)
delay(10);
delay(20);
if (active.stopped != want) {
for (cpu = 1; cpu < nmach; cpu++)
stopcpu(cpu); /* make really sure */
delay(20);
}
cpushutdown();
/*
* should be the only processor running now
*/
pcireset();
// print("reboot entry %#lux code %#lux size %ld\n",
// PADDR(entry), PADDR(code), size);
/* turn off buffered serial console */
serialoq = nil;
@ -642,9 +581,6 @@ reboot(void *entry, void *code, ulong size)
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
iprint("loaded kernel returned!\n");
archreboot();
}
/*

View file

@ -644,58 +644,13 @@ procsave(Proc *p)
mmuflushtlb(0);
}
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);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
if(once)
print("cpu%d: exiting\n", m->machno);
//spllo();
for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
delay(TK2MS(2));
if(active.machs == 0 && consactive() == 0)
break;
}
if(getconf("*debug"))
delay(5*60*1000);
if(active.ispanic){
if(!cpuserver)
for(;;)
halt();
delay(10000);
}else
delay(1000);
}
void
reboot(void *entry, void *code, ulong size)
{
void (*f)(ulong, ulong, ulong);
//ulong *pdb;
writeconf();
shutdown(0);
/*
* should be the only processor running now
*/
print("shutting down...\n");
delay(200);
cpushutdown();
splhi();
@ -709,28 +664,19 @@ reboot(void *entry, void *code, ulong size)
if(entry == 0)
HYPERVISOR_shutdown(0);
/*
* Modify the machine page table to directly map the low 4MB of memory
* This allows the reboot code to turn off the page mapping
*/
//pdb = m->pdb;
//pdb[PDX(0)] = pdb[PDX(KZERO)];
mmuflushtlb(0);
/* setup reboot trampoline function */
f = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
print("rebooting...\n");
/* off we go - never to return */
(*f)(PADDR(entry), PADDR(code), size);
}
void
exit(int ispanic)
exit(int)
{
shutdown(ispanic);
cpushutdown();
arch->reset();
}

View file

@ -177,7 +177,6 @@ struct
Lock;
int machs; /* bitmap of active CPUs */
int exiting; /* shutdown */
int ispanic; /* shutdown in response to a panic */
}active;
extern register Mach* m; /* R10 */

View file

@ -21,13 +21,13 @@ int nconf;
void
exit(int)
{
NOPE
cpushutdown();
for(;;) idlehands();
}
void
reboot(void *, void *, ulong)
{
NOPE
}
void