···30733073 and gids from such clients. This is intended to ease30743074 migration from NFSv2/v3.3075307530763076+ nmi_backtrace.backtrace_idle [KNL]30773077+ Dump stacks even of idle CPUs in response to an30783078+ NMI stack-backtrace request.30793079+30763080 nmi_debug= [KNL,SH] Specify one or more actions to take30773081 when a NMI is triggered.30783082 Format: [state][,regs][,debounce][,die]
···2020#include <linux/sched.h>2121#include <linux/sched/idle.h>2222#include <linux/hypervisor.h>2323+#include <linux/sched/clock.h>2424+#include <linux/nmi.h>2525+#include <linux/sched/debug.h>23262427#include "smpboot.h"2528#include "sched/smp.h"···9996 smpcfd_prepare_cpu(smp_processor_id());10097}101989999+#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG100100+101101+static DEFINE_PER_CPU(call_single_data_t *, cur_csd);102102+static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func);103103+static DEFINE_PER_CPU(void *, cur_csd_info);104104+105105+#define CSD_LOCK_TIMEOUT (5ULL * NSEC_PER_SEC)106106+static atomic_t csd_bug_count = ATOMIC_INIT(0);107107+108108+/* Record current CSD work for current CPU, NULL to erase. */109109+static void csd_lock_record(call_single_data_t *csd)110110+{111111+ if (!csd) {112112+ smp_mb(); /* NULL cur_csd after unlock. */113113+ __this_cpu_write(cur_csd, NULL);114114+ return;115115+ }116116+ __this_cpu_write(cur_csd_func, csd->func);117117+ __this_cpu_write(cur_csd_info, csd->info);118118+ smp_wmb(); /* func and info before csd. */119119+ __this_cpu_write(cur_csd, csd);120120+ smp_mb(); /* Update cur_csd before function call. */121121+ /* Or before unlock, as the case may be. */122122+}123123+124124+static __always_inline int csd_lock_wait_getcpu(call_single_data_t *csd)125125+{126126+ unsigned int csd_type;127127+128128+ csd_type = CSD_TYPE(csd);129129+ if (csd_type == CSD_TYPE_ASYNC || csd_type == CSD_TYPE_SYNC)130130+ return csd->dst; /* Other CSD_TYPE_ values might not have ->dst. */131131+ return -1;132132+}133133+134134+/*135135+ * Complain if too much time spent waiting. Note that only136136+ * the CSD_TYPE_SYNC/ASYNC types provide the destination CPU,137137+ * so waiting on other types gets much less information.138138+ */139139+static __always_inline bool csd_lock_wait_toolong(call_single_data_t *csd, u64 ts0, u64 *ts1, int *bug_id)140140+{141141+ int cpu = -1;142142+ int cpux;143143+ bool firsttime;144144+ u64 ts2, ts_delta;145145+ call_single_data_t *cpu_cur_csd;146146+ unsigned int flags = READ_ONCE(csd->flags);147147+148148+ if (!(flags & CSD_FLAG_LOCK)) {149149+ if (!unlikely(*bug_id))150150+ return true;151151+ cpu = csd_lock_wait_getcpu(csd);152152+ pr_alert("csd: CSD lock (#%d) got unstuck on CPU#%02d, CPU#%02d released the lock.\n",153153+ *bug_id, raw_smp_processor_id(), cpu);154154+ return true;155155+ }156156+157157+ ts2 = sched_clock();158158+ ts_delta = ts2 - *ts1;159159+ if (likely(ts_delta <= CSD_LOCK_TIMEOUT))160160+ return false;161161+162162+ firsttime = !*bug_id;163163+ if (firsttime)164164+ *bug_id = atomic_inc_return(&csd_bug_count);165165+ cpu = csd_lock_wait_getcpu(csd);166166+ if (WARN_ONCE(cpu < 0 || cpu >= nr_cpu_ids, "%s: cpu = %d\n", __func__, cpu))167167+ cpux = 0;168168+ else169169+ cpux = cpu;170170+ cpu_cur_csd = smp_load_acquire(&per_cpu(cur_csd, cpux)); /* Before func and info. */171171+ pr_alert("csd: %s non-responsive CSD lock (#%d) on CPU#%d, waiting %llu ns for CPU#%02d %pS(%ps).\n",172172+ firsttime ? "Detected" : "Continued", *bug_id, raw_smp_processor_id(), ts2 - ts0,173173+ cpu, csd->func, csd->info);174174+ if (cpu_cur_csd && csd != cpu_cur_csd) {175175+ pr_alert("\tcsd: CSD lock (#%d) handling prior %pS(%ps) request.\n",176176+ *bug_id, READ_ONCE(per_cpu(cur_csd_func, cpux)),177177+ READ_ONCE(per_cpu(cur_csd_info, cpux)));178178+ } else {179179+ pr_alert("\tcsd: CSD lock (#%d) %s.\n",180180+ *bug_id, !cpu_cur_csd ? "unresponsive" : "handling this request");181181+ }182182+ if (cpu >= 0) {183183+ if (!trigger_single_cpu_backtrace(cpu))184184+ dump_cpu_task(cpu);185185+ if (!cpu_cur_csd) {186186+ pr_alert("csd: Re-sending CSD lock (#%d) IPI from CPU#%02d to CPU#%02d\n", *bug_id, raw_smp_processor_id(), cpu);187187+ arch_send_call_function_single_ipi(cpu);188188+ }189189+ }190190+ dump_stack();191191+ *ts1 = ts2;192192+193193+ return false;194194+}195195+102196/*103197 * csd_lock/csd_unlock used to serialize access to per-cpu csd resources104198 *···205105 */206106static __always_inline void csd_lock_wait(call_single_data_t *csd)207107{108108+ int bug_id = 0;109109+ u64 ts0, ts1;110110+111111+ ts1 = ts0 = sched_clock();112112+ for (;;) {113113+ if (csd_lock_wait_toolong(csd, ts0, &ts1, &bug_id))114114+ break;115115+ cpu_relax();116116+ }117117+ smp_acquire__after_ctrl_dep();118118+}119119+120120+#else121121+static void csd_lock_record(call_single_data_t *csd)122122+{123123+}124124+125125+static __always_inline void csd_lock_wait(call_single_data_t *csd)126126+{208127 smp_cond_load_acquire(&csd->flags, !(VAL & CSD_FLAG_LOCK));209128}129129+#endif210130211131static __always_inline void csd_lock(call_single_data_t *csd)212132{···286166 * We can unlock early even for the synchronous on-stack case,287167 * since we're doing this from the same CPU..288168 */169169+ csd_lock_record(csd);289170 csd_unlock(csd);290171 local_irq_save(flags);291172 func(info);173173+ csd_lock_record(NULL);292174 local_irq_restore(flags);293175 return 0;294176 }···390268 entry = &csd_next->llist;391269 }392270271271+ csd_lock_record(csd);393272 func(info);394273 csd_unlock(csd);274274+ csd_lock_record(NULL);395275 } else {396276 prev = &csd->llist;397277 }···420296 smp_call_func_t func = csd->func;421297 void *info = csd->info;422298299299+ csd_lock_record(csd);423300 csd_unlock(csd);424301 func(info);302302+ csd_lock_record(NULL);425303 } else if (type == CSD_TYPE_IRQ_WORK) {426304 irq_work_single(csd);427305 }···501375502376 csd->func = func;503377 csd->info = info;378378+#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG379379+ csd->src = smp_processor_id();380380+ csd->dst = cpu;381381+#endif504382505383 err = generic_exec_single(cpu, csd);506384···670540 csd->flags |= CSD_TYPE_SYNC;671541 csd->func = func;672542 csd->info = info;543543+#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG544544+ csd->src = smp_processor_id();545545+ csd->dst = cpu;546546+#endif673547 if (llist_add(&csd->llist, &per_cpu(call_single_queue, cpu)))674548 __cpumask_set_cpu(cpu, cfd->cpumask_ipi);675549 }
+11
lib/Kconfig.debug
···13771377 module may be built after the fact on the running kernel to13781378 be tested, if desired.1379137913801380+config CSD_LOCK_WAIT_DEBUG13811381+ bool "Debugging for csd_lock_wait(), called from smp_call_function*()"13821382+ depends on DEBUG_KERNEL13831383+ depends on 64BIT13841384+ default n13851385+ help13861386+ This option enables debug prints when CPUs are slow to respond13871387+ to the smp_call_function*() IPI wrappers. These debug prints13881388+ include the IPI handler function currently executing (if any)13891389+ and relevant stack traces.13901390+13801391endmenu # lock debugging1381139213821393config TRACE_IRQFLAGS
+5-1
lib/nmi_backtrace.c
···8585 put_cpu();8686}87878888+// Dump stacks even for idle CPUs.8989+static bool backtrace_idle;9090+module_param(backtrace_idle, bool, 0644);9191+8892bool nmi_cpu_backtrace(struct pt_regs *regs)8993{9094 int cpu = smp_processor_id();91959296 if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {9393- if (regs && cpu_in_idle(instruction_pointer(regs))) {9797+ if (!READ_ONCE(backtrace_idle) && regs && cpu_in_idle(instruction_pointer(regs))) {9498 pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n",9599 cpu, (void *)instruction_pointer(regs));96100 } else {