shithub: riscv

Download patch

ref: 3a6a754051a6f3f1ba742f12be0a2c33d309ca53
parent: 3fe38f70014256cdd1d3b1b42f7b8760e6e80778
author: cinap_lenrek <[email protected]>
date: Wed Jul 9 18:45:51 EDT 2014

pc, pc64: initial machine check architecture support

--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -321,6 +321,7 @@
 	Cpuapic	= 1<<9,
 	Mtrr	= 1<<12,	/* memory-type range regs.  */
 	Pge	= 1<<13,	/* page global extension */
+	Mca	= 1<<14,	/* machine-check architecture */
 	Pse2	= 1<<17,	/* more page size extensions */
 	Clflush = 1<<19,
 	Acpif	= 1<<22,	/* therm control msr */
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -824,12 +824,37 @@
 			nomce = strtoul(p, 0, 0);
 		else
 			nomce = 0;
-		if((m->cpuiddx & Mce) && !nomce){
-			cr4 |= 0x40;		/* machine check enable */
-			if(family == 5){
+		if((m->cpuiddx & Mce) != 0 && !nomce){
+			if((m->cpuiddx & Mca) != 0){
+				vlong cap;
+				int bank;
+
+				cap = 0;
+				rdmsr(0x179, &cap);
+
+				if(cap & 0x100)
+					wrmsr(0x17B, ~0ULL);	/* enable all mca features */
+
+				bank = cap & 0xFF;
+				if(bank > 64)
+					bank = 64;
+
+				/* init MCi .. MC1 (except MC0) */
+				while(--bank > 0){
+					wrmsr(0x400 + bank*4, ~0ULL);
+					wrmsr(0x401 + bank*4, 0);
+				}
+
+				if(family != 6 || model >= 0x1A)
+					wrmsr(0x400, ~0ULL);
+
+				wrmsr(0x401, 0);
+			}
+			else if(family == 5){
 				rdmsr(0x00, &mca);
 				rdmsr(0x01, &mct);
 			}
+			cr4 |= 0x40;		/* machine check enable */
 		}
 
 		/*
@@ -854,7 +879,7 @@
 
 		putcr4(cr4);
 
-		if(m->cpuiddx & Mce)
+		if((m->cpuiddx & (Mca|Mce)) == Mce)
 			rdmsr(0x01, &mct);
 	}
 
@@ -1194,4 +1219,42 @@
 			isa->freq = strtoul(p+5, &p, 0);
 	}
 	return 1;
+}
+
+void
+dumpmcregs(void)
+{
+	vlong v, w;
+	int bank;
+
+	if((m->cpuiddx & (Mce|Cpumsr)) != (Mce|Cpumsr))
+		return;
+	if((m->cpuiddx & Mca) == 0){
+		rdmsr(0x00, &v);
+		rdmsr(0x01, &w);
+		iprint("MCA %8.8llux MCT %8.8llux\n", v, w);
+		return;
+	}
+	rdmsr(0x179, &v);
+	rdmsr(0x17A, &w);
+	iprint("MCG CAP %.16llux STATUS %.16llux\n", v, w);
+
+	bank = v & 0xFF;
+	if(bank > 64)
+		bank = 64;
+	while(--bank >= 0){
+		rdmsr(0x401 + bank*4, &v);
+		if((v & (1ull << 63)) == 0)
+			continue;
+		iprint("MC%d STATUS %.16llux", bank, v);
+		if(v & (1ull << 58)){
+			rdmsr(0x402 + bank*4, &w);
+			iprint(" ADDR %.16llux", w);
+		}
+		if(v & (1ull << 59)){
+			rdmsr(0x403 + bank*4, &w);
+			iprint(" MISC %.16llux", w);
+		}
+		iprint("\n");
+	}
 }
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -28,6 +28,7 @@
 #define DMAREAD 1
 #define DMALOOP 2
 long	dmasetup(int, void*, long, int);
+void	dumpmcregs(void);
 #define	evenaddr(x)				/* x86 doesn't care */
 void	fpclear(void);
 void	fpenv(FPsave*);
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -528,8 +528,6 @@
 void
 dumpregs(Ureg* ureg)
 {
-	vlong mca, mct;
-
 	dumpregs2(ureg);
 
 	/*
@@ -542,12 +540,9 @@
 	iprint("  CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux",
 		getcr0(), getcr2(), getcr3());
 	if(m->cpuiddx & (Mce|Tsc|Pse|Vmex)){
-		iprint(" CR4 %8.8lux", getcr4());
-		if((m->cpuiddx & (Mce|Cpumsr)) == (Mce|Cpumsr)){
-			rdmsr(0x00, &mca);
-			rdmsr(0x01, &mct);
-			iprint("\n  MCA %8.8llux MCT %8.8llux", mca, mct);
-		}
+		iprint(" CR4 %8.8lux\n", getcr4());
+		if(ureg->trap == 18)
+			dumpmcregs();
 	}
 	iprint("\n  ur %#p up %#p\n", ureg, up);
 }
--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -286,6 +286,7 @@
 	Cpuapic	= 1<<9,
 	Mtrr	= 1<<12,	/* memory-type range regs.  */
 	Pge	= 1<<13,	/* page global extension */
+	Mca	= 1<<14,	/* machine-check architecture */
 	Pse2	= 1<<17,	/* more page size extensions */
 	Clflush = 1<<19,
 	Acpif	= 1<<22,	/* therm control msr */
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -28,6 +28,7 @@
 #define DMAREAD 1
 #define DMALOOP 2
 long	dmasetup(int, void*, long, int);
+void	dumpmcregs(void);
 #define	evenaddr(x)				/* x86 doesn't care */
 void	(*fprestore)(FPsave*);
 void	(*fpsave)(FPsave*);
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -503,14 +503,9 @@
 	iprint(" CR0 %8.8llux CR2 %16.16llux CR3 %16.16llux",
 		getcr0(), getcr2(), getcr3());
 	if(m->cpuiddx & (Mce|Tsc|Pse|Vmex)){
-		iprint(" CR4 %16.16llux", getcr4());
-		if((m->cpuiddx & (Mce|Cpumsr)) == (Mce|Cpumsr)){
-			vlong mca, mct;
-
-			rdmsr(0x00, &mca);
-			rdmsr(0x01, &mct);
-			iprint("\n MCA %8.8llux MCT %8.8llux", mca, mct);
-		}
+		iprint(" CR4 %16.16llux\n", getcr4());
+		if(ureg->type == 18)
+			dumpmcregs();
 	}
 	iprint("\n  ur %#p up %#p\n", ureg, up);
 }