Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/pmladek/printk

Pull printk updates from Petr Mladek:

 - Add a console_msg_format command line option:

     The value "default" keeps the old "[time stamp] text\n" format. The
     value "syslog" allows to see the syslog-like "<log
     level>[timestamp] text" format.

     This feature was requested by people doing regression tests, for
     example, 0day robot. They want to have both filtered and full logs
     at hands.

 - Reduce the risk of softlockup:

     Pass the console owner in a busy loop.

     This is a new approach to the old problem. It was first proposed by
     Steven Rostedt on Kernel Summit 2017. It marks a context in which
     the console_lock owner calls console drivers and could not sleep.
     On the other side, printk() callers could detect this state and use
     a busy wait instead of a simple console_trylock(). Finally, the
     console_lock owner checks if there is a busy waiter at the end of
     the special context and eventually passes the console_lock to the
     waiter.

     The hand-off works surprisingly well and helps in many situations.
     Well, there is still a possibility of the softlockup, for example,
     when the flood of messages stops and the last owner still has too
     much to flush.

     There is increasing number of people having problems with
     printk-related softlockups. We might eventually need to get better
     solution. Anyway, this looks like a good start and promising
     direction.

 - Do not allow to schedule in console_unlock() called from printk():

     This reverts an older controversial commit. The reschedule helped
     to avoid softlockups. But it also slowed down the console output.
     This patch is obsoleted by the new console waiter logic described
     above. In fact, the reschedule made the hand-off less effective.

 - Deprecate "%pf" and "%pF" format specifier:

     It was needed on ia64, ppc64 and parisc64 to dereference function
     descriptors and show the real function address. It is done
     transparently by "%ps" and "pS" format specifier now.

     Sergey Senozhatsky found that all the function descriptors were in
     a special elf section and could be easily detected.

 - Remove printk_symbol() API:

     It has been obsoleted by "%pS" format specifier, and this change
     helped to remove few continuous lines and a less intuitive old API.

 - Remove redundant memsets:

     Sergey removed unnecessary memset when processing printk.devkmsg
     command line option.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk: (27 commits)
  printk: drop redundant devkmsg_log_str memsets
  printk: Never set console_may_schedule in console_trylock()
  printk: Hide console waiter logic into helpers
  printk: Add console owner and waiter logic to load balance console writes
  kallsyms: remove print_symbol() function
  checkpatch: add pF/pf deprecation warning
  symbol lookup: introduce dereference_symbol_descriptor()
  parisc64: Add .opd based function descriptor dereference
  powerpc64: Add .opd based function descriptor dereference
  ia64: Add .opd based function descriptor dereference
  sections: split dereference_function_descriptor()
  openrisc: Fix conflicting types for _exext and _stext
  lib: do not use print_symbol()
  irq debug: do not use print_symbol()
  sysfs: do not use print_symbol()
  drivers: do not use print_symbol()
  x86: do not use print_symbol()
  unicore32: do not use print_symbol()
  sh: do not use print_symbol()
  mn10300: do not use print_symbol()
  ...
  • Loading branch information
torvalds committed Feb 1, 2018
2 parents 34b1cf6 + bb4f552 commit ab486bc
Show file tree
Hide file tree
Showing 39 changed files with 428 additions and 172 deletions.
14 changes: 14 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,20 @@
console=brl,ttyS0
For now, only VisioBraille is supported.

console_msg_format=
[KNL] Change console messages format
default
By default we print messages on consoles in
"[time stamp] text\n" format (time stamp may not be
printed, depending on CONFIG_PRINTK_TIME or
`printk_time' param).
syslog
Switch to syslog format: "<%u>[time stamp] text\n"
IOW, each message will have a facility and loglevel
prefix. The format is similar to one used by syslog()
syscall, or to executing "dmesg -S --raw" or to reading
from /proc/kmsg.

consoleblank= [KNL] The console blank (screen saver) timeout in
seconds. A value of 0 disables the blank timer.
Defaults to 0.
Expand Down
34 changes: 12 additions & 22 deletions Documentation/core-api/printk-formats.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,42 +68,32 @@ Symbols/Function Pointers

::

%pS versatile_init+0x0/0x110
%ps versatile_init
%pF versatile_init+0x0/0x110
%pf versatile_init
%pS versatile_init+0x0/0x110
%pSR versatile_init+0x9/0x110
(with __builtin_extract_return_addr() translation)
%ps versatile_init
%pB prev_fn_of_versatile_init+0x88/0x88


The ``F`` and ``f`` specifiers are for printing function pointers,
for example, f->func, &gettimeofday. They have the same result as
``S`` and ``s`` specifiers. But they do an extra conversion on
ia64, ppc64 and parisc64 architectures where the function pointers
are actually function descriptors.
The ``S`` and ``s`` specifiers are used for printing a pointer in symbolic
format. They result in the symbol name with (S) or without (s)
offsets. If KALLSYMS are disabled then the symbol address is printed instead.

The ``S`` and ``s`` specifiers can be used for printing symbols
from direct addresses, for example, __builtin_return_address(0),
(void *)regs->ip. They result in the symbol name with (S) or
without (s) offsets. If KALLSYMS are disabled then the symbol
address is printed instead.
Note, that the ``F`` and ``f`` specifiers are identical to ``S`` (``s``)
and thus deprecated. We have ``F`` and ``f`` because on ia64, ppc64 and
parisc64 function pointers are indirect and, in fact, are function
descriptors, which require additional dereferencing before we can lookup
the symbol. As of now, ``S`` and ``s`` perform dereferencing on those
platforms (when needed), so ``F`` and ``f`` exist for compatibility
reasons only.

The ``B`` specifier results in the symbol name with offsets and should be
used when printing stack backtraces. The specifier takes into
consideration the effect of compiler optimisations which may occur
when tail-calls are used and marked with the noreturn GCC attribute.

Examples::

printk("Going to call: %pF\n", gettimeofday);
printk("Going to call: %pF\n", p->func);
printk("%s: called from %pS\n", __func__, (void *)_RET_IP_);
printk("%s: called from %pS\n", __func__,
(void *)__builtin_return_address(0));
printk("Faulted at %pS\n", (void *)regs->ip);
printk(" %s%pB\n", (reliable ? "" : "? "), (void *)*stack);

Kernel Pointers
---------------

Expand Down
4 changes: 2 additions & 2 deletions Documentation/filesystems/sysfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
if (dev_attr->show)
ret = dev_attr->show(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
print_symbol("dev_attr_show: %s returned bad count\n",
(unsigned long)dev_attr->show);
printk("dev_attr_show: %pS returned bad count\n",
dev_attr->show);
}
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions Documentation/translations/zh_CN/filesystems/sysfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
if (dev_attr->show)
ret = dev_attr->show(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
print_symbol("dev_attr_show: %s returned bad count\n",
(unsigned long)dev_attr->show);
printk("dev_attr_show: %pS returned bad count\n",
dev_attr->show);
}
return ret;
}
Expand Down
5 changes: 2 additions & 3 deletions arch/arm/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <linux/unistd.h>
#include <linux/user.h>
#include <linux/interrupt.h>
#include <linux/kallsyms.h>
#include <linux/init.h>
#include <linux/elfcore.h>
#include <linux/pm.h>
Expand Down Expand Up @@ -121,8 +120,8 @@ void __show_regs(struct pt_regs *regs)

show_regs_print_info(KERN_DEFAULT);

print_symbol("PC is at %s\n", instruction_pointer(regs));
print_symbol("LR is at %s\n", regs->ARM_lr);
printk("PC is at %pS\n", (void *)instruction_pointer(regs));
printk("LR is at %pS\n", (void *)regs->ARM_lr);
printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n",
regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr);
printk("sp : %08lx ip : %08lx fp : %08lx\n",
Expand Down
5 changes: 2 additions & 3 deletions arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/kallsyms.h>
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/elfcore.h>
Expand Down Expand Up @@ -221,8 +220,8 @@ void __show_regs(struct pt_regs *regs)

show_regs_print_info(KERN_DEFAULT);
print_pstate(regs);
print_symbol("pc : %s\n", regs->pc);
print_symbol("lr : %s\n", lr);
printk("pc : %pS\n", (void *)regs->pc);
printk("lr : %pS\n", (void *)lr);
printk("sp : %016llx\n", sp);

i = top_reg;
Expand Down
4 changes: 1 addition & 3 deletions arch/c6x/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/ptrace.h>
#include <linux/sched/debug.h>
#include <linux/kallsyms.h>
#include <linux/bug.h>

#include <asm/soc.h>
Expand Down Expand Up @@ -375,8 +374,7 @@ static void show_trace(unsigned long *stack, unsigned long *endstack)
if (i % 5 == 0)
pr_debug("\n ");
#endif
pr_debug(" [<%08lx>]", addr);
print_symbol(" %s\n", addr);
pr_debug(" [<%08lx>] %pS\n", addr, (void *)addr);
i++;
}
}
Expand Down
10 changes: 9 additions & 1 deletion arch/ia64/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_b
extern char __start_unwind[], __end_unwind[];
extern char __start_ivt_text[], __end_ivt_text[];

#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1

#undef dereference_function_descriptor
static inline void *dereference_function_descriptor(void *ptr)
{
Expand All @@ -38,6 +40,12 @@ static inline void *dereference_function_descriptor(void *ptr)
return ptr;
}

#undef dereference_kernel_function_descriptor
static inline void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
return ptr;
return dereference_function_descriptor(ptr);
}

#endif /* _ASM_IA64_SECTIONS_H */

12 changes: 12 additions & 0 deletions arch/ia64/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include <asm/patch.h>
#include <asm/unaligned.h>
#include <asm/sections.h>

#define ARCH_MODULE_DEBUG 0

Expand Down Expand Up @@ -918,3 +919,14 @@ module_arch_cleanup (struct module *mod)
if (mod->arch.core_unw_table)
unw_remove_unwind_table(mod->arch.core_unw_table);
}

void *dereference_module_function_descriptor(struct module *mod, void *ptr)
{
Elf64_Shdr *opd = mod->arch.opd;

if (ptr < (void *)opd->sh_addr ||
ptr >= (void *)(opd->sh_addr + opd->sh_size))
return ptr;

return dereference_function_descriptor(ptr);
}
10 changes: 3 additions & 7 deletions arch/ia64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <linux/pm.h>
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -69,7 +68,6 @@ void
ia64_do_show_stack (struct unw_frame_info *info, void *arg)
{
unsigned long ip, sp, bsp;
char buf[128]; /* don't make it so big that it overflows the stack! */

printk("\nCall Trace:\n");
do {
Expand All @@ -79,11 +77,9 @@ ia64_do_show_stack (struct unw_frame_info *info, void *arg)

unw_get_sp(info, &sp);
unw_get_bsp(info, &bsp);
snprintf(buf, sizeof(buf),
" [<%016lx>] %%s\n"
printk(" [<%016lx>] %pS\n"
" sp=%016lx bsp=%016lx\n",
ip, sp, bsp);
print_symbol(buf, ip);
ip, (void *)ip, sp, bsp);
} while (unw_unwind(info) >= 0);
}

Expand Down Expand Up @@ -111,7 +107,7 @@ show_regs (struct pt_regs *regs)
printk("psr : %016lx ifs : %016lx ip : [<%016lx>] %s (%s)\n",
regs->cr_ipsr, regs->cr_ifs, ip, print_tainted(),
init_utsname()->release);
print_symbol("ip is at %s\n", ip);
printk("ip is at %pS\n", (void *)ip);
printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
printk("rnat: %016lx bsps: %016lx pr : %016lx\n",
Expand Down
2 changes: 2 additions & 0 deletions arch/ia64/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ SECTIONS {
RODATA

.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
__start_opd = .;
*(.opd)
__end_opd = .;
}

/*
Expand Down
4 changes: 1 addition & 3 deletions arch/mn10300/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/kallsyms.h>
#include <linux/pci.h>
#include <linux/kdebug.h>
#include <linux/bug.h>
Expand Down Expand Up @@ -262,8 +261,7 @@ void show_trace(unsigned long *sp)
raslot = ULONG_MAX;
else
printk(" ?");
print_symbol(" %s", addr);
printk("\n");
printk(" %pS\n", (void *)addr);
}
}

Expand Down
3 changes: 1 addition & 2 deletions arch/openrisc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/unwinder.h>

extern char _etext, _stext;
#include <asm/sections.h>

int kstack_depth_to_print = 0x180;
int lwa_flag;
Expand Down
2 changes: 2 additions & 0 deletions arch/parisc/boot/compressed/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ SECTIONS
. = ALIGN(16);
/* Linkage tables */
.opd : {
__start_opd = .;
*(.opd)
__end_opd = .;
} PROVIDE (__gp = .);
.plt : {
*(.plt)
Expand Down
6 changes: 6 additions & 0 deletions arch/parisc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@
#include <asm-generic/sections.h>

#ifdef CONFIG_64BIT

#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1

#undef dereference_function_descriptor
void *dereference_function_descriptor(void *);

#undef dereference_kernel_function_descriptor
void *dereference_kernel_function_descriptor(void *);
#endif

#endif
16 changes: 16 additions & 0 deletions arch/parisc/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

#include <asm/pgtable.h>
#include <asm/unwind.h>
#include <asm/sections.h>

#if 0
#define DEBUGP printk
Expand Down Expand Up @@ -954,3 +955,18 @@ void module_arch_cleanup(struct module *mod)
{
deregister_unwind_table(mod);
}

#ifdef CONFIG_64BIT
void *dereference_module_function_descriptor(struct module *mod, void *ptr)
{
unsigned long start_opd = (Elf64_Addr)mod->core_layout.base +
mod->arch.fdesc_offset;
unsigned long end_opd = start_opd +
mod->arch.fdesc_count * sizeof(Elf64_Fdesc);

if (ptr < (void *)start_opd || ptr >= (void *)end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif
9 changes: 9 additions & 0 deletions arch/parisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ void *dereference_function_descriptor(void *ptr)
ptr = p;
return ptr;
}

void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd ||
ptr >= (void *)__end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif

static inline unsigned long brk_rnd(void)
Expand Down
2 changes: 2 additions & 0 deletions arch/parisc/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ SECTIONS
. = ALIGN(16);
/* Linkage tables */
.opd : {
__start_opd = .;
*(.opd)
__end_opd = .;
} PROVIDE (__gp = .);
.plt : {
*(.plt)
Expand Down
3 changes: 3 additions & 0 deletions arch/powerpc/include/asm/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ struct mod_arch_specific {
unsigned long tramp;
#endif

/* For module function descriptor dereference */
unsigned long start_opd;
unsigned long end_opd;
#else /* powerpc64 */
/* Indices of PLT sections within module. */
unsigned int core_plt_section;
Expand Down
12 changes: 12 additions & 0 deletions arch/powerpc/include/asm/sections.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ static inline int overlaps_kvm_tmp(unsigned long start, unsigned long end)
}

#ifdef PPC64_ELF_ABI_v1

#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1

#undef dereference_function_descriptor
static inline void *dereference_function_descriptor(void *ptr)
{
Expand All @@ -76,6 +79,15 @@ static inline void *dereference_function_descriptor(void *ptr)
ptr = p;
return ptr;
}

#undef dereference_kernel_function_descriptor
static inline void *dereference_kernel_function_descriptor(void *ptr)
{
if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
return ptr;

return dereference_function_descriptor(ptr);
}
#endif /* PPC64_ELF_ABI_v1 */

#endif
Expand Down
Loading

0 comments on commit ab486bc

Please sign in to comment.