linux/kernel/printk/printk_safe.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * printk_safe.c - Safe printk for printk-deadlock-prone contexts
   4 */
   5
   6#include <linux/preempt.h>
   7#include <linux/kdb.h>
   8#include <linux/smp.h>
   9#include <linux/cpumask.h>
  10#include <linux/printk.h>
  11#include <linux/kprobes.h>
  12
  13#include "internal.h"
  14
  15static DEFINE_PER_CPU(int, printk_context);
  16
  17/* Can be preempted by NMI. */
  18void __printk_safe_enter(void)
  19{
  20        this_cpu_inc(printk_context);
  21}
  22
  23/* Can be preempted by NMI. */
  24void __printk_safe_exit(void)
  25{
  26        this_cpu_dec(printk_context);
  27}
  28
  29asmlinkage int vprintk(const char *fmt, va_list args)
  30{
  31#ifdef CONFIG_KGDB_KDB
  32        /* Allow to pass printk() to kdb but avoid a recursion. */
  33        if (unlikely(kdb_trap_printk && kdb_printf_cpu < 0))
  34                return vkdb_printf(KDB_MSGSRC_PRINTK, fmt, args);
  35#endif
  36
  37        /*
  38         * Use the main logbuf even in NMI. But avoid calling console
  39         * drivers that might have their own locks.
  40         */
  41        if (this_cpu_read(printk_context) || in_nmi()) {
  42                int len;
  43
  44                len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
  45                defer_console_output();
  46                return len;
  47        }
  48
  49        /* No obstacles. */
  50        return vprintk_default(fmt, args);
  51}
  52EXPORT_SYMBOL(vprintk);
  53