hc
2023-11-06 1622ff3442ff6aecc1f538cda437379d1f6a4a93
kernel/kernel/printk/printk.c
....@@ -429,6 +429,65 @@
429429 printk_safe_exit_irqrestore(flags); \
430430 } while (0)
431431
432
+#ifdef CONFIG_EARLY_PRINTK
433
+struct console *early_console;
434
+
435
+static void early_vprintk(const char *fmt, va_list ap)
436
+{
437
+ if (early_console) {
438
+ char buf[512];
439
+ int n = vscnprintf(buf, sizeof(buf), fmt, ap);
440
+
441
+ early_console->write(early_console, buf, n);
442
+ }
443
+}
444
+
445
+asmlinkage void early_printk(const char *fmt, ...)
446
+{
447
+ va_list ap;
448
+
449
+ va_start(ap, fmt);
450
+ early_vprintk(fmt, ap);
451
+ va_end(ap);
452
+}
453
+
454
+/*
455
+ * This is independent of any log levels - a global
456
+ * kill switch that turns off all of printk.
457
+ *
458
+ * Used by the NMI watchdog if early-printk is enabled.
459
+ */
460
+static bool __read_mostly printk_killswitch;
461
+
462
+static int __init force_early_printk_setup(char *str)
463
+{
464
+ printk_killswitch = true;
465
+ return 0;
466
+}
467
+early_param("force_early_printk", force_early_printk_setup);
468
+
469
+void printk_kill(void)
470
+{
471
+ printk_killswitch = true;
472
+}
473
+
474
+#ifdef CONFIG_PRINTK
475
+static int forced_early_printk(const char *fmt, va_list ap)
476
+{
477
+ if (!printk_killswitch)
478
+ return 0;
479
+ early_vprintk(fmt, ap);
480
+ return 1;
481
+}
482
+#endif
483
+
484
+#else
485
+static inline int forced_early_printk(const char *fmt, va_list ap)
486
+{
487
+ return 0;
488
+}
489
+#endif
490
+
432491 #ifdef CONFIG_PRINTK
433492 DECLARE_WAIT_QUEUE_HEAD(log_wait);
434493 /* the next printk record to read by syslog(READ) or /proc/kmsg */
....@@ -1517,12 +1576,23 @@
15171576 u64 next_seq;
15181577 u64 seq;
15191578 u32 idx;
1579
+ int attempts = 0;
1580
+ int num_msg;
15201581
15211582 text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
15221583 if (!text)
15231584 return -ENOMEM;
15241585
15251586 logbuf_lock_irq();
1587
+
1588
+try_again:
1589
+ attempts++;
1590
+ if (attempts > 10) {
1591
+ len = -EBUSY;
1592
+ goto out;
1593
+ }
1594
+ num_msg = 0;
1595
+
15261596 /*
15271597 * Find first record that fits, including all following records,
15281598 * into the user-provided buffer for this dump.
....@@ -1535,6 +1605,14 @@
15351605 len += msg_print_text(msg, true, NULL, 0);
15361606 idx = log_next(idx);
15371607 seq++;
1608
+ num_msg++;
1609
+ if (num_msg > 5) {
1610
+ num_msg = 0;
1611
+ logbuf_unlock_irq();
1612
+ logbuf_lock_irq();
1613
+ if (clear_seq < log_first_seq)
1614
+ goto try_again;
1615
+ }
15381616 }
15391617
15401618 /* move first record forward until length fits into the buffer */
....@@ -1546,6 +1624,14 @@
15461624 len -= msg_print_text(msg, true, NULL, 0);
15471625 idx = log_next(idx);
15481626 seq++;
1627
+ num_msg++;
1628
+ if (num_msg > 5) {
1629
+ num_msg = 0;
1630
+ logbuf_unlock_irq();
1631
+ logbuf_lock_irq();
1632
+ if (clear_seq < log_first_seq)
1633
+ goto try_again;
1634
+ }
15491635 }
15501636
15511637 /* last message fitting into this dump */
....@@ -1583,6 +1669,7 @@
15831669 clear_seq = log_next_seq;
15841670 clear_idx = log_next_idx;
15851671 }
1672
+out:
15861673 logbuf_unlock_irq();
15871674
15881675 kfree(text);
....@@ -1714,6 +1801,7 @@
17141801 return do_syslog(type, buf, len, SYSLOG_FROM_READER);
17151802 }
17161803
1804
+#ifndef CONFIG_PREEMPT_RT_FULL
17171805 /*
17181806 * Special console_lock variants that help to reduce the risk of soft-lockups.
17191807 * They allow to pass console_lock to another printk() call using a busy wait.
....@@ -1854,6 +1942,15 @@
18541942 return 1;
18551943 }
18561944
1945
+#else
1946
+
1947
+static int console_trylock_spinning(void)
1948
+{
1949
+ return console_trylock();
1950
+}
1951
+
1952
+#endif
1953
+
18571954 /*
18581955 * Call the console drivers, asking them to write out
18591956 * log_buf[start] to log_buf[end - 1].
....@@ -1872,6 +1969,12 @@
18721969 if (!console_drivers)
18731970 return;
18741971
1972
+ if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) {
1973
+ if (in_irq() || in_nmi())
1974
+ return;
1975
+ }
1976
+
1977
+ migrate_disable();
18751978 for_each_console(con) {
18761979 if (exclusive_console && con != exclusive_console)
18771980 continue;
....@@ -1887,6 +1990,7 @@
18871990 else
18881991 con->write(con, text, len);
18891992 }
1993
+ migrate_enable();
18901994 }
18911995
18921996 int printk_delay_msec __read_mostly;
....@@ -2057,6 +2161,13 @@
20572161 unsigned long flags;
20582162 u64 curr_log_seq;
20592163
2164
+ /*
2165
+ * Fall back to early_printk if a debugging subsystem has
2166
+ * killed printk output
2167
+ */
2168
+ if (unlikely(forced_early_printk(fmt, args)))
2169
+ return 1;
2170
+
20602171 if (level == LOGLEVEL_SCHED) {
20612172 level = LOGLEVEL_DEFAULT;
20622173 in_sched = true;
....@@ -2074,20 +2185,30 @@
20742185
20752186 /* If called from the scheduler, we can not call up(). */
20762187 if (!in_sched && pending_output) {
2188
+ int may_trylock = 1;
2189
+
2190
+#ifdef CONFIG_PREEMPT_RT_FULL
2191
+ /*
2192
+ * we can't take a sleeping lock with IRQs or preeption disabled
2193
+ * so we can't print in these contexts
2194
+ */
2195
+ if (!(preempt_count() == 0 && !irqs_disabled()))
2196
+ may_trylock = 0;
2197
+#endif
20772198 /*
20782199 * Disable preemption to avoid being preempted while holding
20792200 * console_sem which would prevent anyone from printing to
20802201 * console
20812202 */
2082
- preempt_disable();
2203
+ migrate_disable();
20832204 /*
20842205 * Try to acquire and then immediately release the console
20852206 * semaphore. The release will print out buffers and wake up
20862207 * /dev/kmsg and syslog() users.
20872208 */
2088
- if (console_trylock_spinning())
2209
+ if (may_trylock && console_trylock_spinning())
20892210 console_unlock();
2090
- preempt_enable();
2211
+ migrate_enable();
20912212 }
20922213
20932214 if (pending_output)
....@@ -2200,26 +2321,6 @@
22002321 static bool suppress_message_printing(int level) { return false; }
22012322
22022323 #endif /* CONFIG_PRINTK */
2203
-
2204
-#ifdef CONFIG_EARLY_PRINTK
2205
-struct console *early_console;
2206
-
2207
-asmlinkage __visible void early_printk(const char *fmt, ...)
2208
-{
2209
- va_list ap;
2210
- char buf[512];
2211
- int n;
2212
-
2213
- if (!early_console)
2214
- return;
2215
-
2216
- va_start(ap, fmt);
2217
- n = vscnprintf(buf, sizeof(buf), fmt, ap);
2218
- va_end(ap);
2219
-
2220
- early_console->write(early_console, buf, n);
2221
-}
2222
-#endif
22232324
22242325 static int __add_preferred_console(char *name, int idx, char *options,
22252326 char *brl_options)
....@@ -2579,6 +2680,10 @@
25792680 console_seq++;
25802681 raw_spin_unlock(&logbuf_lock);
25812682
2683
+#ifdef CONFIG_PREEMPT_RT_FULL
2684
+ printk_safe_exit_irqrestore(flags);
2685
+ call_console_drivers(ext_text, ext_len, text, len);
2686
+#else
25822687 /*
25832688 * While actively printing out messages, if another printk()
25842689 * were to occur on another CPU, it may wait for this one to
....@@ -2601,6 +2706,7 @@
26012706 }
26022707
26032708 printk_safe_exit_irqrestore(flags);
2709
+#endif
26042710
26052711 if (do_cond_resched)
26062712 cond_resched();
....@@ -2648,6 +2754,11 @@
26482754 {
26492755 struct console *c;
26502756
2757
+ if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) {
2758
+ if (in_irq() || in_nmi())
2759
+ return;
2760
+ }
2761
+
26512762 /*
26522763 * console_unblank can no longer be called in interrupt context unless
26532764 * oops_in_progress is set to 1..