git: 9front

Download patch

ref: 4474fc6f24a5cdc319a3937884f51380a15717b2
parent: 751d73c598ddac68c4204c9dd38f9a1ee6168e73
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Fri May 4 07:02:11 EDT 2012

kernel: use monitor/mwait instruction on pc multiprocessor for idlehands

--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -218,6 +218,7 @@
 	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
 	uvlong	cpuhz;
 	int	cpuidax;
+	int	cpuidcx;
 	int	cpuiddx;
 	char	cpuidid[16];
 	char*	cpuidtype;
@@ -277,6 +278,9 @@
 
 /* cpuid instruction result register bits */
 enum {
+	/* cx */
+	Monitor	= 1<<3,
+
 	/* dx */
 	Fpuonchip = 1<<0,
 //	Pse	= 1<<3,		/* page size extensions */
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -732,8 +732,8 @@
 	if(m->cpuidid[0])
 		i += sprint(buf+i, "%12.12s ", m->cpuidid);
 	seprint(buf+i, buf + sizeof buf - 1,
-		"%s (cpuid: AX 0x%4.4uX DX 0x%4.4uX)\n",
-		m->cpuidtype, m->cpuidax, m->cpuiddx);
+		"%s (cpuid: AX 0x%4.4uX CX 0x%4.4uX DX 0x%4.4uX)\n",
+		m->cpuidtype, m->cpuidax, m->cpuidcx, m->cpuiddx);
 	print(buf);
 }
 
@@ -766,6 +766,7 @@
 
 	cpuid(Procsig, regs);
 	m->cpuidax = regs[0];
+	m->cpuidcx = regs[2];
 	m->cpuiddx = regs[3];
 
 	if(strncmp(m->cpuidid, "AuthenticAMD", 12) == 0 ||
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -42,6 +42,7 @@
 char*	getconf(char*);
 void	guesscpuhz(int);
 void	halt(void);
+void	mwait(void*);
 int	i8042auxcmd(int);
 int	i8042auxcmds(uchar*, int);
 void	i8042auxenable(void (*)(int, int));
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -855,6 +855,21 @@
 	HLT
 	RET
 
+TEXT mwait(SB), $0
+	MOVL	addr+0(FP), 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
+
 /*
  * Interrupt/exception handling.
  * Each entry in the vector table calls either _strayintr or _strayintrx depending
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -868,6 +868,10 @@
 void
 idlehands(void)
 {
+	extern int nrdy;
+
 	if(conf.nmach == 1)
 		halt();
+	else if(m->cpuidcx & Monitor)
+		mwait(&nrdy);
 }
--