hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/kernel/panic.c
....@@ -31,6 +31,7 @@
3131 #include <linux/bug.h>
3232 #include <linux/ratelimit.h>
3333 #include <linux/debugfs.h>
34
+#include <linux/sysfs.h>
3435 #include <asm/sections.h>
3536
3637 #define PANIC_TIMER_STEP 100
....@@ -41,7 +42,9 @@
4142 * Should we dump all CPUs backtraces in an oops event?
4243 * Defaults to 0, can be changed via sysctl.
4344 */
44
-unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
45
+static unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
46
+#else
47
+#define sysctl_oops_all_cpu_backtrace 0
4548 #endif /* CONFIG_SMP */
4649
4750 int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;
....@@ -54,6 +57,7 @@
5457 int panic_on_warn __read_mostly;
5558 unsigned long panic_on_taint;
5659 bool panic_on_taint_nousertaint = false;
60
+static unsigned int warn_limit __read_mostly;
5761
5862 int panic_timeout = CONFIG_PANIC_TIMEOUT;
5963 EXPORT_SYMBOL_GPL(panic_timeout);
....@@ -69,6 +73,56 @@
6973 ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
7074
7175 EXPORT_SYMBOL(panic_notifier_list);
76
+
77
+#ifdef CONFIG_SYSCTL
78
+static struct ctl_table kern_panic_table[] = {
79
+#ifdef CONFIG_SMP
80
+ {
81
+ .procname = "oops_all_cpu_backtrace",
82
+ .data = &sysctl_oops_all_cpu_backtrace,
83
+ .maxlen = sizeof(int),
84
+ .mode = 0644,
85
+ .proc_handler = proc_dointvec_minmax,
86
+ .extra1 = SYSCTL_ZERO,
87
+ .extra2 = SYSCTL_ONE,
88
+ },
89
+#endif
90
+ {
91
+ .procname = "warn_limit",
92
+ .data = &warn_limit,
93
+ .maxlen = sizeof(warn_limit),
94
+ .mode = 0644,
95
+ .proc_handler = proc_douintvec,
96
+ },
97
+ { }
98
+};
99
+
100
+static __init int kernel_panic_sysctls_init(void)
101
+{
102
+ register_sysctl_init("kernel", kern_panic_table);
103
+ return 0;
104
+}
105
+late_initcall(kernel_panic_sysctls_init);
106
+#endif
107
+
108
+static atomic_t warn_count = ATOMIC_INIT(0);
109
+
110
+#ifdef CONFIG_SYSFS
111
+static ssize_t warn_count_show(struct kobject *kobj, struct kobj_attribute *attr,
112
+ char *page)
113
+{
114
+ return sysfs_emit(page, "%d\n", atomic_read(&warn_count));
115
+}
116
+
117
+static struct kobj_attribute warn_count_attr = __ATTR_RO(warn_count);
118
+
119
+static __init int kernel_panic_sysfs_init(void)
120
+{
121
+ sysfs_add_file_to_group(kernel_kobj, &warn_count_attr.attr, NULL);
122
+ return 0;
123
+}
124
+late_initcall(kernel_panic_sysfs_init);
125
+#endif
72126
73127 static long no_blink(int state)
74128 {
....@@ -166,6 +220,19 @@
166220 ftrace_dump(DUMP_ALL);
167221 }
168222
223
+void check_panic_on_warn(const char *origin)
224
+{
225
+ unsigned int limit;
226
+
227
+ if (panic_on_warn)
228
+ panic("%s: panic_on_warn set ...\n", origin);
229
+
230
+ limit = READ_ONCE(warn_limit);
231
+ if (atomic_inc_return(&warn_count) >= limit && limit)
232
+ panic("%s: system warned too often (kernel.warn_limit is %d)",
233
+ origin, limit);
234
+}
235
+
169236 /**
170237 * panic - halt the system
171238 * @fmt: The text string to print
....@@ -177,12 +244,21 @@
177244 void panic(const char *fmt, ...)
178245 {
179246 static char buf[1024];
180
- va_list args2;
181247 va_list args;
182248 long i, i_next = 0, len;
183249 int state = 0;
184250 int old_cpu, this_cpu;
185251 bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
252
+
253
+ if (panic_on_warn) {
254
+ /*
255
+ * This thread may hit another WARN() in the panic path.
256
+ * Resetting this prevents additional WARN() from panicking the
257
+ * system on this thread. Other threads are blocked by the
258
+ * panic_mutex in panic().
259
+ */
260
+ panic_on_warn = 0;
261
+ }
186262
187263 /*
188264 * Disable local interrupts. This will prevent panic_smp_self_stop
....@@ -192,21 +268,6 @@
192268 */
193269 local_irq_disable();
194270 preempt_disable_notrace();
195
-
196
- console_verbose();
197
- pr_emerg("Kernel panic - not syncing:\n");
198
- va_start(args2, fmt);
199
- va_copy(args, args2);
200
- vprintk(fmt, args2);
201
- va_end(args2);
202
-#ifdef CONFIG_DEBUG_BUGVERBOSE
203
- /*
204
- * Avoid nested stack-dumping if a panic occurs during oops processing
205
- */
206
- if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)
207
- dump_stack();
208
-#endif
209
- pr_flush(1000, true);
210271
211272 /*
212273 * It's possible to come here directly from a panic-assertion and
....@@ -229,12 +290,23 @@
229290 if (old_cpu != PANIC_CPU_INVALID && old_cpu != this_cpu)
230291 panic_smp_self_stop();
231292
293
+ console_verbose();
232294 bust_spinlocks(1);
295
+ va_start(args, fmt);
233296 len = vscnprintf(buf, sizeof(buf), fmt, args);
234297 va_end(args);
235298
236299 if (len && buf[len - 1] == '\n')
237300 buf[len - 1] = '\0';
301
+
302
+ pr_emerg("Kernel panic - not syncing: %s\n", buf);
303
+#ifdef CONFIG_DEBUG_BUGVERBOSE
304
+ /*
305
+ * Avoid nested stack-dumping if a panic occurs during oops processing
306
+ */
307
+ if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)
308
+ dump_stack();
309
+#endif
238310
239311 /*
240312 * If kgdb is enabled, give it a chance to run before we stop all
....@@ -252,6 +324,7 @@
252324 * Bypass the panic_cpu check and call __crash_kexec directly.
253325 */
254326 if (!_crash_kexec_post_notifiers) {
327
+ printk_safe_flush_on_panic();
255328 __crash_kexec(NULL);
256329
257330 /*
....@@ -275,6 +348,8 @@
275348 */
276349 atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
277350
351
+ /* Call flush even twice. It tries harder with a single online CPU */
352
+ printk_safe_flush_on_panic();
278353 kmsg_dump(KMSG_DUMP_PANIC);
279354
280355 /*
....@@ -544,11 +619,9 @@
544619
545620 static int init_oops_id(void)
546621 {
547
-#ifndef CONFIG_PREEMPT_RT
548622 if (!oops_id)
549623 get_random_bytes(&oops_id, sizeof(oops_id));
550624 else
551
-#endif
552625 oops_id++;
553626
554627 return 0;
....@@ -559,7 +632,6 @@
559632 {
560633 init_oops_id();
561634 pr_warn("---[ end trace %016llx ]---\n", (unsigned long long)oops_id);
562
- pr_flush(1000, true);
563635 }
564636
565637 /*
....@@ -599,16 +671,7 @@
599671 if (regs)
600672 show_regs(regs);
601673
602
- if (panic_on_warn) {
603
- /*
604
- * This thread may hit another WARN() in the panic path.
605
- * Resetting this prevents additional WARN() from panicking the
606
- * system on this thread. Other threads are blocked by the
607
- * panic_mutex in panic().
608
- */
609
- panic_on_warn = 0;
610
- panic("panic_on_warn set ...\n");
611
- }
674
+ check_panic_on_warn("kernel");
612675
613676 if (!regs)
614677 dump_stack();