Page MenuHomeFreeBSD

D12275.id32803.diff
No OneTemporary

D12275.id32803.diff

Index: FreeBSD/sys/x86/x86/mca.c
===================================================================
--- FreeBSD/sys/x86/x86/mca.c
+++ FreeBSD/sys/x86/x86/mca.c
@@ -116,10 +116,11 @@
static STAILQ_HEAD(, mca_internal) mca_freelist;
static int mca_freecount;
static STAILQ_HEAD(, mca_internal) mca_records;
+static struct mca_internal *mca_lastrec = NULL;
static struct callout mca_timer;
static int mca_ticks = 3600; /* Check hourly by default. */
static struct taskqueue *mca_tq;
-static struct task mca_refill_task, mca_scan_task;
+static struct task mca_postscan_task, mca_scan_task;
static struct mtx mca_lock;
#ifdef DEV_APIC
@@ -491,10 +492,40 @@
}
static void
-mca_refill(void *context, int pending)
+mca_emit_logs(void)
+{
+ struct mca_internal *mca;
+
+ mtx_lock_spin(&mca_lock);
+ if (mca_lastrec == NULL)
+ mca = STAILQ_FIRST(&mca_records);
+ else
+ mca = STAILQ_NEXT(mca_lastrec, link);
+ if (mca != NULL) {
+ STAILQ_FOREACH_FROM(mca, &mca_records, link) {
+ if (!mca->logged) {
+ mca->logged = 1;
+ mca_log(&mca->rec);
+ }
+ mca_lastrec = mca;
+ }
+ mca_lastrec = STAILQ_LAST(&mca_records, mca_internal, link);
+ }
+ mtx_unlock_spin(&mca_lock);
+}
+
+/*
+ * Refill the free list and log any unlogged messages. This is
+ * intended to be called from a task queue and to handle work which
+ * does not need to be done (or cannot be done) in the hardware
+ * interrupt context.
+ */
+static void
+mca_postscan(void *context __unused, int pending __unused)
{
mca_fill_freelist();
+ mca_emit_logs();
}
static void
@@ -523,8 +554,6 @@
STAILQ_INSERT_TAIL(&mca_records, rec, link);
mca_count++;
mtx_unlock_spin(&mca_lock);
- if (mode == CMCI && !cold)
- taskqueue_enqueue(mca_tq, &mca_refill_task);
}
#ifdef DEV_APIC
@@ -717,7 +746,6 @@
static void
mca_scan_cpus(void *context, int pending)
{
- struct mca_internal *mca;
struct thread *td;
int count, cpu;
@@ -733,16 +761,8 @@
sched_unbind(td);
}
thread_unlock(td);
- if (count != 0) {
- mtx_lock_spin(&mca_lock);
- STAILQ_FOREACH(mca, &mca_records, link) {
- if (!mca->logged) {
- mca->logged = 1;
- mca_log(&mca->rec);
- }
- }
- mtx_unlock_spin(&mca_lock);
- }
+ if (count != 0)
+ mca_emit_logs();
}
static void
@@ -786,6 +806,9 @@
mca_startup(void *dummy)
{
+ /* Handle any events that might have been logged during startup. */
+ mca_postscan(NULL, 0);
+
if (mca_banks <= 0)
return;
@@ -846,7 +869,7 @@
TASK_INIT(&mca_scan_task, 0, mca_scan_cpus, NULL);
callout_init(&mca_timer, 1);
STAILQ_INIT(&mca_freelist);
- TASK_INIT(&mca_refill_task, 0, mca_refill, NULL);
+ TASK_INIT(&mca_postscan_task, 0, mca_postscan, NULL);
mca_fill_freelist();
SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca), OID_AUTO,
"count", CTLFLAG_RD, (int *)(uintptr_t)&mca_count, 0,
@@ -1183,6 +1206,10 @@
panic("Unrecoverable machine check exception");
}
+ /* Schedule post-processing to log the message(s). */
+ if (!cold)
+ taskqueue_enqueue(mca_tq, &mca_postscan_task);
+
/* Clear MCIP. */
wrmsr(MSR_MCG_STATUS, mcg_status & ~MCG_STATUS_MCIP);
}
@@ -1192,7 +1219,6 @@
void
cmc_intr(void)
{
- struct mca_internal *mca;
int count;
/*
@@ -1201,16 +1227,8 @@
*/
count = mca_scan(CMCI, NULL);
- /* If we found anything, log them to the console. */
- if (count != 0) {
- mtx_lock_spin(&mca_lock);
- STAILQ_FOREACH(mca, &mca_records, link) {
- if (!mca->logged) {
- mca->logged = 1;
- mca_log(&mca->rec);
- }
- }
- mtx_unlock_spin(&mca_lock);
- }
+ /* If we found anything, do post-processing. */
+ if (count > 0 && !cold)
+ taskqueue_enqueue(mca_tq, &mca_postscan_task);
}
#endif

File Metadata

Mime Type
text/plain
Expires
Sun, Jul 26, 7:07 PM (22 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35557637
Default Alt Text
D12275.id32803.diff (3 KB)

Event Timeline