shithub: riscv

Download patch

ref: 35d19fc6fbd7f33a36497516ac7b0bc7d516fcc0
parent: d082e3a5ae2a9ceafd5db6f7108af0ba194b8d52
parent: 6a55790197d8eed5b7e020a7b964ae260d0d205b
author: mischief <mischief@offblast.org>
date: Sun Feb 2 02:41:56 EST 2014

merge

--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -1133,3 +1133,62 @@
 	if(doi8253set)
 		(*arch->timerset)(x);
 }
+
+/*
+ *  put the processor in the halt state if we've no processes to run.
+ *  an interrupt will get us going again.
+ *
+ *  halting in an smp system can result in a startup latency for
+ *  processes that become ready.
+ *  if idle_spin is zero, we care more about saving energy
+ *  than reducing this latency.
+ *
+ *  the performance loss with idle_spin == 0 seems to be slight
+ *  and it reduces lock contention (thus system time and real time)
+ *  on many-core systems with large values of NPROC.
+ */
+void
+idlehands(void)
+{
+	extern int nrdy, idle_spin;
+
+	if(conf.nmach == 1)
+		halt();
+	else if(m->cpuidcx & Monitor)
+		mwait(&nrdy);
+	else if(idle_spin == 0)
+		halt();
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+	char cc[32], *p;
+	int i;
+
+	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
+	p = getconf(cc);
+	if(p == nil)
+		return 0;
+
+	isa->type = "";
+	isa->nopt = tokenize(p, isa->opt, NISAOPT);
+	for(i = 0; i < isa->nopt; i++){
+		p = isa->opt[i];
+		if(cistrncmp(p, "type=", 5) == 0)
+			isa->type = p + 5;
+		else if(cistrncmp(p, "port=", 5) == 0)
+			isa->port = strtoul(p+5, &p, 0);
+		else if(cistrncmp(p, "irq=", 4) == 0)
+			isa->irq = strtoul(p+4, &p, 0);
+		else if(cistrncmp(p, "dma=", 4) == 0)
+			isa->dma = strtoul(p+4, &p, 0);
+		else if(cistrncmp(p, "mem=", 4) == 0)
+			isa->mem = strtoul(p+4, &p, 0);
+		else if(cistrncmp(p, "size=", 5) == 0)
+			isa->size = strtoul(p+5, &p, 0);
+		else if(cistrncmp(p, "freq=", 5) == 0)
+			isa->freq = strtoul(p+5, &p, 0);
+	}
+	return 1;
+}
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -1000,109 +1000,3 @@
 	shutdown(ispanic);
 	arch->reset();
 }
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[32], *p;
-	int i;
-
-	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
-	p = getconf(cc);
-	if(p == nil)
-		return 0;
-
-	isa->type = "";
-	isa->nopt = tokenize(p, isa->opt, NISAOPT);
-	for(i = 0; i < isa->nopt; i++){
-		p = isa->opt[i];
-		if(cistrncmp(p, "type=", 5) == 0)
-			isa->type = p + 5;
-		else if(cistrncmp(p, "port=", 5) == 0)
-			isa->port = strtoul(p+5, &p, 0);
-		else if(cistrncmp(p, "irq=", 4) == 0)
-			isa->irq = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "dma=", 4) == 0)
-			isa->dma = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "mem=", 4) == 0)
-			isa->mem = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "size=", 5) == 0)
-			isa->size = strtoul(p+5, &p, 0);
-		else if(cistrncmp(p, "freq=", 5) == 0)
-			isa->freq = strtoul(p+5, &p, 0);
-	}
-	return 1;
-}
-
-int
-cistrcmp(char *a, char *b)
-{
-	int ac, bc;
-
-	for(;;){
-		ac = *a++;
-		bc = *b++;
-	
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-	return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
-	unsigned ac, bc;
-
-	while(n > 0){
-		ac = *a++;
-		bc = *b++;
-		n--;
-
-		if(ac >= 'A' && ac <= 'Z')
-			ac = 'a' + (ac - 'A');
-		if(bc >= 'A' && bc <= 'Z')
-			bc = 'a' + (bc - 'A');
-
-		ac -= bc;
-		if(ac)
-			return ac;
-		if(bc == 0)
-			break;
-	}
-
-	return 0;
-}
-
-/*
- *  put the processor in the halt state if we've no processes to run.
- *  an interrupt will get us going again.
- *
- *  halting in an smp system can result in a startup latency for
- *  processes that become ready.
- *  if idle_spin is zero, we care more about saving energy
- *  than reducing this latency.
- *
- *  the performance loss with idle_spin == 0 seems to be slight
- *  and it reduces lock contention (thus system time and real time)
- *  on many-core systems with large values of NPROC.
- */
-void
-idlehands(void)
-{
-	extern int nrdy;
-
-	if(conf.nmach == 1)
-		halt();
-	else if(m->cpuidcx & Monitor)
-		mwait(&nrdy);
-	else if(idle_spin == 0)
-		halt();
-}
--- 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,24 +421,62 @@
 	schedinit();
 }
 
-void
-exit(int)
+static void
+shutdown(int ispanic)
 {
-	print("exit\n");
-	splhi();
-	for(;;);
+	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
-reboot(void*, void*, ulong)
+exit(int ispanic)
 {
-	exit(0);
+	shutdown(ispanic);
+	arch->reset();
 }
 
 void
-idlehands(void)
+reboot(void*, void*, ulong)
 {
-	halt();
+	exit(0);
 }
 
 /*
@@ -706,37 +746,4 @@
 	 * especially on VMware, but it turns out not to matter.
 	 */
 	mmuflushtlb();
-}
-
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	char cc[32], *p;
-	int i;
-
-	snprint(cc, sizeof cc, "%s%d", class, ctlrno);
-	p = getconf(cc);
-	if(p == nil)
-		return 0;
-
-	isa->type = "";
-	isa->nopt = tokenize(p, isa->opt, NISAOPT);
-	for(i = 0; i < isa->nopt; i++){
-		p = isa->opt[i];
-		if(cistrncmp(p, "type=", 5) == 0)
-			isa->type = p + 5;
-		else if(cistrncmp(p, "port=", 5) == 0)
-			isa->port = strtoul(p+5, &p, 0);
-		else if(cistrncmp(p, "irq=", 4) == 0)
-			isa->irq = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "dma=", 4) == 0)
-			isa->dma = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "mem=", 4) == 0)
-			isa->mem = strtoul(p+4, &p, 0);
-		else if(cistrncmp(p, "size=", 5) == 0)
-			isa->size = strtoul(p+5, &p, 0);
-		else if(cistrncmp(p, "freq=", 5) == 0)
-			isa->freq = strtoul(p+5, &p, 0);
-	}
-	return 1;
 }
--