Commit df43d903 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'printk-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux

Pull printk updates from Petr Mladek:

 - Optionally, provide an index of possible printk messages via
   <debugfs>/printk/index/. It can be used when monitoring important
   kernel messages on a farm of various hosts. The monitor has to be
   updated when some messages has changed or are not longer available by
   a newly deployed kernel.

 - Add printk.console_no_auto_verbose boot parameter. It allows to
   generate crash dump even with slow consoles in a reasonable time
   frame.

 - Remove printk_safe buffers. The messages are always stored directly
   to the main logbuffer, even in NMI or recursive context. Also it
   allows to serialize syslog operations by a mutex instead of a spin
   lock.

 - Misc clean up and build fixes.

* tag 'printk-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  printk/index: Fix -Wunused-function warning
  lib/nmi_backtrace: Serialize even messages about idle CPUs
  printk: Add printk.console_no_auto_verbose boot parameter
  printk: Remove console_silent()
  lib/test_scanf: Handle n_bits == 0 in random tests
  printk: syslog: close window between wait and read
  printk: convert @syslog_lock to mutex
  printk: remove NMI tracking
  printk: remove safe buffers
  printk: track/limit recursion
  lib/nmi_backtrace: explicitly serialize banner and regs
  printk: Move the printk() kerneldoc comment to its new home
  printk/index: Fix warning about missing prototypes
  MIPS/asm/printk: Fix build failure caused by printk
  printk: index: Add indexing support to dev_printk
  printk: Userspace format indexing support
  printk: Rework parse_prefix into printk_parse_prefix
  printk: Straighten out log_flags into printk_info_flags
  string_helpers: Escape double quotes in escape_special
  printk/console: Check consistent sequence number when handling race in console_unlock()
parents 9e5f3ffc c985aafb
......@@ -4198,6 +4198,15 @@
Format: <bool> (1/Y/y=enable, 0/N/n=disable)
default: disabled
printk.console_no_auto_verbose=
Disable console loglevel raise on oops, panic
or lockdep-detected issues (only if lock debug is on).
With an exception to setups with low baudrate on
serial console, keeping this 0 is a good choice
in order to provide more debug information.
Format: <bool>
default: 0 (auto_verbose is enabled)
printk.devkmsg={on,off,ratelimit}
Control writing to /dev/kmsg.
on - unlimited logging to /dev/kmsg from userspace
......
......@@ -107,9 +107,6 @@ also ``CONFIG_DYNAMIC_DEBUG`` in the case of pr_debug()) is defined.
Function reference
==================
.. kernel-doc:: kernel/printk/printk.c
:functions: printk
.. kernel-doc:: include/linux/printk.h
:functions: pr_emerg pr_alert pr_crit pr_err pr_warn pr_notice pr_info
:functions: printk pr_emerg pr_alert pr_crit pr_err pr_warn pr_notice pr_info
pr_fmt pr_debug pr_devel pr_cont
......@@ -15021,6 +15021,11 @@ S: Maintained
F: include/linux/printk.h
F: kernel/printk/
PRINTK INDEXING
R: Chris Down <chris@chrisdown.name>
S: Maintained
F: kernel/printk/index.c
PROC FILESYSTEM
L: linux-kernel@vger.kernel.org
L: linux-fsdevel@vger.kernel.org
......
......@@ -23,7 +23,7 @@ __invalid_entry:
adr r0, strerr
mrs r1, ipsr
mov r2, lr
bl printk
bl _printk
#endif
mov r0, sp
bl show_regs
......
......@@ -667,9 +667,9 @@ static void do_handle_IPI(int ipinr)
break;
case IPI_CPU_BACKTRACE:
printk_nmi_enter();
printk_deferred_enter();
nmi_cpu_backtrace(get_irq_regs());
printk_nmi_exit();
printk_deferred_exit();
break;
default:
......
......@@ -202,7 +202,7 @@ finished_setup:
1006: adr r0, .Lbad
mov r1, loglvl
mov r2, frame
bl printk
bl _printk
no_frame: ldmfd sp!, {r4 - r9, fp, pc}
ENDPROC(c_backtrace)
.pushsection __ex_table,"a"
......
......@@ -103,7 +103,7 @@ for_each_frame: tst frame, mask @ Check for address exceptions
1006: adr r0, .Lbad
mov r1, loglvl
mov r2, frame
bl printk
bl _printk
no_frame: ldmfd sp!, {r4 - r9, pc}
ENDPROC(c_backtrace)
......
......@@ -25,4 +25,4 @@ ENTRY(insl)
ENTRY(outsl)
adr r0, .Liosl_warning
mov r1, lr
b printk
b _printk
......@@ -23,7 +23,7 @@
#ifdef DEBUG
stmfd sp!, {r0-r3, ip, lr}
ldr r0, =1f
bl printk
bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
......@@ -38,7 +38,7 @@
stmfd sp!, {r0-r3, ip, lr}
mov r1, \arg
ldr r0, =1f
bl printk
bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
......@@ -55,7 +55,7 @@
mov r2, \arg2
mov r1, \arg1
ldr r0, =1f
bl printk
bl _printk
ldmfd sp!, {r0-r3, ip, lr}
.pushsection .rodata, "a"
......
......@@ -143,9 +143,9 @@ extern long ia64_cmpxchg_called_with_bad_pointer(void);
do { \
if (_cmpxchg_bugcheck_count-- <= 0) { \
void *ip; \
extern int printk(const char *fmt, ...); \
extern int _printk(const char *fmt, ...); \
ip = (void *) ia64_getreg(_IA64_REG_IP); \
printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
_printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
break; \
} \
} while (0)
......
......@@ -114,7 +114,7 @@ symbol = value
.set push; \
.set reorder; \
PTR_LA a0, 8f; \
jal printk; \
jal _printk; \
.set pop; \
TEXT(string)
#else
......
......@@ -551,7 +551,7 @@ EXCEPTION_ENTRY(_external_irq_handler)
l.movhi r3,hi(42f)
l.ori r3,r3,lo(42f)
l.sw 0x0(r1),r3
l.jal printk
l.jal _printk
l.sw 0x4(r1),r4
l.addi r1,r1,0x8
......@@ -681,8 +681,8 @@ _syscall_debug:
l.sw -4(r1),r27
l.sw -8(r1),r11
l.addi r1,r1,-8
l.movhi r27,hi(printk)
l.ori r27,r27,lo(printk)
l.movhi r27,hi(_printk)
l.ori r27,r27,lo(_printk)
l.jalr r27
l.nop
l.addi r1,r1,8
......
......@@ -858,7 +858,7 @@ KernelSPE:
ori r3,r3,87f@l
mr r4,r2 /* current */
lwz r5,_NIP(r1)
bl printk
bl _printk
#endif
b interrupt_return
#ifdef CONFIG_PRINTK
......
......@@ -171,7 +171,6 @@ extern void panic_flush_kmsg_start(void)
extern void panic_flush_kmsg_end(void)
{
printk_safe_flush_on_panic();
kmsg_dump(KMSG_DUMP_PANIC);
bust_spinlocks(0);
debug_locks_off();
......
......@@ -184,11 +184,6 @@ static void watchdog_smp_panic(int cpu, u64 tb)
wd_smp_unlock(&flags);
printk_safe_flush();
/*
* printk_safe_flush() seems to require another print
* before anything actually goes out to console.
*/
if (sysctl_hardlockup_all_cpu_backtrace)
trigger_allbutself_cpu_backtrace();
......
......@@ -313,7 +313,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
int (*old_handler)(struct pt_regs *regs);
/* Avoid hardlocking with irresponsive CPU holding logbuf_lock */
printk_nmi_enter();
printk_deferred_enter();
/*
* This function is only called after the system
......
......@@ -38,7 +38,8 @@ extern void panic(const char *fmt, ...)
#define UM_KERN_CONT KERN_CONT
#ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...)
#define printk(...) _printk(__VA_ARGS__)
extern int _printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#else
static inline int printk(const char *fmt, ...)
......
......@@ -432,7 +432,7 @@ SYM_FUNC_START(early_ignore_irq)
pushl 32(%esp)
pushl 40(%esp)
pushl $int_msg
call printk
call _printk
call dump_stack
......
......@@ -4579,8 +4579,8 @@ static void __dev_printk(const char *level, const struct device *dev,
printk("%s(NULL device *): %pV", level, vaf);
}
void dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
void _dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{
struct va_format vaf;
va_list args;
......@@ -4594,7 +4594,7 @@ void dev_printk(const char *level, const struct device *dev,
va_end(args);
}
EXPORT_SYMBOL(dev_printk);
EXPORT_SYMBOL(_dev_printk);
#define define_dev_printk_level(func, kern_level) \
void func(const struct device *dev, const char *fmt, ...) \
......
......@@ -483,6 +483,8 @@
\
TRACEDATA \
\
PRINTK_INDEX \
\
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
__start___ksymtab = .; \
......@@ -894,6 +896,17 @@
#define TRACEDATA
#endif
#ifdef CONFIG_PRINTK_INDEX
#define PRINTK_INDEX \
.printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) { \
__start_printk_index = .; \
*(.printk_index) \
__stop_printk_index = .; \
}
#else
#define PRINTK_INDEX
#endif
#define NOTES \
.notes : AT(ADDR(.notes) - LOAD_OFFSET) { \
__start_notes = .; \
......
......@@ -38,8 +38,8 @@ __printf(3, 4) __cold
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
__printf(3, 4) __cold
void dev_printk(const char *level, const struct device *dev,
const char *fmt, ...);
void _dev_printk(const char *level, const struct device *dev,
const char *fmt, ...);
__printf(2, 3) __cold
void _dev_emerg(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
......@@ -69,7 +69,7 @@ static inline void __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{}
static inline __printf(3, 4)
void dev_printk(const char *level, const struct device *dev,
void _dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{}
......@@ -97,25 +97,57 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
#endif
/*
* Need to take variadic arguments even though we don't use them, as dev_fmt()
* may only just have been expanded and may result in multiple arguments.
*/
#define dev_printk_index_emit(level, fmt, ...) \
printk_index_subsys_emit("%s %s: ", level, fmt)
#define dev_printk_index_wrap(_p_func, level, dev, fmt, ...) \
({ \
dev_printk_index_emit(level, fmt); \
_p_func(dev, fmt, ##__VA_ARGS__); \
})
/*
* Some callsites directly call dev_printk rather than going through the
* dev_<level> infrastructure, so we need to emit here as well as inside those
* level-specific macros. Only one index entry will be produced, either way,
* since dev_printk's `fmt` isn't known at compile time if going through the
* dev_<level> macros.
*
* dev_fmt() isn't called for dev_printk when used directly, as it's used by
* the dev_<level> macros internally which already have dev_fmt() processed.
*
* We also can't use dev_printk_index_wrap directly, because we have a separate
* level to process.
*/
#define dev_printk(level, dev, fmt, ...) \
({ \
dev_printk_index_emit(level, fmt); \
_dev_printk(level, dev, fmt, ##__VA_ARGS__); \
})
/*
* #defines for all the dev_<level> macros to prefix with whatever
* possible use of #define dev_fmt(fmt) ...
*/
#define dev_emerg(dev, fmt, ...) \
_dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
_dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
_dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
_dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
_dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
_dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
_dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_emerg(dev, fmt, ...) \
dev_printk_index_wrap(_dev_emerg, KERN_EMERG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
dev_printk_index_wrap(_dev_crit, KERN_CRIT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
dev_printk_index_wrap(_dev_alert, KERN_ALERT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
dev_printk_index_wrap(_dev_warn, KERN_WARNING, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
dev_printk_index_wrap(_dev_notice, KERN_NOTICE, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
......
......@@ -116,7 +116,6 @@ extern void rcu_nmi_exit(void);
do { \
lockdep_off(); \
arch_nmi_enter(); \
printk_nmi_enter(); \
BUG_ON(in_nmi() == NMI_MASK); \
__preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
} while (0)
......@@ -135,7 +134,6 @@ extern void rcu_nmi_exit(void);
do { \
BUG_ON(!in_nmi()); \
__preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
printk_nmi_exit(); \
arch_nmi_exit(); \
lockdep_on(); \
} while (0)
......
......@@ -511,6 +511,11 @@ struct module {
struct klp_modinfo *klp_info;
#endif
#ifdef CONFIG_PRINTK_INDEX
unsigned int printk_index_size;
struct pi_entry **printk_index_start;
#endif
#ifdef CONFIG_MODULE_UNLOAD
/* What modules depend on me? */
struct list_head source_list;
......
......@@ -70,16 +70,7 @@ extern int console_printk[];
#define minimum_console_loglevel (console_printk[2])
#define default_console_loglevel (console_printk[3])
static inline void console_silent(void)
{
console_loglevel = CONSOLE_LOGLEVEL_SILENT;
}
static inline void console_verbose(void)
{
if (console_loglevel)
console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
}
extern void console_verbose(void);
/* strlen("ratelimit") + 1 */
#define DEVKMSG_STR_MAX_SIZE 10
......@@ -150,18 +141,6 @@ static inline __printf(1, 2) __cold
void early_printk(const char *s, ...) { }
#endif
#ifdef CONFIG_PRINTK_NMI
extern void printk_nmi_enter(void);
extern void printk_nmi_exit(void);
extern void printk_nmi_direct_enter(void);
extern void printk_nmi_direct_exit(void);
#else
static inline void printk_nmi_enter(void) { }
static inline void printk_nmi_exit(void) { }
static inline void printk_nmi_direct_enter(void) { }
static inline void printk_nmi_direct_exit(void) { }
#endif /* PRINTK_NMI */
struct dev_printk_info;
#ifdef CONFIG_PRINTK
......@@ -174,12 +153,22 @@ asmlinkage __printf(1, 0)
int vprintk(const char *fmt, va_list args);
asmlinkage __printf(1, 2) __cold
int printk(const char *fmt, ...);
int _printk(const char *fmt, ...);
/*
* Special printk facility for scheduler/timekeeping use only, _DO_NOT_USE_ !
*/
__printf(1, 2) __cold int printk_deferred(const char *fmt, ...);
__printf(1, 2) __cold int _printk_deferred(const char *fmt, ...);
extern void __printk_safe_enter(void);
extern void __printk_safe_exit(void);
/*
* The printk_deferred_enter/exit macros are available only as a hack for
* some code paths that need to defer all printk console printing. Interrupts
* must be disabled for the deferred duration.
*/
#define printk_deferred_enter __printk_safe_enter
#define printk_deferred_exit __printk_safe_exit
/*
* Please don't use printk_ratelimit(), because it shares ratelimiting state
......@@ -209,8 +198,6 @@ void dump_stack_print_info(const char *log_lvl);
void show_regs_print_info(const char *log_lvl);
extern asmlinkage void dump_stack_lvl(const char *log_lvl) __cold;
extern asmlinkage void dump_stack(void) __cold;
extern void printk_safe_flush(void);
extern void printk_safe_flush_on_panic(void);
#else
static inline __printf(1, 0)
int vprintk(const char *s, va_list args)
......@@ -218,15 +205,24 @@ int vprintk(const char *s, va_list args)
return 0;
}
static inline __printf(1, 2) __cold
int printk(const char *s, ...)
int _printk(const char *s, ...)
{
return 0;
}
static inline __printf(1, 2) __cold
int printk_deferred(const char *s, ...)
int _printk_deferred(const char *s, ...)
{
return 0;
}
static inline void printk_deferred_enter(void)
{
}
static inline void printk_deferred_exit(void)
{
}
static inline int printk_ratelimit(void)
{
return 0;
......@@ -278,14 +274,6 @@ static inline void dump_stack_lvl(const char *log_lvl)
static inline void dump_stack(void)
{
}
static inline void printk_safe_flush(void)
{
}
static inline void printk_safe_flush_on_panic(void)
{
}
#endif
#ifdef CONFIG_SMP
......@@ -348,6 +336,117 @@ extern int kptr_restrict;
#define pr_fmt(fmt) fmt
#endif
struct module;
#ifdef CONFIG_PRINTK_INDEX
struct pi_entry {
const char *fmt;
const char *func;
const char *file;
unsigned int line;
/*
* While printk and pr_* have the level stored in the string at compile
* time, some subsystems dynamically add it at runtime through the
* format string. For these dynamic cases, we allow the subsystem to
* tell us the level at compile time.
*
* NULL indicates that the level, if any, is stored in fmt.
*/
const char *level;
/*
* The format string used by various subsystem specific printk()
* wrappers to prefix the message.
*
* Note that the static prefix defined by the pr_fmt() macro is stored
* directly in the message format (@fmt), not here.
*/
const char *subsys_fmt_prefix;
} __packed;
#define __printk_index_emit(_fmt, _level, _subsys_fmt_prefix) \
do { \
if (__builtin_constant_p(_fmt) && __builtin_constant_p(_level)) { \
/*
* We check __builtin_constant_p multiple times here
* for the same input because GCC will produce an error
* if we try to assign a static variable to fmt if it
* is not a constant, even with the outer if statement.
*/ \
static const struct pi_entry _entry \
__used = { \
.fmt = __builtin_constant_p(_fmt) ? (_fmt) : NULL, \
.func = __func__, \
.file = __FILE__, \
.line = __LINE__, \
.level = __builtin_constant_p(_level) ? (_level) : NULL, \
.subsys_fmt_prefix = _subsys_fmt_prefix,\
}; \
static const struct pi_entry *_entry_ptr \
__used __section(".printk_index") = &_entry; \
} \
} while (0)
#else /* !CONFIG_PRINTK_INDEX */
#define __printk_index_emit(...) do {} while (0)
#endif /* CONFIG_PRINTK_INDEX */
/*
* Some subsystems have their own custom printk that applies a va_format to a
* generic format, for example, to include a device number or other metadata
* alongside the format supplied by the caller.
*
* In order to store these in the way they would be emitted by the printk
* infrastructure, the subsystem provides us with the start, fixed string, and
* any subsequent text in the format string.
*
* We take a variable argument list as pr_fmt/dev_fmt/etc are sometimes passed
* as multiple arguments (eg: `"%s: ", "blah"`), and we must only take the
* first one.
*
* subsys_fmt_prefix must be known at compile time, or compilation will fail
* (since this is a mistake). If fmt or level is not known at compile time, no
* index entry will be made (since this can legitimately happen).
*/
#define printk_index_subsys_emit(subsys_fmt_prefix, level, fmt, ...) \
__printk_index_emit(fmt, level, subsys_fmt_prefix)
#define printk_index_wrap(_p_func, _fmt, ...) \
({ \
__printk_index_emit(_fmt, NULL, NULL); \
_p_func(_fmt, ##__VA_ARGS__); \
})
/**
* printk - print a kernel message
* @fmt: format string
*
* This is printk(). It can be called from any context. We want it to work.
*
* If printk indexing is enabled, _printk() is called from printk_index_wrap.
* Otherwise, printk is simply #defined to _printk.
*
* We try to grab the console_lock. If we succeed, it's easy - we log the
* output and call the console drivers. If we fail to get the semaphore, we
* place the output into the log buffer and return. The current holder of
* the console_sem will notice the new output in console_unlock(); and will
* send it to the consoles before releasing the lock.
*
* One effect of this deferred printing is that code which calls printk() and
* then changes console_loglevel may break. This is because console_loglevel
* is inspected when the actual printing occurs.
*
* See also:
* printf(3)
*
* See the vsnprintf() documentation for format string extensions over C99.
*/
#define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
#define printk_deferred(fmt, ...) \
printk_index_wrap(_printk_deferred, fmt, ##__VA_ARGS__)
/**
* pr_emerg - Print an emergency-level message
* @fmt: format string
......
......@@ -775,6 +775,20 @@ config PRINTK_SAFE_LOG_BUF_SHIFT
13 => 8 KB for each CPU
12 => 4 KB for each CPU
config PRINTK_INDEX
bool "Printk indexing debugfs interface"
depends on PRINTK && DEBUG_FS
help
Add support for indexing of all printk formats known at compile time
at <debugfs>/printk/index/<module>.
This can be used as part of maintaining daemons which monitor
/dev/kmsg, as it permits auditing the printk formats present in a
kernel, allowing detection of cases where monitored printks are
changed or no longer present.
There is no additional runtime cost to printk with this enabled.
#
# Architectures with an unreliable sched_clock() should select this:
#
......@@ -1509,11 +1523,6 @@ config PRINTK
very difficult to diagnose system problems, saying N here is
strongly discouraged.
config PRINTK_NMI
def_bool y
depends on PRINTK
depends on HAVE_NMI
config BUG
bool "BUG() support" if EXPERT
default y
......
......@@ -979,7 +979,6 @@ void crash_kexec(struct pt_regs *regs)
old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);
if (old_cpu == PANIC_CPU_INVALID) {
/* This is the 1st CPU which comes here, so go ahead. */
printk_safe_flush_on_panic();
__crash_kexec(regs);
/*
......
......@@ -3355,6 +3355,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)
sizeof(unsigned long),
&mod->num_kprobe_blacklist);
#endif
#ifdef CONFIG_PRINTK_INDEX
mod->printk_index_start = section_objs(info, ".printk_index",
sizeof(*mod->printk_index_start),
&mod->printk_index_size);
#endif
#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
mod->static_call_sites = section_objs(info, ".static_call_sites",
sizeof(*mod->static_call_sites),
......
......@@ -248,7 +248,6 @@ void panic(const char *fmt, ...)
* Bypass the panic_cpu check and call __crash_kexec directly.
*/
if (!_crash_kexec_post_notifiers) {
printk_safe_flush_on_panic();
__crash_kexec(NULL);
/*
......@@ -272,8 +271,6 @@ void panic(const char *fmt, ...)
*/
atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
/* Call flush even twice. It tries harder with a single online CPU */
printk_safe_flush_on_panic();
kmsg_dump(KMSG_DUMP_PANIC);
/*
......
......@@ -3,3 +3,4 @@ obj-y = printk.o
obj-$(CONFIG_PRINTK) += printk_safe.o
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o
obj-$(CONFIG_PRINTK) += printk_ringbuffer.o
obj-$(CONFIG_PRINTK_INDEX) += index.o
// SPDX-License-Identifier: GPL-2.0
/*
* Userspace indexing of printk formats
*/
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include "internal.h"
extern struct pi_entry *__start_printk_index[];
extern struct pi_entry *__stop_printk_index[];
/* The base dir for module formats, typically debugfs/printk/index/ */
static struct dentry *dfs_index;
static struct pi_entry *pi_get_entry(const struct module *mod, loff_t pos)
{
struct pi_entry **entries;
unsigned int nr_entries;
#ifdef CONFIG_MODULES
if (mod) {
entries = mod->printk_index_start;
nr_entries = mod->printk_index_size;
}
#endif
if (!mod) {
/* vmlinux, comes from linker symbols */
entries = __start_printk_index;
nr_entries = __stop_printk_index - __start_printk_index;
}
if (pos >= nr_entries)
return NULL;
return entries[pos];
}
static void *pi_next(struct seq_file *s, void *v, loff_t *pos)
{
const struct module *mod = s->file->f_inode->i_private;
struct pi_entry *entry = pi_get_entry(mod, *pos);
(*pos)++;
return entry;
}
static void *pi_start(struct seq_file *s, loff_t *pos)
{
/*
* Make show() print the header line. Do not update *pos because
* pi_next() still has to return the entry at index 0 later.
*/
if (*pos == 0)
return SEQ_START_TOKEN;
return pi_next(s, NULL, pos);
}
/*
* We need both ESCAPE_ANY and explicit characters from ESCAPE_SPECIAL in @only
* because otherwise ESCAPE_NAP will cause double quotes and backslashes to be
* ignored for quoting.
*/
#define seq_escape_printf_format(s, src) \
seq_escape_str(s, src, ESCAPE_ANY | ESCAPE_NAP | ESCAPE_APPEND, "\"\\")
static int pi_show(struct seq_file *s, void *v)
{
const struct pi_entry *entry = v;
int level = LOGLEVEL_DEFAULT;
enum printk_info_flags flags = 0;
u16 prefix_len = 0;
if (v == SEQ_START_TOKEN) {
seq_puts(s, "# <level/flags> filename:line function \"format\"\n");
return 0;
}
if (!entry->fmt)
return 0;
if (entry->level)
printk_parse_prefix(entry->level, &level, &flags);
else
prefix_len = printk_parse_prefix(entry->fmt, &level, &flags);
if (flags & LOG_CONT) {
/*
* LOGLEVEL_DEFAULT here means "use the same level as the
* message we're continuing from", not the default message
* loglevel, so don't display it as such.
*/
if (level == LOGLEVEL_DEFAULT)
seq_puts(s, "<c>");
else
seq_printf(s, "<%d,c>", level);
} else
seq_printf(s, "<%d>", level);
seq_printf(s, " %s:%d %s \"", entry->file, entry->line, entry->func);
if (entry->subsys_fmt_prefix)
seq_escape_printf_format(s, entry->subsys_fmt_prefix);
seq_escape_printf_format(s, entry->fmt + prefix_len);
seq_puts(s, "\"\n");
return 0;
}
static void pi_stop(struct seq_file *p, void *v) { }
static const struct seq_operations dfs_index_sops = {
.start = pi_start,
.next = pi_next,
.show = pi_show,
.stop = pi_stop,
};
DEFINE_SEQ_ATTRIBUTE(dfs_index);
#ifdef CONFIG_MODULES
static const char *pi_get_module_name(struct module *mod)
{
return mod ? mod->name : "vmlinux";
}
#else
static const char *pi_get_module_name(struct module *mod)
{
return "vmlinux";
}
#endif
static void pi_create_file(struct module *mod)
{
debugfs_create_file(pi_get_module_name(mod), 0444, dfs_index,
mod, &dfs_index_fops);
}
#ifdef CONFIG_MODULES
static void pi_remove_file(struct module *mod)
{
debugfs_remove(debugfs_lookup(pi_get_module_name(mod), dfs_index));
}
static int pi_module_notify(struct notifier_block *nb, unsigned long op,
void *data)
{
struct module *mod = data;
switch (op) {
case MODULE_STATE_COMING:
pi_create_file(mod);
break;
case MODULE_STATE_GOING:
pi_remove_file(mod);
break;
default: /* we don't care about other module states */
break;
}
return NOTIFY_OK;
}
static struct notifier_block module_printk_fmts_nb = {
.notifier_call = pi_module_notify,
};
static void __init pi_setup_module_notifier(void)
{
register_module_notifier(&module_printk_fmts_nb);
}
#else
static inline void __init pi_setup_module_notifier(void) { }
#endif
static int __init pi_init(void)
{
struct dentry *dfs_root = debugfs_create_dir("printk", NULL);
dfs_index = debugfs_create_dir("index", dfs_root);
pi_setup_module_notifier();
pi_create_file(NULL);
return 0;
}
/* debugfs comes up on core and must be initialised first */
postcore_initcall(pi_init);
......@@ -6,11 +6,11 @@
#ifdef CONFIG_PRINTK
#define PRINTK_SAFE_CONTEXT_MASK 0x007ffffff
#define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x008000000
#define PRINTK_NMI_CONTEXT_MASK 0xff0000000
#define PRINTK_NMI_CONTEXT_OFFSET 0x010000000
/* Flags for a single printk record. */
enum printk_info_flags {
LOG_NEWLINE = 2, /* text ended with a newline */
LOG_CONT = 8, /* text is a fragment of a continuation line */
};
__printf(4, 0)
int vprintk_store(int facility, int level,
......@@ -19,10 +19,7 @@ int vprintk_store(int facility, int level,
__printf(1, 0) int vprintk_default(const char *fmt, va_list args);
__printf(1, 0) int vprintk_deferred(const char *fmt, va_list args);
void __printk_safe_enter(void);
void __printk_safe_exit(void);
void printk_safe_init(void);
bool printk_percpu_data_ready(void);
#define printk_safe_enter_irqsave(flags) \
......@@ -37,20 +34,10 @@ bool printk_percpu_data_ready(void);
local_irq_restore(flags); \
} while (0)
#define printk_safe_enter_irq() \
do { \
local_irq_disable(); \
__printk_safe_enter(); \
} while (0)
#define printk_safe_exit_irq() \
do { \
__printk_safe_exit(); \
local_irq_enable(); \
} while (0)
void defer_console_output(void);
u16 printk_parse_prefix(const char *text, int *level,
enum printk_info_flags *flags);
#else
/*
......@@ -61,9 +48,5 @@ void defer_console_output(void);
#define printk_safe_enter_irqsave(flags) local_irq_save(flags)
#define printk_safe_exit_irqrestore(flags) local_irq_restore(flags)
#define printk_safe_enter_irq() local_irq_disable()
#define printk_safe_exit_irq() local_irq_enable()
static inline void printk_safe_init(void) { }
static inline bool printk_percpu_data_ready(void) { return false; }
#endif /* CONFIG_PRINTK */
This diff is collapsed.
This diff is collapsed.
......@@ -9815,7 +9815,6 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
tracing_off();
local_irq_save(flags);
printk_nmi_direct_enter();
/* Simulate the iterator */
trace_init_global_iter(&iter);
......@@ -9897,7 +9896,6 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
atomic_dec(&per_cpu_ptr(iter.array_buffer->data, cpu)->disabled);
}
atomic_dec(&dump_running);
printk_nmi_direct_exit();
local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(ftrace_dump);
......
......@@ -75,12 +75,6 @@ void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,
touch_softlockup_watchdog();
}
/*
* Force flush any remote buffers that might be stuck in IRQ context
* and therefore could not run their irq_work.
*/
printk_safe_flush();
clear_bit_unlock(0, &backtrace_flag);
put_cpu();
}
......@@ -92,8 +86,14 @@ module_param(backtrace_idle, bool, 0644);
bool nmi_cpu_backtrace(struct pt_regs *regs)
{
int cpu = smp_processor_id();
unsigned long flags;
if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) {
/*
* Allow nested NMI backtraces while serializing
* against other CPUs.
*/
printk_cpu_lock_irqsave(flags);
if (!READ_ONCE(backtrace_idle) && regs && cpu_in_idle(instruction_pointer(regs))) {
pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n",
cpu, (void *)instruction_pointer(regs));
......@@ -104,6 +104,7 @@ bool nmi_cpu_backtrace(struct pt_regs *regs)
else
dump_stack();
}
printk_cpu_unlock_irqrestore(flags);
cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
return true;
}
......
......@@ -361,6 +361,9 @@ static bool escape_special(unsigned char c, char **dst, char *end)
case '\e':
to = 'e';
break;
case '"':
to = '"';
break;
default:
return false;
}
......@@ -474,6 +477,7 @@ static bool escape_hex(unsigned char c, char **dst, char *end)
* '\t' - horizontal tab
* '\v' - vertical tab
* %ESCAPE_SPECIAL:
* '\"' - double quote
* '\\' - backslash
* '\a' - alert (BEL)
* '\e' - escape
......
......@@ -140,13 +140,13 @@ static const struct test_string_2 escape0[] __initconst = {{
},{
.in = "\\h\\\"\a\e\\",
.s1 = {{
.out = "\\\\h\\\\\"\\a\\e\\\\",
.out = "\\\\h\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL,
},{
.out = "\\\\\\150\\\\\\042\\a\\e\\\\",
.out = "\\\\\\150\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
.out = "\\\\\\x68\\\\\\x22\\a\\e\\\\",
.out = "\\\\\\x68\\\\\\\"\\a\\e\\\\",
.flags = ESCAPE_SPECIAL | ESCAPE_HEX,
},{
/* terminator */
......@@ -157,10 +157,10 @@ static const struct test_string_2 escape0[] __initconst = {{
.out = "\eb \\C\007\"\x90\\r]",
.flags = ESCAPE_SPACE,
},{
.out = "\\eb \\\\C\\a\"\x90\r]",
.out = "\\eb \\\\C\\a\\\"\x90\r]",
.flags = ESCAPE_SPECIAL,
},{
.out = "\\eb \\\\C\\a\"\x90\\r]",
.out = "\\eb \\\\C\\a\\\"\x90\\r]",
.flags = ESCAPE_SPACE | ESCAPE_SPECIAL,
},{
.out = "\\033\\142\\040\\134\\103\\007\\042\\220\\015\\135",
......@@ -169,10 +169,10 @@ static const struct test_string_2 escape0[] __initconst = {{
.out = "\\033\\142\\040\\134\\103\\007\\042\\220\\r\\135",
.flags = ESCAPE_SPACE | ESCAPE_OCTAL,
},{
.out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\015\\135",
.out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\015\\135",
.flags = ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
.out = "\\e\\142\\040\\\\\\103\\a\\042\\220\\r\\135",
.out = "\\e\\142\\040\\\\\\103\\a\\\"\\220\\r\\135",
.flags = ESCAPE_SPACE | ESCAPE_SPECIAL | ESCAPE_OCTAL,
},{
.out = "\eb \\C\007\"\x90\r]",
......
......@@ -271,7 +271,7 @@ static u32 __init next_test_random(u32 max_bits)
{
u32 n_bits = hweight32(prandom_u32_state(&rnd_state)) % (max_bits + 1);
return prandom_u32_state(&rnd_state) & (UINT_MAX >> (32 - n_bits));
return prandom_u32_state(&rnd_state) & GENMASK(n_bits, 0);
}
static unsigned long long __init next_test_random_ull(void)
......@@ -280,7 +280,7 @@ static unsigned long long __init next_test_random_ull(void)
u32 n_bits = (hweight32(rand1) * 3) % 64;
u64 val = (u64)prandom_u32_state(&rnd_state) * rand1;
return val & (ULLONG_MAX >> (64 - n_bits));
return val & GENMASK_ULL(n_bits, 0);
}
#define random_for_type(T) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment