diff options
| author | Jonathan T. Looney <jtl@FreeBSD.org> | 2025-10-03 16:23:07 +0000 |
|---|---|---|
| committer | Jonathan T. Looney <jtl@FreeBSD.org> | 2025-10-06 15:59:31 +0000 |
| commit | 4a5d8670a7d58b04913fd90aae85a1e35236ca3d (patch) | |
| tree | 4fdeac9af099d004ba981166fe9e75d5f4bc8e82 | |
| parent | a0c709ab5af4e87ce4579404c4ffbd4295ad12c5 (diff) | |
x86: Close race condition on MCA task queues at startup
Currently, the CMCI handler checks the cold variable to determine
whether it can schedule a task. The task queue is setup as part of the
mca_startup() function, which is run well after the configure_final()
function sets the cold variable to 0. Therefore, if an MCA arrives
in the window between configure_final() and mca_startup() running,
the code could try to schedule a task on an unintitalized task queue.
Close the race by specifically checking whether the mca_startup()
function has run.
Reviewed by: markj
MFC after: 1 week
Sponsored by: Netflix
Differential Revision: https://reviews.freebsd.org/D12276
| -rw-r--r-- | sys/x86/x86/mca.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/x86/x86/mca.c b/sys/x86/x86/mca.c index 1851df8d00a0..933d10e52187 100644 --- a/sys/x86/x86/mca.c +++ b/sys/x86/x86/mca.c @@ -133,6 +133,7 @@ static struct taskqueue *mca_tq; static struct task mca_resize_task; static struct timeout_task mca_scan_task; static struct mtx mca_lock; +static bool mca_startup_done = false; /* Statistics on number of MCA events by type, updated atomically. */ static uint64_t mca_stats[MCA_T_COUNT]; @@ -1025,7 +1026,7 @@ mca_process_records(enum scan_mode mode) mtx_unlock_spin(&mca_lock); if (mode == POLLED) mca_resize_freelist(); - else if (!cold) + else if (mca_startup_done) taskqueue_enqueue(mca_tq, &mca_resize_task); } @@ -1097,7 +1098,7 @@ sysctl_mca_maxcount(SYSCTL_HANDLER_ARGS) doresize = true; } mtx_unlock_spin(&mca_lock); - if (doresize && !cold) + if (doresize && mca_startup_done) taskqueue_enqueue(mca_tq, &mca_resize_task); return (error); } @@ -1115,6 +1116,7 @@ mca_startup(void *dummy) taskqueue_start_threads(&mca_tq, 1, PI_SWI(SWI_TQ), "mca taskq"); taskqueue_enqueue_timeout_sbt(mca_tq, &mca_scan_task, mca_ticks * SBT_1S, 0, C_PREL(1)); + mca_startup_done = true; } SYSINIT(mca_startup, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, mca_startup, NULL); |
