shithub: riscv

Download patch

ref: ced2a9bc7cc247be72bd6915c9a01a7d2d2710a5
parent: e10e93451a5c77dbd68748ebda4752956ba6357d
author: Jacob Moody <moody@posixcafe.org>
date: Sat Mar 1 20:21:26 EST 2025

pc: more cputemp support for AMD and cleanup

Instead of walking the PCI devices at read time,
and having a failure mode where we return invalid
output, instead just search the PCI devices as
part of initialization. Our existing functions could
be used for a larger set of families. Some motherboard/chip
combinations have multiple PCI devices so we should walk
all of them in all handlers. Some slight refactor along
the way.

--- a/sys/src/9/pc/cputemp.c
+++ b/sys/src/9/pc/cputemp.c
@@ -91,34 +91,50 @@
 	return t;
 }
 
+/*
+ * AMD exposes some sensors via PCI config space
+ * on various devices depending on the CPU family.
+ * This is largely undocumented, and has variance
+ * depending on the motherboard vendor used.
+ * Consumer grade often only has one sensor
+ * per chip, however server grade can have up
+ * to one sensor per core exposed this way.
+ */
+static Pcidev 	*amddevs[MAXMACH];
+static int	namddevs;
+
 static long
 amd0ftemprd(Chan*, void *a, long n, vlong offset)
 {
-	char *s, *e, buf[64];
-	long i, t, j, max;
-	Pcidev *p;
+	static Lock lk;
+	int i;
+	char *s, *e, buf[16*4];
+	long v, t, j, max;
 
-	p = pcimatch(0, 0x1022, 0x1103);
-	if(p == nil)
-		return readstr(offset, a, n, "-1±-1 unsupported\n");
+	/* one sensor per core */
 	max = 2;
-	if(max > conf.nmach)
-		max = conf.nmach;
+	if(conf.nmach == 1)
+		max = 1;
+	else if(amddevs[1] != nil && conf.nmach == 2)
+		max = 1;
 	s = buf;
 	e = buf + sizeof buf;
+	lock(&lk);
+	for(i = 0; i < namddevs; i++)
 	for(j = 0; j < max; j++){
-		pcicfgw32(p, 0xe4, pcicfgr32(p, 0xe4) & ~4 | j<<2);
-		i = pcicfgr32(p, 0xe4);
+		pcicfgw32(amddevs[i], 0xe4, pcicfgr32(amddevs[i], 0xe4) & ~4 | j<<2);
+		v = pcicfgr32(amddevs[i], 0xe4);
 		if(m->cpuidstepping == 2)
-			t = i>>16 & 0xff;
+			t = v>>16 & 0xff;
 		else{
-			t = i>>14 & 0x3ff;
+			t = v>>14 & 0x3ff;
 			t *= 3;
 			t /= 4;
 		}
 		t += -49;
-		s = seprint(s, e, "%ld±%uld%s\n", t, 1l, "");
+		s = seprint(s, e, "%ld±1\n", t);
 	}
+	unlock(&lk);
 	return readstr(offset, a, n, buf);
 }
 
@@ -125,72 +141,60 @@
 static long
 amd10temprd(Chan*, void *a, long n, vlong offset)
 {
-	char *s, *e, *r, *buf;
-	long i, t, c, nb, cores[MAXMACH];
-	Pcidev *p;
+	int i;
+	char *s, *e, buf[16*nelem(amddevs)];
+	u32int v;
 
-	nb = 0;
-	for(p = 0; p = pcimatch(p, 0x1022, 0x1203); ){
-		cores[nb++] = 1 + ((pcicfgr32(p, 0xe8) & 0x3000)>>12);
-		if(nb == nelem(cores))
-			break;
-	}
-	if(nb == 0)
-		return readstr(offset, a, n, "-1±-1 unsupported\n");
-	buf = smalloc(MAXMACH*4*32);
 	s = buf;
-	e = buf + MAXMACH*4*32;
-	nb = 0;
-	c = 0;
-	for(p = 0; p = pcimatch(p, 0x1022, 0x1203); nb++){
-		i = pcicfgr32(p, 0xa4) & 0x7fffffff;
-		i >>= 21;
-		t = i/8;
-		r = ".0";
-		if(i % 8 >= 4)
-			r = ".5";
-		/*
-		 * only one value per nb; repeat per core
-		 */
-		while(c++ < conf.nmach && cores[nb]--)
-			s = seprint(s, e, "%ld%s±0.5%s\n", t, r, "");
+	e = buf + sizeof buf;
+	for(i = 0; i < namddevs; i++){
+		v = pcicfgr32(amddevs[i], 0xa4);
+		v = ((v>>21)+4) / 8;
+		s = seprint(s, e, "%ud±1\n", v);
 	}
-	i = readstr(offset, a, n, buf);
-	free(buf);
-	return i;
+	return readstr(offset, a, n, buf);
 }
 
-static Pcidev*
-finddev(void)
+static int
+finddevs(void)
 {
 	Pcidev *p;
 
 	for(p = nil; p = pcimatch(p, 0x1022, 0); )
 		switch(p->did){
-		case 0x1480:
+		case 0x1103:	/* 0f */
+		case 0x1203:	/* 10 */
+		case 0x1303:	/* 11 */
+		case 0x1703:	/* 14 */
+		case 0x1603:	/* 15 */
+		case 0x1403:
+		case 0x141d:
+		case 0x1533:	/* 16 */
+		case 0x1583:
+		case 0x1480:	/* 17 */
 		case 0x1450:
 		case 0x15d0:
 		case 0x1630:
-		case 0x14a4:
+		case 0x14a4:	/* 19 */
 		case 0x14b5:
 		case 0x14d8:
 		case 0x14eb:
-			return p;
+			amddevs[namddevs++] = p;
+			if(namddevs == nelem(amddevs))
+				return namddevs;
 		}
-	return nil;
+	return namddevs;
 }
 
-static Pcidev *snmdev;
-
 static u32int
-snmread(ulong addr)
+snmread(Pcidev *p, ulong addr)
 {
 	static Lock lk;
 	u32int v;
 
 	lock(&lk);
-	pcicfgw32(snmdev, 0x60, addr);
-	v = pcicfgr32(snmdev, 0x64);
+	pcicfgw32(p, 0x60, addr);
+	v = pcicfgr32(p, 0x64);
 	unlock(&lk);
 	return v;
 }
@@ -198,13 +202,20 @@
 static long
 amd17temprd(Chan*, void *a, long n, vlong offset)
 {
-	u32int i;
-	char buf[16];
+	int i;
+	char *s, *e, buf[16*nelem(amddevs)];
+	u32int v, r;
+	enum { Range = 1u<<19, Tjsel = 1u<<17 };
 
-	i = snmread(0x59800);
-	i >>= 21;
-	i = (i+4)/8;
-	snprint(buf, sizeof buf, "%ud±1\n", i);
+	s = buf;
+	e = buf + sizeof buf;
+	for(i = 0; i < namddevs; i++){
+		r = snmread(amddevs[i], 0x59800);
+		v = ((r >> 21)+4) / 8;
+		if(r & (Range|Tjsel))
+			v -= 49;
+		s = seprint(s, e, "%ud±1\n", v);
+	}
 	return readstr(offset, a, n, buf);
 }
 
@@ -216,20 +227,27 @@
 	if(intelcputempok())
 		return intelcputemprd;
 
-	if(strcmp(m->cpuidid,  "AuthenticAMD") == 0)
+	if(strcmp(m->cpuidid,  "AuthenticAMD") == 0){
+		if(finddevs() == 0)
+			return nil;
 		switch(m->cpuidfamily){
 		case 0x0f:
 			return amd0ftemprd;
 		case 0x10:
+		case 0x11:
+		case 0x12:
+		case 0x14:
+		case 0x15:
+		case 0x16:
 			return amd10temprd;
 		case 0x17:
-			snmdev = finddev();
-			if(snmdev == nil)
-				return nil;
+		case 0x19:
+		case 0x1a:
 			return amd17temprd;
 		default:
 			return nil;
 		}
+	}
 
 	return nil;
 }
@@ -237,7 +255,7 @@
 void
 cputemplink(void)
 {
-	Rdwrfn* fn;
+	Rdwrfn *fn;
 
 	if((fn = probe()) != nil)
 		addarchfile("cputemp", 0444, fn, nil);
--