ref: c3028fb924d4d112293a885733da60e2e9a730f4
parent: ddd51650d8c9c0d0fb684417728a270ed73b4629
author: cinap_lenrek <[email protected]>
date: Mon Feb 3 00:29:53 EST 2014
pc64: implement shutdown and idlehands just copies from pc kernel. should refactor into common pc code.
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -332,9 +332,19 @@
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 @@
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
/*
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -26,6 +26,8 @@
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 @@
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 @@
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();
}
/*