shithub: riscv

Download patch

ref: 041ae3997c7360631c48f05de851972b5f2277ed
parent: c7fb3d697367ac99c7b922a9ad873d3aaaceab29
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Feb 23 12:19:38 EST 2025

ether8169: initialize stats counter to prevent scribbling over memory

on the RTL8168EP. when PXE booting, we would get memory corruption
from, apparently, the counters that the PXE rom had set up getting
scribbled over our kernel memory. This resets the counters early,
setting them to the expected DTCC address.

--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -61,7 +61,8 @@
 };
 
 enum {					/* Dtccr */
-	Cmd		= 0x00000008,	/* Command */
+	Reset		= 0x00000001,	/* Reset */
+	Dump		= 0x00000008,	/* Dump */
 };
 
 enum {					/* Cr */
@@ -425,7 +426,7 @@
 		csr8w(ctlr, Ldps, 1);				/* magic */
 		rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000);	/* magic */
 	}
-	
+
 	if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
 		error("no phy");
 	}
@@ -524,6 +525,7 @@
 rtl8169ifstat(void *arg, char *p, char *e)
 {
 	Ether *edev = arg;
+	u64int pa;
 	Ctlr *ctlr;
 	Dtcc *dtcc;
 	int i, r, timeo;
@@ -535,14 +537,15 @@
 		nexterror();
 	}
 
-	csr32w(ctlr, Dtccr+4, 0);
-	csr32w(ctlr, Dtccr, PCIWADDR(ctlr->dtcc)|Cmd);
+	pa = PCIWADDR(ctlr->dtcc)|Dump;
+	csr32w(ctlr, Dtccr+4, pa >> 32);
+	csr32w(ctlr, Dtccr, pa);
 	for(timeo = 0; timeo < 1000; timeo++){
-		if(!(csr32r(ctlr, Dtccr) & Cmd))
+		if(!(csr32r(ctlr, Dtccr) & (Reset|Dump)))
 			break;
 		delay(1);
 	}
-	if(csr32r(ctlr, Dtccr) & Cmd)
+	if(csr32r(ctlr, Dtccr) & (Reset|Dump))
 		error(Eio);
 	dtcc = ctlr->dtcc;
 
@@ -667,7 +670,7 @@
 static void
 rtl8169init(Ether* edev)
 {
-	int i;
+	int i, timeo;
 	u32int r;
 	Block *bp;
 	Ctlr *ctlr;
@@ -728,6 +731,19 @@
 	pa = PCIWADDR(ctlr->rd);
 	csr32w(ctlr, Rdsar+4, pa>>32);
 	csr32w(ctlr, Rdsar, pa);
+
+	pa = PCIWADDR(ctlr->dtcc)|Reset;
+	csr32w(ctlr, Dtccr+4, pa >> 32);
+	csr32w(ctlr, Dtccr, pa);
+	for(timeo = 0; timeo < 1000; timeo++){
+		if(!(csr32r(ctlr, Dtccr) & (Reset|Dump)))
+			break;
+		delay(1);
+	}
+	if(csr32r(ctlr, Dtccr) & (Reset|Dump)){
+		iunlock(ctlr);
+		error("reset failed");
+	}
 
 	/* pre-RTL8168G controllers need TX/RX before configuration */
 	switch(ctlr->macv){
--