From ce0b4910bdf8c515fe8be49a6c582ee8b206ca0a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:04 +0200 Subject: lib/vsprintf: Make dec_spec global There are places where default specification to print decimal numbers is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-2-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7a708f82559..8f29af063d8a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -693,6 +693,11 @@ char *symbol_string(char *buf, char *end, void *ptr, #endif } +static const struct printf_spec default_dec_spec = { + .base = 10, + .precision = -1, +}; + static noinline_for_stack char *resource_string(char *buf, char *end, struct resource *res, struct printf_spec spec, const char *fmt) @@ -722,11 +727,6 @@ char *resource_string(char *buf, char *end, struct resource *res, .precision = -1, .flags = SMALL | ZEROPAD, }; - static const struct printf_spec dec_spec = { - .base = 10, - .precision = -1, - .flags = 0, - }; static const struct printf_spec str_spec = { .field_width = -1, .precision = 10, @@ -760,10 +760,10 @@ char *resource_string(char *buf, char *end, struct resource *res, specp = &mem_spec; } else if (res->flags & IORESOURCE_IRQ) { p = string(p, pend, "irq ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_DMA) { p = string(p, pend, "dma ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_BUS) { p = string(p, pend, "bus ", str_spec); specp = &bus_spec; @@ -903,9 +903,6 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, int cur, rbot, rtop; bool first = true; - /* reused to print numbers */ - spec = (struct printf_spec){ .base = 10 }; - rbot = cur = find_first_bit(bitmap, nr_bits); while (cur < nr_bits) { rtop = cur; @@ -920,13 +917,13 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, } first = false; - buf = number(buf, end, rbot, spec); + buf = number(buf, end, rbot, default_dec_spec); if (rbot < rtop) { if (buf < end) *buf = '-'; buf++; - buf = number(buf, end, rtop, spec); + buf = number(buf, end, rtop, default_dec_spec); } rbot = cur; -- cgit v1.2.3 From abd4fe6276fa1111453f96cefa7145b6d15868ca Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:05 +0200 Subject: lib/vsprintf: Make strspec global There are places where default specification to print strings is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-3-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 8f29af063d8a..0c23b006b495 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -693,6 +693,11 @@ char *symbol_string(char *buf, char *end, void *ptr, #endif } +static const struct printf_spec default_str_spec = { + .field_width = -1, + .precision = -1, +}; + static const struct printf_spec default_dec_spec = { .base = 10, .precision = -1, @@ -1461,10 +1466,6 @@ char *format_flags(char *buf, char *end, unsigned long flags, const struct trace_print_flags *names) { unsigned long mask; - const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; const struct printf_spec numspec = { .flags = SPECIAL|SMALL, .field_width = -1, @@ -1477,7 +1478,7 @@ char *format_flags(char *buf, char *end, unsigned long flags, if ((flags & mask) != mask) continue; - buf = string(buf, end, names->name, strspec); + buf = string(buf, end, names->name, default_str_spec); flags &= ~mask; if (flags) { @@ -1535,22 +1536,18 @@ char *device_node_gen_full_name(const struct device_node *np, char *buf, char *e { int depth; const struct device_node *parent = np->parent; - static const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; /* special case for root node */ if (!parent) - return string(buf, end, "/", strspec); + return string(buf, end, "/", default_str_spec); for (depth = 0; parent->parent; depth++) parent = parent->parent; for ( ; depth >= 0; depth--) { - buf = string(buf, end, "/", strspec); + buf = string(buf, end, "/", default_str_spec); buf = string(buf, end, device_node_name_for_depth(np, depth), - strspec); + default_str_spec); } return buf; } -- cgit v1.2.3 From 544339730844674058e772084948cfcc9e62a3c5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:06 +0200 Subject: lib/vsprintf: Make flag_spec global There are places where default specification to print flags as number is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-4-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 0c23b006b495..c789d265311b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -698,6 +698,12 @@ static const struct printf_spec default_str_spec = { .precision = -1, }; +static const struct printf_spec default_flag_spec = { + .base = 16, + .precision = -1, + .flags = SPECIAL | SMALL, +}; + static const struct printf_spec default_dec_spec = { .base = 10, .precision = -1, @@ -737,11 +743,6 @@ char *resource_string(char *buf, char *end, struct resource *res, .precision = 10, .flags = LEFT, }; - static const struct printf_spec flag_spec = { - .base = 16, - .precision = -1, - .flags = SPECIAL | SMALL, - }; /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8) * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ @@ -798,7 +799,7 @@ char *resource_string(char *buf, char *end, struct resource *res, p = string(p, pend, " disabled", str_spec); } else { p = string(p, pend, " flags ", str_spec); - p = number(p, pend, res->flags, flag_spec); + p = number(p, pend, res->flags, default_flag_spec); } *p++ = ']'; *p = '\0'; @@ -1466,12 +1467,6 @@ char *format_flags(char *buf, char *end, unsigned long flags, const struct trace_print_flags *names) { unsigned long mask; - const struct printf_spec numspec = { - .flags = SPECIAL|SMALL, - .field_width = -1, - .precision = -1, - .base = 16, - }; for ( ; flags && names->name; names++) { mask = names->mask; @@ -1489,7 +1484,7 @@ char *format_flags(char *buf, char *end, unsigned long flags, } if (flags) - buf = number(buf, end, flags, numspec); + buf = number(buf, end, flags, default_flag_spec); return buf; } -- cgit v1.2.3 From 558594f3c2a5cd65f18b976faf68143c502b73b2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:07 +0200 Subject: lib/vsprintf: Move pointer_string() upper As preparatory patch to further clean up. No functional change. Link: http://lkml.kernel.org/r/20180216210711.79901-5-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c789d265311b..87dbced51b1a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1347,6 +1347,20 @@ char *uuid_string(char *buf, char *end, const u8 *addr, return string(buf, end, uuid, spec); } +static noinline_for_stack +char *pointer_string(char *buf, char *end, const void *ptr, + struct printf_spec spec) +{ + spec.base = 16; + spec.flags |= SMALL; + if (spec.field_width == -1) { + spec.field_width = 2 * sizeof(ptr); + spec.flags |= ZEROPAD; + } + + return number(buf, end, (unsigned long int)ptr, spec); +} + int kptr_restrict __read_mostly; static noinline_for_stack @@ -1634,20 +1648,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, return widen_string(buf, buf - buf_start, end, spec); } -static noinline_for_stack -char *pointer_string(char *buf, char *end, const void *ptr, - struct printf_spec spec) -{ - spec.base = 16; - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = 2 * sizeof(ptr); - spec.flags |= ZEROPAD; - } - - return number(buf, end, (unsigned long int)ptr, spec); -} - static bool have_filled_random_ptr_key __read_mostly; static siphash_key_t ptr_key __read_mostly; -- cgit v1.2.3 From 496a9a5f3806d58b14ae06b390d5b1ffa26e9f9a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:08 +0200 Subject: lib/vsprintf: Deduplicate pointer_string() There is an exact code at the end of ptr_to_id(). Replace it by calling pointer_string() directly. This is followup to the commit ad67b74d2469 ("printk: hash addresses printed with %p"). Cc: Tobin C. Harding Link: http://lkml.kernel.org/r/20180216210711.79901-6-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 87dbced51b1a..9004bbb3d84d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1367,13 +1367,6 @@ static noinline_for_stack char *restricted_pointer(char *buf, char *end, const void *ptr, struct printf_spec spec) { - spec.base = 16; - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = 2 * sizeof(ptr); - spec.flags |= ZEROPAD; - } - switch (kptr_restrict) { case 0: /* Always print %pK values */ @@ -1385,8 +1378,11 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, * kptr_restrict==1 cannot be used in IRQ context * because its test for CAP_SYSLOG would be meaningless. */ - if (in_irq() || in_serving_softirq() || in_nmi()) + if (in_irq() || in_serving_softirq() || in_nmi()) { + if (spec.field_width == -1) + spec.field_width = 2 * sizeof(ptr); return string(buf, end, "pK-error", spec); + } /* * Only print the real pointer value if the current @@ -1411,7 +1407,7 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, break; } - return number(buf, end, (unsigned long)ptr, spec); + return pointer_string(buf, end, ptr, spec); } static noinline_for_stack @@ -1686,10 +1682,9 @@ early_initcall(initialize_ptr_random); static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) { unsigned long hashval; - const int default_width = 2 * sizeof(ptr); if (unlikely(!have_filled_random_ptr_key)) { - spec.field_width = default_width; + spec.field_width = 2 * sizeof(ptr); /* string length must be less than default_width */ return string(buf, end, "(ptrval)", spec); } @@ -1704,15 +1699,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) #else hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); #endif - - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = default_width; - spec.flags |= ZEROPAD; - } - spec.base = 16; - - return number(buf, end, hashval, spec); + return pointer_string(buf, end, (const void *)hashval, spec); } /* -- cgit v1.2.3 From 91efafb1dd8f471177a3dddb4841d75d3df1cc46 Mon Sep 17 00:00:00 2001 From: Shunyong Yang Date: Fri, 16 Feb 2018 23:07:09 +0200 Subject: lib/vsprintf: Replace space with '_' before crng is ready Before crng is ready, output of "%p" composes of "(ptrval)" and left padding spaces for alignment as no random address can be generated. This seems a little strange when default string width is larger than strlen("(ptrval)"). For example, when irq domain names are built with "%p", the nodes under /sys/kernel/debug/irq/domains like this on AArch64 system, [root@y irq]# ls domains/ default irqchip@ (ptrval)-2 irqchip@ (ptrval)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@ (ptrval) irqchip@ (ptrval)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 The name "irqchip@ (ptrval)-2" is not so readable in console output. This patch replaces space with readable "_" when output needs padding. Following is the output after applying the patch, [root@y domains]# ls default irqchip@(____ptrval____)-2 irqchip@(____ptrval____)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@(____ptrval____) irqchip@(____ptrval____)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 There is same problem in some subsystem's dmesg output. Moreover, someone may call "%p" in a similar case. In addition, the timing of crng initialization done may vary on different system. So, the change is made in vsprintf.c. Suggested-by: Rasmus Villemoes Link: http://lkml.kernel.org/r/20180216210711.79901-7-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Cc: Joey Zheng Signed-off-by: Shunyong Yang Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 9004bbb3d84d..97be2d07297a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1681,12 +1681,13 @@ early_initcall(initialize_ptr_random); /* Maps a pointer to a 32 bit unique identifier. */ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) { + const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; unsigned long hashval; if (unlikely(!have_filled_random_ptr_key)) { spec.field_width = 2 * sizeof(ptr); /* string length must be less than default_width */ - return string(buf, end, "(ptrval)", spec); + return string(buf, end, str, spec); } #ifdef CONFIG_64BIT -- cgit v1.2.3 From 7e6bd6f3dcf913460a0a0ae7f260a8280001dd80 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:11 +0200 Subject: lib/vsprintf: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Link: http://lkml.kernel.org/r/20180216210711.79901-9-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 97be2d07297a..38a71df48d48 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2092,6 +2092,7 @@ qualifier: case 'x': spec->flags |= SMALL; + /* fall through */ case 'X': spec->base = 16; @@ -3046,8 +3047,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; case 'i': base = 0; + /* fall through */ case 'd': is_sign = true; + /* fall through */ case 'u': break; case '%': -- cgit v1.2.3 From cdb7e52d960a59f30de853f5dd85574432d6bb50 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Sat, 14 Apr 2018 12:00:05 +0900 Subject: vsprintf: Tweak pF/pf comment Reflect changes that have happened to pf/pF (deprecation) specifiers in pointer() comment section. Link: http://lkml.kernel.org/r/20180414030005.25831-1-sergey.senozhatsky@gmail.com Cc: Steven Rostedt Cc: Andrew Morton Cc: Joe Perches Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- lib/vsprintf.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 38a71df48d48..7649ef4ed7d0 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1713,10 +1713,10 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * * Right now we handle: * - * - 'F' For symbolic function descriptor pointers with offset - * - 'f' For simple symbolic function names without offset - * - 'S' For symbolic direct pointers with offset - * - 's' For symbolic direct pointers without offset + * - 'S' For symbolic direct pointers (or function descriptors) with offset + * - 's' For symbolic direct pointers (or function descriptors) without offset + * - 'F' Same as 'S' + * - 'f' Same as 's' * - '[FfSs]R' as above with __builtin_extract_return_addr() translation * - 'B' For backtraced symbolic direct pointers with offset * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] @@ -1813,10 +1813,6 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * ** When making changes please also update: * Documentation/core-api/printk-formats.rst * - * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 - * function pointers are really function descriptors, which contain a - * pointer to the real address. - * * Note: The default behaviour (unadorned %p) is to hash the address, * rendering it useful as a unique identifier. */ -- cgit v1.2.3 From 666902e42fd8344b923c02dc5b0f37948ff4f225 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:22 +0200 Subject: lib/vsprintf: Remove atomic-unsafe support for %pCr "%pCr" formats the current rate of a clock, and calls clk_get_rate(). The latter obtains a mutex, hence it must not be called from atomic context. Remove support for this rarely-used format, as vsprintf() (and e.g. printk()) must be callable from any context. Any remaining out-of-tree users will start seeing the clock's name printed instead of its rate. Reported-by: Jia-Ju Bai Fixes: 900cca2944254edd ("lib/vsprintf: add %pC{,n,r} format specifiers for clocks") Link: http://lkml.kernel.org/r/1527845302-12159-5-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.1+ Signed-off-by: Geert Uytterhoeven Signed-off-by: Petr Mladek --- Documentation/core-api/printk-formats.rst | 3 +-- lib/vsprintf.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'lib/vsprintf.c') diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index eb30efdd2e78..25dc591cb110 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -419,11 +419,10 @@ struct clk %pC pll1 %pCn pll1 - %pCr 1560000000 For printing struct clk structures. %pC and %pCn print the name (Common Clock Framework) or address (legacy clock framework) of the -structure; %pCr prints the current clock rate. +structure. Passed by reference. diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7a708f82559..8f28036f5c1d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1446,9 +1446,6 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, return string(buf, end, NULL, spec); switch (fmt[1]) { - case 'r': - return number(buf, end, clk_get_rate(clk), spec); - case 'n': default: #ifdef CONFIG_COMMON_CLK -- cgit v1.2.3