diff options
| -rw-r--r-- | sys/src/9/pc64/l.s | 38 | ||||
| -rw-r--r-- | sys/src/9/pc64/main.c | 63 |
2 files changed, 90 insertions, 11 deletions
diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index 65aebb07b..e1eb310b1 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -332,9 +332,19 @@ TEXT mb586(SB), 1, $-4 RET /* + * Park a processor. Should never fall through a return from main to here, + * should only be called by application processors when shutting down. + */ +TEXT idle(SB), 1, $-4 +_idle: + STI + HLT + JMP _idle + +/* * BIOS32. */ -TEXT bios32call(SB), 1, $-1 +TEXT bios32call(SB), 1, $-4 XORL AX, AX INCL AX RET @@ -526,14 +536,30 @@ TEXT setlabel(SB), 1, $-4 MOVL $0, AX /* return 0 */ RET -TEXT idle(SB), $0 -_idle: +TEXT halt(SB), 1, $-4 + CLI + CMPL nrdy(SB), $0 + JEQ _nothingready + STI + RET +_nothingready: STI HLT - JMP _idle + RET -TEXT halt(SB), 1, $-4 - HLT +TEXT mwait(SB), 1, $-4 + MOVQ RARG, AX + MOVL (AX), CX + ORL CX, CX + JNZ _mwaitdone + XORL DX, DX + BYTE $0x0f; BYTE $0x01; BYTE $0xc8 /* MONITOR */ + MOVL (AX), CX + ORL CX, CX + JNZ _mwaitdone + XORL AX, AX + BYTE $0x0f; BYTE $0x01; BYTE $0xc9 /* MWAIT */ +_mwaitdone: RET /* diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 8c07566c7..8ad503288 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -26,6 +26,8 @@ char *confname[MAXCONF]; char *confval[MAXCONF]; int nconf; int delaylink; +int idle_spin; + uchar *sp; /* user stack of init proc */ extern void (*i8237alloc)(void); @@ -419,12 +421,56 @@ 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 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); + }else + delay(1000); +} + void -exit(int) +exit(int ispanic) { - print("exit\n"); - splhi(); - for(;;); + shutdown(ispanic); + arch->reset(); } void @@ -436,7 +482,14 @@ reboot(void*, void*, ulong) void idlehands(void) { - halt(); + extern int nrdy; + + if(conf.nmach == 1) + halt(); + else if(m->cpuidcx & Monitor) + mwait(&nrdy); + else if(idle_spin == 0) + halt(); } /* |
