| .. | .. |
|---|
| 429 | 429 | printk_safe_exit_irqrestore(flags); \ |
|---|
| 430 | 430 | } while (0) |
|---|
| 431 | 431 | |
|---|
| 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 | + |
|---|
| 432 | 491 | #ifdef CONFIG_PRINTK |
|---|
| 433 | 492 | DECLARE_WAIT_QUEUE_HEAD(log_wait); |
|---|
| 434 | 493 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
|---|
| .. | .. |
|---|
| 1517 | 1576 | u64 next_seq; |
|---|
| 1518 | 1577 | u64 seq; |
|---|
| 1519 | 1578 | u32 idx; |
|---|
| 1579 | + int attempts = 0; |
|---|
| 1580 | + int num_msg; |
|---|
| 1520 | 1581 | |
|---|
| 1521 | 1582 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
|---|
| 1522 | 1583 | if (!text) |
|---|
| 1523 | 1584 | return -ENOMEM; |
|---|
| 1524 | 1585 | |
|---|
| 1525 | 1586 | 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 | + |
|---|
| 1526 | 1596 | /* |
|---|
| 1527 | 1597 | * Find first record that fits, including all following records, |
|---|
| 1528 | 1598 | * into the user-provided buffer for this dump. |
|---|
| .. | .. |
|---|
| 1535 | 1605 | len += msg_print_text(msg, true, NULL, 0); |
|---|
| 1536 | 1606 | idx = log_next(idx); |
|---|
| 1537 | 1607 | 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 | + } |
|---|
| 1538 | 1616 | } |
|---|
| 1539 | 1617 | |
|---|
| 1540 | 1618 | /* move first record forward until length fits into the buffer */ |
|---|
| .. | .. |
|---|
| 1546 | 1624 | len -= msg_print_text(msg, true, NULL, 0); |
|---|
| 1547 | 1625 | idx = log_next(idx); |
|---|
| 1548 | 1626 | 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 | + } |
|---|
| 1549 | 1635 | } |
|---|
| 1550 | 1636 | |
|---|
| 1551 | 1637 | /* last message fitting into this dump */ |
|---|
| .. | .. |
|---|
| 1583 | 1669 | clear_seq = log_next_seq; |
|---|
| 1584 | 1670 | clear_idx = log_next_idx; |
|---|
| 1585 | 1671 | } |
|---|
| 1672 | +out: |
|---|
| 1586 | 1673 | logbuf_unlock_irq(); |
|---|
| 1587 | 1674 | |
|---|
| 1588 | 1675 | kfree(text); |
|---|
| .. | .. |
|---|
| 1714 | 1801 | return do_syslog(type, buf, len, SYSLOG_FROM_READER); |
|---|
| 1715 | 1802 | } |
|---|
| 1716 | 1803 | |
|---|
| 1804 | +#ifndef CONFIG_PREEMPT_RT_FULL |
|---|
| 1717 | 1805 | /* |
|---|
| 1718 | 1806 | * Special console_lock variants that help to reduce the risk of soft-lockups. |
|---|
| 1719 | 1807 | * They allow to pass console_lock to another printk() call using a busy wait. |
|---|
| .. | .. |
|---|
| 1854 | 1942 | return 1; |
|---|
| 1855 | 1943 | } |
|---|
| 1856 | 1944 | |
|---|
| 1945 | +#else |
|---|
| 1946 | + |
|---|
| 1947 | +static int console_trylock_spinning(void) |
|---|
| 1948 | +{ |
|---|
| 1949 | + return console_trylock(); |
|---|
| 1950 | +} |
|---|
| 1951 | + |
|---|
| 1952 | +#endif |
|---|
| 1953 | + |
|---|
| 1857 | 1954 | /* |
|---|
| 1858 | 1955 | * Call the console drivers, asking them to write out |
|---|
| 1859 | 1956 | * log_buf[start] to log_buf[end - 1]. |
|---|
| .. | .. |
|---|
| 1872 | 1969 | if (!console_drivers) |
|---|
| 1873 | 1970 | return; |
|---|
| 1874 | 1971 | |
|---|
| 1972 | + if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) { |
|---|
| 1973 | + if (in_irq() || in_nmi()) |
|---|
| 1974 | + return; |
|---|
| 1975 | + } |
|---|
| 1976 | + |
|---|
| 1977 | + migrate_disable(); |
|---|
| 1875 | 1978 | for_each_console(con) { |
|---|
| 1876 | 1979 | if (exclusive_console && con != exclusive_console) |
|---|
| 1877 | 1980 | continue; |
|---|
| .. | .. |
|---|
| 1887 | 1990 | else |
|---|
| 1888 | 1991 | con->write(con, text, len); |
|---|
| 1889 | 1992 | } |
|---|
| 1993 | + migrate_enable(); |
|---|
| 1890 | 1994 | } |
|---|
| 1891 | 1995 | |
|---|
| 1892 | 1996 | int printk_delay_msec __read_mostly; |
|---|
| .. | .. |
|---|
| 2057 | 2161 | unsigned long flags; |
|---|
| 2058 | 2162 | u64 curr_log_seq; |
|---|
| 2059 | 2163 | |
|---|
| 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 | + |
|---|
| 2060 | 2171 | if (level == LOGLEVEL_SCHED) { |
|---|
| 2061 | 2172 | level = LOGLEVEL_DEFAULT; |
|---|
| 2062 | 2173 | in_sched = true; |
|---|
| .. | .. |
|---|
| 2074 | 2185 | |
|---|
| 2075 | 2186 | /* If called from the scheduler, we can not call up(). */ |
|---|
| 2076 | 2187 | 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 |
|---|
| 2077 | 2198 | /* |
|---|
| 2078 | 2199 | * Disable preemption to avoid being preempted while holding |
|---|
| 2079 | 2200 | * console_sem which would prevent anyone from printing to |
|---|
| 2080 | 2201 | * console |
|---|
| 2081 | 2202 | */ |
|---|
| 2082 | | - preempt_disable(); |
|---|
| 2203 | + migrate_disable(); |
|---|
| 2083 | 2204 | /* |
|---|
| 2084 | 2205 | * Try to acquire and then immediately release the console |
|---|
| 2085 | 2206 | * semaphore. The release will print out buffers and wake up |
|---|
| 2086 | 2207 | * /dev/kmsg and syslog() users. |
|---|
| 2087 | 2208 | */ |
|---|
| 2088 | | - if (console_trylock_spinning()) |
|---|
| 2209 | + if (may_trylock && console_trylock_spinning()) |
|---|
| 2089 | 2210 | console_unlock(); |
|---|
| 2090 | | - preempt_enable(); |
|---|
| 2211 | + migrate_enable(); |
|---|
| 2091 | 2212 | } |
|---|
| 2092 | 2213 | |
|---|
| 2093 | 2214 | if (pending_output) |
|---|
| .. | .. |
|---|
| 2200 | 2321 | static bool suppress_message_printing(int level) { return false; } |
|---|
| 2201 | 2322 | |
|---|
| 2202 | 2323 | #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 |
|---|
| 2223 | 2324 | |
|---|
| 2224 | 2325 | static int __add_preferred_console(char *name, int idx, char *options, |
|---|
| 2225 | 2326 | char *brl_options) |
|---|
| .. | .. |
|---|
| 2579 | 2680 | console_seq++; |
|---|
| 2580 | 2681 | raw_spin_unlock(&logbuf_lock); |
|---|
| 2581 | 2682 | |
|---|
| 2683 | +#ifdef CONFIG_PREEMPT_RT_FULL |
|---|
| 2684 | + printk_safe_exit_irqrestore(flags); |
|---|
| 2685 | + call_console_drivers(ext_text, ext_len, text, len); |
|---|
| 2686 | +#else |
|---|
| 2582 | 2687 | /* |
|---|
| 2583 | 2688 | * While actively printing out messages, if another printk() |
|---|
| 2584 | 2689 | * were to occur on another CPU, it may wait for this one to |
|---|
| .. | .. |
|---|
| 2601 | 2706 | } |
|---|
| 2602 | 2707 | |
|---|
| 2603 | 2708 | printk_safe_exit_irqrestore(flags); |
|---|
| 2709 | +#endif |
|---|
| 2604 | 2710 | |
|---|
| 2605 | 2711 | if (do_cond_resched) |
|---|
| 2606 | 2712 | cond_resched(); |
|---|
| .. | .. |
|---|
| 2648 | 2754 | { |
|---|
| 2649 | 2755 | struct console *c; |
|---|
| 2650 | 2756 | |
|---|
| 2757 | + if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) { |
|---|
| 2758 | + if (in_irq() || in_nmi()) |
|---|
| 2759 | + return; |
|---|
| 2760 | + } |
|---|
| 2761 | + |
|---|
| 2651 | 2762 | /* |
|---|
| 2652 | 2763 | * console_unblank can no longer be called in interrupt context unless |
|---|
| 2653 | 2764 | * oops_in_progress is set to 1.. |
|---|