shithub: riscv

Download patch

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();
 }
 
 /*