9front - general discussion about 9front
 help / color / mirror / Atom feed
From: Robert Ransom <rransom.8774@gmail.com>
To: 9front@9front.org
Cc: cinap_lenrek@felloff.net
Subject: Re: [9front] Kernel patches (cpufreqctl, Radeon on amd64, trivia)
Date: Sat, 11 Jan 2020 16:24:10 -0500	[thread overview]
Message-ID: <CABqy+spp1+n85_FEq50MEKb=FVc37neyujaV0pkJDq+BGgdO5Q@mail.gmail.com> (raw)
In-Reply-To: <76481B02AE084AE907C892C25C6715F4@felloff.net>

[-- Attachment #1: Type: text/plain, Size: 247 bytes --]

On 1/11/20, cinap_lenrek@felloff.net <cinap_lenrek@felloff.net> wrote:
> applied the trivial ones.
>
> Patch 7514, 7515, 7517, 7518 got mangled (by postmaster@ewsd?) in the mail.
> can you resubmit please and put me directly in CC?

See attached.

[-- Attachment #2: 7514.patch --]
[-- Type: text/x-patch, Size: 10456 bytes --]

# HG changeset patch
# User Robert Ransom <rransom.8774@gmail.com>
# Date 1578147512 18000
# Node ID 939ab197463703d4835622103bde410bd0a2acd7
# Parent  85dfb4d0d5ee93073cde636cc5288e72116b46e5
Adapt vgaradeon driver to 64-bit

Not yet tested.

diff --git a/sys/src/9/pc/vgaradeon.c b/sys/src/9/pc/vgaradeon.c
--- a/sys/src/9/pc/vgaradeon.c
+++ b/sys/src/9/pc/vgaradeon.c
@@ -28,45 +28,45 @@
 /* mmio access */
 
 static void
-OUTREG8(ulong mmio, ulong offset, uchar val)
+OUTREG8(ulong *mmio, ulong offset, uchar val)
 {
-	((uchar*)KADDR((mmio + offset)))[0] = val;
+	((uchar*)KADDR((((uintptr)mmio) + offset)))[0] = val;
 }
 
 static void
-OUTREG(ulong mmio, ulong offset, ulong val)
+OUTREG(ulong *mmio, ulong offset, ulong val)
 {
-	((ulong*)KADDR((mmio + offset)))[0] = val;
+	((ulong*)KADDR((((uintptr)mmio) + offset)))[0] = val;
 }
 
 static ulong
-INREG(ulong mmio, ulong offset)
+INREG(ulong *mmio, ulong offset)
 {
-	return ((ulong*)KADDR((mmio + offset)))[0];
+	return ((ulong*)KADDR((((uintptr)mmio) + offset)))[0];
 }
 
 static void
-OUTREGP(ulong mmio, ulong offset, ulong val, ulong mask)
+OUTREGP(ulong *mmio, ulong offset, ulong val, ulong mask)
 {
 	OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
 }
 
 static void
-OUTPLL(ulong mmio, ulong offset, ulong val)
+OUTPLL(ulong *mmio, ulong offset, ulong val)
 {
 	OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
 	OUTREG(mmio, CLOCK_CNTL_DATA, val);
 }
 
 static ulong
-INPLL(ulong mmio, ulong offset)
+INPLL(ulong *mmio, ulong offset)
 {
 	OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
 	return INREG(mmio, CLOCK_CNTL_DATA);
 }
 
 static void
-OUTPLLP(ulong mmio, ulong offset, ulong val, ulong mask)
+OUTPLLP(ulong *mmio, ulong offset, ulong val, ulong mask)
 {
 	OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
 }
@@ -174,10 +174,10 @@
 		y = 0;
 	}
 
-	OUTREG((ulong)scr->mmio, CUR_OFFSET, storage + oy * 256);
-	OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_OFF,
+	OUTREG(scr->mmio, CUR_OFFSET, storage + oy * 256);
+	OUTREG(scr->mmio, CUR_HORZ_VERT_OFF,
 		(ox & 0x7fff) << 16 | (oy & 0x7fff));
-	OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_POSN,
+	OUTREG(scr->mmio, CUR_HORZ_VERT_POSN,
 		(x & 0x7fff) << 16 | (y & 0x7fff));
 	return 0;
 }
@@ -187,7 +187,7 @@
 {
 	if(scr->mmio == nil)
 		return;
-	OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
+	OUTREGP(scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
 }
 
 static void
@@ -200,11 +200,11 @@
 
 	radeoncurdisable(scr);
 	storage = scr->apsize - 1*Meg;
-	scr->storage = (ulong)KADDR(scr->paddr + storage);
+	scr->storage = (uintptr)KADDR(scr->paddr + storage);
 	radeoncurload(scr, &arrow);
 	radeoncurmove(scr, ZP);
 
-	OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
+	OUTREGP(scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
 		~(CRTC_CUR_EN | 3<<20));
 }
 
@@ -223,24 +223,24 @@
 
 	mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
 	if (blank == 0) {
-		OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
+		OUTREGP(scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
 		return;
 	}
 
 	cp = getconf("*dpms");
 	if (cp) {
 		if (strcmp(cp, "standby") == 0)
-			OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
+			OUTREGP(scr->mmio, CRTC_EXT_CNTL,
 				CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
 		else if (strcmp(cp, "suspend") == 0)
-			OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
+			OUTREGP(scr->mmio, CRTC_EXT_CNTL,
 				CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
 		else if (strcmp(cp, "off") == 0)
-			OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
+			OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
 		return;
 	}
 
-	OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
+	OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
 }
 
 /* hw acceleration */
@@ -251,7 +251,7 @@
 	int i;
 
 	for (i = 0; i < 2000000; i++)
-		if (INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
+		if (INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
 		    entries)
 			return;
 	iprint("radeon: fifo timeout\n");
@@ -266,12 +266,12 @@
 		int i;
 
 		for (i = 0; i < 2000000; i++)
-			if (!(INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
+			if (!(INREG(scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
 				return;
 
 		iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
-			INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
-			INREG((ulong)scr->mmio, RBBM_STATUS));
+			INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
+			INREG(scr->mmio, RBBM_STATUS));
 	}
 }
 
@@ -284,15 +284,15 @@
 		return 0;
 
 	radeonwaitfifo(scr, 6);
-	OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
+	OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
 		dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
 		GMC_SRC_DATATYPE_COLOR | ROP3_P);
-	OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, color);
-	OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
-	OUTREG((ulong)scr->mmio, DP_CNTL,
+	OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, color);
+	OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
+	OUTREG(scr->mmio, DP_CNTL,
 		DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
-	OUTREG((ulong)scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
-	OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
+	OUTREG(scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
+	OUTREG(scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
 
 	radeonwaitidle(scr);
 	return 1;
@@ -329,14 +329,14 @@
 		dp_cntl |= DST_X_LEFT_TO_RIGHT;
 
 	radeonwaitfifo(scr, 6);
-	OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
+	OUTREG(scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
 		GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
 		ROP3_S);
-	OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
-	OUTREG((ulong)scr->mmio, DP_CNTL, dp_cntl);
-	OUTREG((ulong)scr->mmio, SRC_Y_X, ys << 16 | xs);
-	OUTREG((ulong)scr->mmio, DST_Y_X, yd << 16 | xd);
-	OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
+	OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
+	OUTREG(scr->mmio, DP_CNTL, dp_cntl);
+	OUTREG(scr->mmio, SRC_Y_X, ys << 16 | xs);
+	OUTREG(scr->mmio, DST_Y_X, yd << 16 | xd);
+	OUTREG(scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
 
 	radeonwaitidle(scr);
 
@@ -376,75 +376,75 @@
 	}
 
 	/* disable 3D */
-	OUTREG((ulong)scr->mmio, RB3D_CNTL, 0);
+	OUTREG(scr->mmio, RB3D_CNTL, 0);
 
 	/* flush engine */
-	OUTREGP((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT,
+	OUTREGP(scr->mmio, RB2D_DSTCACHE_CTLSTAT,
 		RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
 	for (i = 0; i < 2000000; i++)
-		if (!(INREG((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
+		if (!(INREG(scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
 		    RB2D_DC_BUSY))
 			break;
 
 	/* reset 2D engine */
-	clock_cntl_index = INREG((ulong)scr->mmio, CLOCK_CNTL_INDEX);
+	clock_cntl_index = INREG(scr->mmio, CLOCK_CNTL_INDEX);
 
-	mclk_cntl = INPLL((ulong)scr->mmio, MCLK_CNTL);
-	OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
+	mclk_cntl = INPLL(scr->mmio, MCLK_CNTL);
+	OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
 		FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
 		FORCEON_AIC);
-	rbbm_soft_reset = INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
+	rbbm_soft_reset = INREG(scr->mmio, RBBM_SOFT_RESET);
 
-	OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
+	OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
 		SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
 		SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
-	INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
-	OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
+	INREG(scr->mmio, RBBM_SOFT_RESET);
+	OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
 		~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
 		SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
-	INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
+	INREG(scr->mmio, RBBM_SOFT_RESET);
 
-	OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl);
-	OUTREG((ulong)scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
+	OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl);
+	OUTREG(scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
 
 	/* init 2D engine */
 	radeonwaitfifo(scr, 1);
-	OUTREG((ulong)scr->mmio, RB2D_DSTCACHE_MODE, 0);
+	OUTREG(scr->mmio, RB2D_DSTCACHE_MODE, 0);
 
 	pitch = Dx(scr->gscreen->r) * bpp;
 	radeonwaitfifo(scr, 4);
-	OUTREG((ulong)scr->mmio, DEFAULT_PITCH, pitch);
-	OUTREG((ulong)scr->mmio, DST_PITCH, pitch);
-	OUTREG((ulong)scr->mmio, SRC_PITCH, pitch);
-	OUTREG((ulong)scr->mmio, DST_PITCH_OFFSET_C, 0);
+	OUTREG(scr->mmio, DEFAULT_PITCH, pitch);
+	OUTREG(scr->mmio, DST_PITCH, pitch);
+	OUTREG(scr->mmio, SRC_PITCH, pitch);
+	OUTREG(scr->mmio, DST_PITCH_OFFSET_C, 0);
 
 	radeonwaitfifo(scr, 3);
-	OUTREG((ulong)scr->mmio, DEFAULT_OFFSET, 0);
-	OUTREG((ulong)scr->mmio, DST_OFFSET, 0);
-	OUTREG((ulong)scr->mmio, SRC_OFFSET, 0);
+	OUTREG(scr->mmio, DEFAULT_OFFSET, 0);
+	OUTREG(scr->mmio, DST_OFFSET, 0);
+	OUTREG(scr->mmio, SRC_OFFSET, 0);
 
 	radeonwaitfifo(scr, 1);
-	OUTREGP((ulong)scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
+	OUTREGP(scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
 
 	radeonwaitfifo(scr, 1);
-	OUTREG((ulong)scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
+	OUTREG(scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
 		DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
 
 	dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
 		GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
 		GMC_CLR_CMP_CNTL_DIS;
 	radeonwaitfifo(scr, 1);
-	OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
+	OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
 	    dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
 
 	radeonwaitfifo(scr, 7);
-	OUTREG((ulong)scr->mmio, DST_LINE_START,    0);
-	OUTREG((ulong)scr->mmio, DST_LINE_END,      0);
-	OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
-	OUTREG((ulong)scr->mmio, DP_BRUSH_BKGD_CLR, 0);
-	OUTREG((ulong)scr->mmio, DP_SRC_FRGD_CLR,   ~0ul);
-	OUTREG((ulong)scr->mmio, DP_SRC_BKGD_CLR,   0);
-	OUTREG((ulong)scr->mmio, DP_WRITE_MASK,     ~0ul);
+	OUTREG(scr->mmio, DST_LINE_START,    0);
+	OUTREG(scr->mmio, DST_LINE_END,      0);
+	OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
+	OUTREG(scr->mmio, DP_BRUSH_BKGD_CLR, 0);
+	OUTREG(scr->mmio, DP_SRC_FRGD_CLR,   ~0ul);
+	OUTREG(scr->mmio, DP_SRC_BKGD_CLR,   0);
+	OUTREG(scr->mmio, DP_WRITE_MASK,     ~0ul);
 
 	radeonwaitidle(scr);
 
diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -129,7 +129,7 @@
 #	vgamga4xx	+cur
 #	vganeomagic	+cur
 #	vganvidia	+cur
-#	vgaradeon	+cur
+	vgaradeon	+cur
 #	vgargb524	=cur
 #	vgas3		+cur vgasavage
 #	vgat2r4		+cur

[-- Attachment #3: 7515.patch --]
[-- Type: text/x-patch, Size: 2817 bytes --]

# HG changeset patch
# User Robert Ransom <rransom.8774@gmail.com>
# Date 1578147960 18000
# Node ID 48a158c0731b26c142a404cc3fdd04e679a3bca1
# Parent  939ab197463703d4835622103bde410bd0a2acd7
Add minimal CPU frequency support for AMD family 10h and later

This uses the 'hardware P-state control' present through the
current family 17h processors.  Family 10h also has the registers
for the older software COF/VID control mechanism required by family
0fh (and earlier?), so this really ought to be generalized to
support more than one type of CPU frequency control on the same
system.

diff --git a/sys/src/9/pc/cpufreq.c b/sys/src/9/pc/cpufreq.c
new file mode 100644
--- /dev/null
+++ b/sys/src/9/pc/cpufreq.c
@@ -0,0 +1,97 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+	CMpowersave,
+};
+
+static Cmdtab amdpstatectlmsg[] = {
+	CMpowersave,	"powersave",	1,
+};
+
+static int
+amdpstatecpufreqok(void)
+{
+	ulong regs[4];
+
+	if(strcmp(m->cpuidid, "AuthenticAMD") == 0){
+		cpuid(0x80000007, regs);
+		return (regs[3] & (1 << 7)) != 0;
+	}
+	return 0;
+}
+
+static void
+amdpstateset(ulong pst)
+{
+	vlong cmdmsr;
+	long i;
+	Mach *w;
+
+	w = up->wired;
+	cmdmsr = pst & 15;
+	for(i = 0; i < conf.nmach; ++i){
+		procwired(up, i);
+		sched();
+		if(wrmsr(0xC0010062, cmdmsr) < 0)
+			print("error setting P-state %uld on mach %ld\n", pst, i);
+	}
+	up->wired = w;
+	sched();
+}
+
+static void
+amdpstatectl(Cmdbuf *cb)
+{
+	Cmdtab *ct;
+	vlong limmsr;
+	ulong PstateMaxVal;
+
+	ct = lookupcmd(cb, amdpstatectlmsg, nelem(amdpstatectlmsg));
+	switch(ct->index){
+	case CMpowersave:
+		if(rdmsr(0xC0010061, &limmsr) < 0){
+			cmderror(cb, "MSRC001_0061 unsupported?!");
+			return;
+		}
+		PstateMaxVal = (limmsr >> 4) & 15;
+		print("PStateMaxVal: %uld\n", PstateMaxVal);
+
+		amdpstateset(PstateMaxVal);
+
+		return;
+	}
+
+	cmderror(cb, "bad cpufreq control message");
+}
+
+static long
+amdpstatectlwrite(Chan *c, void *a, long n, vlong off)
+{
+	Cmdbuf *cb;
+
+	if(off || n >= READSTR)
+		error(Ebadarg);
+
+	cb = parsecmd(a, n);
+	if(waserror()){
+		free(cb);
+		nexterror();
+	}
+	amdpstatectl(cb);
+	poperror();
+	free(cb);
+	return n;
+}
+
+void
+cpufreqlink(void)
+{
+	if(amdpstatecpufreqok())
+		addarchfile("cpufreqctl", 0664, nil, amdpstatectlwrite);
+}
diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -48,6 +48,7 @@
 	devpccard
 	devi82365
 	cputemp
+	cpufreq
 	apm		apmjump
 	ether2000	ether8390
 	ether2114x	pci
diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -47,6 +47,7 @@
 #	devpccard
 #	devi82365
 	cputemp
+	cpufreq
 #	ether2000	ether8390
 #	ether2114x	pci
 #	ether589	etherelnk3

[-- Attachment #4: 7517.patch --]
[-- Type: text/x-patch, Size: 691 bytes --]

# HG changeset patch
# User Robert Ransom <rransom.8774@gmail.com>
# Date 1578551612 18000
# Node ID 64f92cdc003b532a34e90fda087c7a59977058b2
# Parent  7d487cd61e9268bd7fd0d88e20f8479d6939e960
Reduce CPU power and heat early in bootrc if possible

diff -r 7d487cd61e92 -r 64f92cdc003b sys/src/9/boot/bootrc
--- a/sys/src/9/boot/bootrc	Thu Jan 09 01:28:02 2020 -0500
+++ b/sys/src/9/boot/bootrc	Thu Jan 09 01:33:32 2020 -0500
@@ -17,6 +17,10 @@
 for(i in I l^(0 1 2 3))
 	bind -qa '#'$i /net
 
+# cut CPU frequency back from maximum if possible/necessary
+if(test -e /dev/cpufreqctl)
+	echo 'powersave' >>/dev/cpufreqctl
+
 # usually better than 1970
 cat '#r/rtc' >/dev/time >[2]/dev/null
 

[-- Attachment #5: 7518.patch --]
[-- Type: text/x-patch, Size: 5417 bytes --]

# HG changeset patch
# User Robert Ransom <rransom.8774@gmail.com>
# Date 1578731009 18000
# Node ID 6fd1dc88184ef0db3b95278fc9e6fe0a987d22f3
# Parent  64f92cdc003b532a34e90fda087c7a59977058b2
Add support for setting any CPU frequency level to amdpstate driver

Not finished, but now the 'powersave' command can be undone.  Needs
to be extended to print out the frequency and other values of the
available P-states, and to check and print various other values in
the processor's PCI configuration spaces.

Reading the effective CPU frequency will take more work, including
two additional assembly routines.

diff -r 64f92cdc003b -r 6fd1dc88184e sys/src/9/pc/cpufreq.c
--- a/sys/src/9/pc/cpufreq.c	Thu Jan 09 01:33:32 2020 -0500
+++ b/sys/src/9/pc/cpufreq.c	Sat Jan 11 03:23:29 2020 -0500
@@ -6,12 +6,41 @@
 #include "io.h"
 #include "../port/error.h"
 
+/* Relevant hardware documentation for AMD "hardware P-state control":
+
+   AMD document 25481 - CPUID Specification
+     Fn0000_0006 - EffFreq bit (read effective frequency) - TODO   
+     Fn8000_0007 - HwPstate, VID, and FID bits
+
+   AMD document 31116 - AMD Family 10h BKDG
+     section 2.4.2.1.3 Core P-state Control (p. 54)
+     MSR reference MSRC001_0061 to _0063 (p. 427,428)
+     Note that MSRC001_0070 and _0071 (software low-level COF/VID control)
+       used on family 0Fh are still present; however, the processor's
+       "core performance boost" feature will clash with the older
+       mechanism unless CPB is disabled first.
+
+   AMD document 56255 - AMD Family 17h OSRR (cut-down version of BKDG)
+     confirms that this P-state mechanism is still in use;
+     specifies P-state bitfields as 3 bits wide;
+     MSRC001_0070 and _0071 are no longer documented as COF/VID control,
+       but not yet used for P-states.
+
+   AMD document 24593 Rev. 3.32 October 2019 - arch. manual vol 2 System Programming
+     specifies P-state bitfields as 4 bits wide; 
+     MSRC001_0070 and _0071 would fall within the range used by firmware
+       to provide supported P-state values to the processor.
+
+*/
+
 enum {
 	CMpowersave,
+	CMpstate,
 };
 
 static Cmdtab amdpstatectlmsg[] = {
 	CMpowersave,	"powersave",	1,
+	CMpstate,	"pstate",	2,
 };
 
 static int
@@ -26,44 +55,64 @@
 	return 0;
 }
 
-static void
+static int
 amdpstateset(ulong pst)
 {
 	vlong cmdmsr;
 	long i;
 	Mach *w;
+	int failed = 0;
 
 	w = up->wired;
 	cmdmsr = pst & 15;
 	for(i = 0; i < conf.nmach; ++i){
 		procwired(up, i);
 		sched();
-		if(wrmsr(0xC0010062, cmdmsr) < 0)
+		if(wrmsr(0xC0010062, cmdmsr) < 0){
 			print("error setting P-state %uld on mach %ld\n", pst, i);
+			failed = -1;
+		}
 	}
 	up->wired = w;
 	sched();
+
+	return failed;
 }
 
 static void
 amdpstatectl(Cmdbuf *cb)
 {
 	Cmdtab *ct;
+	char *p;
 	vlong limmsr;
-	ulong PstateMaxVal;
+	ulong pst;
 
 	ct = lookupcmd(cb, amdpstatectlmsg, nelem(amdpstatectlmsg));
 	switch(ct->index){
 	case CMpowersave:
 		if(rdmsr(0xC0010061, &limmsr) < 0){
-			cmderror(cb, "MSRC001_0061 unsupported?!");
+			cmderror(cb, "MSRC001_0061 (PState limits) unreadable");
 			return;
 		}
-		PstateMaxVal = (limmsr >> 4) & 15;
-		print("PStateMaxVal: %uld\n", PstateMaxVal);
+		pst = (limmsr >> 4) & 15;
+		print("PStateMaxVal: %uld\n", pst);
 
-		amdpstateset(PstateMaxVal);
+		if(amdpstateset(pst) < 0)
+			cmderror(cb, "error setting min-power P-state");
+		return;
+	case CMpstate:
+		p = cb->f[1];
+		if((*p == 'P') || (*p == 'p'))
+			++p;
 
+		pst = strtoul(p, &p, 10);
+		if(*p){
+			cmderror(cb, "invalid P-state format");
+			return;
+		}
+
+		if(amdpstateset(pst) < 0)
+			cmderror(cb, "error setting specified P-state");
 		return;
 	}
 
@@ -71,7 +120,65 @@
 }
 
 static long
-amdpstatectlwrite(Chan *c, void *a, long n, vlong off)
+amdpstatectlread(Chan *, void *a, long n, vlong off)
+{
+	char *p, *s, *e;
+	ulong offset = off;
+	int hwcrvalid, limmsrvalid;
+	ulong cpuidregs[4];
+	vlong hwcr, limmsr;
+	int cpuidCPB;
+	int CpbDis, PstateMaxVal, CurPstateLimit;
+
+	cpuid(0x80000007, cpuidregs);
+	hwcrvalid   = (rdmsr(0xC0010015, &hwcr)   >= 0);
+	limmsrvalid = (rdmsr(0xC0010061, &limmsr) >= 0);
+
+	cpuidCPB = ((cpuidregs[3] & (1 << 9)) != 0);
+
+	s = smalloc(READSTR);
+	if(waserror()){
+		free(s);
+		nexterror();
+	}
+	p = s; e = s+READSTR;
+	p = seprint(p, e, "type %s\n", "amdpstate");
+	p = seprint(p, e, "boostavail %s\n",
+		(cpuidCPB) ? "yes" : "no");
+	/* FIXME check bits in PCI config space too; requires ECAM */   
+
+	if(hwcrvalid){
+		CpbDis = ((ulong)hwcr & (1 << 25));
+		p = seprint(p, e, "boost %s\n",
+			CpbDis ? "disabled" : "enabled");
+	}else{
+		p = seprint(p, e, "ERROR MSRC001_0015 (HWCR) unreadable\n");
+	}
+
+	if(limmsrvalid){
+		PstateMaxVal = (limmsr >> 4) & 15;
+		CurPstateLimit = limmsr & 15;
+		p = seprint(p, e, "pstaterange %d %d\n", PstateMaxVal, CurPstateLimit);
+	}else{
+		PstateMaxVal = -1;
+		CurPstateLimit = 0;
+		p = seprint(p, e, "ERROR MSRC001_0061 (PState limits) unreadable\n");
+	}
+
+	/* TODO dump more data */   
+	USED(PstateMaxVal);
+	USED(CurPstateLimit);
+
+	USED(p);
+	n = readstr(offset, a, n, s);
+	poperror();
+	free(s);
+
+	return n;
+}
+
+static long
+amdpstatectlwrite(Chan *, void *a, long n, vlong off)
 {
 	Cmdbuf *cb;
 
@@ -93,5 +200,5 @@
 cpufreqlink(void)
 {
 	if(amdpstatecpufreqok())
-		addarchfile("cpufreqctl", 0664, nil, amdpstatectlwrite);
+		addarchfile("cpufreqctl", 0664, amdpstatectlread, amdpstatectlwrite);
 }

      reply	other threads:[~2020-01-11 21:24 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-11  3:59 Robert Ransom
2020-01-11 20:33 ` [9front] " cinap_lenrek
2020-01-11 21:24   ` Robert Ransom [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CABqy+spp1+n85_FEq50MEKb=FVc37neyujaV0pkJDq+BGgdO5Q@mail.gmail.com' \
    --to=rransom.8774@gmail.com \
    --cc=9front@9front.org \
    --cc=cinap_lenrek@felloff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).