Page MenuHomeFreeBSD

D52709.id.diff
No OneTemporary

D52709.id.diff

diff --git a/sys/x86/include/mca.h b/sys/x86/include/mca.h
--- a/sys/x86/include/mca.h
+++ b/sys/x86/include/mca.h
@@ -44,6 +44,31 @@
int mr_cpu;
};
+enum mca_stat_types {
+ MCA_T_NONE = 0,
+ MCA_T_UNCLASSIFIED,
+ MCA_T_UCODE_ROM_PARITY,
+ MCA_T_EXTERNAL,
+ MCA_T_FRC,
+ MCA_T_INTERNAL_PARITY,
+ MCA_T_SMM_HANDLER,
+ MCA_T_INTERNAL_TIMER,
+ MCA_T_GENERIC_IO,
+ MCA_T_INTERNAL,
+ MCA_T_MEMORY,
+ MCA_T_TLB,
+ MCA_T_MEMCONTROLLER_GEN,
+ MCA_T_MEMCONTROLLER_RD,
+ MCA_T_MEMCONTROLLER_WR,
+ MCA_T_MEMCONTROLLER_AC,
+ MCA_T_MEMCONTROLLER_MS,
+ MCA_T_MEMCONTROLLER_OTHER,
+ MCA_T_CACHE,
+ MCA_T_BUS,
+ MCA_T_UNKNOWN,
+ MCA_T_COUNT /* Must stay last */
+};
+
#ifdef _KERNEL
void cmc_intr(void);
diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c
--- a/sys/x86/x86/mca.c
+++ b/sys/x86/x86/mca.c
@@ -134,6 +134,12 @@
static struct timeout_task mca_scan_task;
static struct mtx mca_lock;
+/* Statistics on number of MCA events by type, updated atomically. */
+static uint64_t mca_stats[MCA_T_COUNT];
+SYSCTL_OPAQUE(_hw_mca, OID_AUTO, stats, CTLFLAG_RD | CTLFLAG_SKIP,
+ mca_stats, MCA_T_COUNT * sizeof(mca_stats[0]),
+ "S", "Array of MCA events by type");
+
static unsigned int
mca_ia32_ctl_reg(int bank)
{
@@ -356,21 +362,27 @@
}
static const char *
-mca_error_mmtype(uint16_t mca_error)
+mca_error_mmtype(uint16_t mca_error, enum mca_stat_types *event_type)
{
switch ((mca_error & 0x70) >> 4) {
case 0x0:
+ *event_type = MCA_T_MEMCONTROLLER_GEN;
return ("GEN");
case 0x1:
+ *event_type = MCA_T_MEMCONTROLLER_RD;
return ("RD");
case 0x2:
+ *event_type = MCA_T_MEMCONTROLLER_WR;
return ("WR");
case 0x3:
+ *event_type = MCA_T_MEMCONTROLLER_AC;
return ("AC");
case 0x4:
+ *event_type = MCA_T_MEMCONTROLLER_MS;
return ("MS");
}
+ *event_type = MCA_T_MEMCONTROLLER_OTHER;
return ("???");
}
@@ -426,6 +438,7 @@
mca_log(const struct mca_record *rec)
{
uint16_t mca_error;
+ enum mca_stat_types event_type;
if (mca_mute(rec))
return;
@@ -473,34 +486,44 @@
if (rec->mr_status & MC_STATUS_OVER)
printf("OVER ");
mca_error = rec->mr_status & MC_STATUS_MCA_ERROR;
+ event_type = MCA_T_COUNT;
switch (mca_error) {
/* Simple error codes. */
case 0x0000:
printf("no error");
+ event_type = MCA_T_NONE;
break;
case 0x0001:
printf("unclassified error");
+ event_type = MCA_T_UNCLASSIFIED;
break;
case 0x0002:
printf("ucode ROM parity error");
+ event_type = MCA_T_UCODE_ROM_PARITY;
break;
case 0x0003:
printf("external error");
+ event_type = MCA_T_EXTERNAL;
break;
case 0x0004:
printf("FRC error");
+ event_type = MCA_T_FRC;
break;
case 0x0005:
printf("internal parity error");
+ event_type = MCA_T_INTERNAL_PARITY;
break;
case 0x0006:
printf("SMM handler code access violation");
+ event_type = MCA_T_SMM_HANDLER;
break;
case 0x0400:
printf("internal timer error");
+ event_type = MCA_T_INTERNAL_TIMER;
break;
case 0x0e0b:
printf("generic I/O error");
+ event_type = MCA_T_GENERIC_IO;
if (rec->mr_cpu_vendor_id == CPU_VENDOR_INTEL &&
(rec->mr_status & MC_STATUS_MISCV)) {
printf(" (pci%d:%d:%d:%d)",
@@ -513,6 +536,7 @@
default:
if ((mca_error & 0xfc00) == 0x0400) {
printf("internal error %x", mca_error & 0x03ff);
+ event_type = MCA_T_INTERNAL;
break;
}
@@ -521,6 +545,7 @@
/* Memory hierarchy error. */
if ((mca_error & 0xeffc) == 0x000c) {
printf("%s memory error", mca_error_level(mca_error));
+ event_type = MCA_T_MEMORY;
break;
}
@@ -528,12 +553,14 @@
if ((mca_error & 0xeff0) == 0x0010) {
printf("%sTLB %s error", mca_error_ttype(mca_error),
mca_error_level(mca_error));
+ event_type = MCA_T_TLB;
break;
}
/* Memory controller error. */
if ((mca_error & 0xef80) == 0x0080) {
- printf("%s channel ", mca_error_mmtype(mca_error));
+ printf("%s channel ", mca_error_mmtype(mca_error,
+ &event_type));
if ((mca_error & 0x000f) != 0x000f)
printf("%d", mca_error & 0x000f);
else
@@ -548,12 +575,14 @@
mca_error_ttype(mca_error),
mca_error_level(mca_error),
mca_error_request(mca_error));
+ event_type = MCA_T_CACHE;
break;
}
/* Extended memory error. */
if ((mca_error & 0xef80) == 0x0280) {
- printf("%s channel ", mca_error_mmtype(mca_error));
+ printf("%s channel ", mca_error_mmtype(mca_error,
+ &event_type));
if ((mca_error & 0x000f) != 0x000f)
printf("%d", mca_error & 0x000f);
else
@@ -565,6 +594,7 @@
/* Bus and/or Interconnect error. */
if ((mca_error & 0xe800) == 0x0800) {
printf("BUS%s ", mca_error_level(mca_error));
+ event_type = MCA_T_BUS;
switch ((mca_error & 0x0600) >> 9) {
case 0:
printf("Source");
@@ -600,6 +630,7 @@
}
printf("unknown error %x", mca_error);
+ event_type = MCA_T_UNKNOWN;
break;
}
printf("\n");
@@ -615,6 +646,12 @@
}
if (rec->mr_status & MC_STATUS_MISCV)
printf("MCA: Misc 0x%llx\n", (long long)rec->mr_misc);
+ if (event_type < 0 || event_type >= MCA_T_COUNT) {
+ KASSERT(0, ("%s: invalid event type (%d)", __func__,
+ event_type));
+ event_type = MCA_T_UNKNOWN;
+ }
+ atomic_add_64(&mca_stats[event_type], 1);
}
static bool

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 31, 7:39 AM (8 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24509204
Default Alt Text
D52709.id.diff (5 KB)

Event Timeline