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);
}