Commit 332d2e78 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Implement %pR to print struct resource content



Add a %pR option to the kernel vsnprintf that prints the range of
addresses inside a struct resource passed by pointer.

Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 88e36621
Loading
Loading
Loading
Loading
+43 −6
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/ioport.h>

#include <asm/page.h>		/* for PAGE_SIZE */
#include <asm/div64.h>
@@ -550,18 +551,51 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
#endif
}

static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags)
{
#ifndef IO_RSRC_PRINTK_SIZE
#define IO_RSRC_PRINTK_SIZE	4
#endif

#ifndef MEM_RSRC_PRINTK_SIZE
#define MEM_RSRC_PRINTK_SIZE	8
#endif

	/* room for the actual numbers, the two "0x", -, [, ] and the final zero */
	char sym[4*sizeof(resource_size_t) + 8];
	char *p = sym, *pend = sym + sizeof(sym);
	int size = -1;

	if (res->flags & IORESOURCE_IO)
		size = IO_RSRC_PRINTK_SIZE;
	else if (res->flags & IORESOURCE_MEM)
		size = MEM_RSRC_PRINTK_SIZE;

	*p++ = '[';
	p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
	*p++ = '-';
	p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
	*p++ = ']';
	*p = 0;

	return string(buf, end, sym, field_width, precision, flags);
}

/*
 * Show a '%p' thing.  A kernel extension is that the '%p' is followed
 * by an extra set of alphanumeric characters that are extended format
 * specifiers.
 *
 * Right now we just handle 'F' (for symbolic Function descriptor pointers)
 * and 'S' (for Symbolic direct pointers), but this can easily be
 * extended in the future (network address types etc).
 * Right now we handle:
 *
 * - 'F' For symbolic function descriptor pointers
 * - 'S' For symbolic direct pointers
 * - 'R' For a struct resource pointer, it prints the range of
 *       addresses (not the name nor the flags)
 *
 * The difference between 'S' and 'F' is that on ia64 and ppc64 function
 * pointers are really function descriptors, which contain a pointer the
 * real address. 
 * 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.
 */
static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
{
@@ -571,6 +605,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
		/* Fallthrough */
	case 'S':
		return symbol_string(buf, end, ptr, field_width, precision, flags);
	case 'R':
		return resource_string(buf, end, ptr, field_width, precision, flags);
	}
	flags |= SMALL;
	if (field_width == -1) {
@@ -590,6 +626,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
 * This function follows C99 vsnprintf, but has some extensions:
 * %pS output the name of a text symbol
 * %pF output the name of a function pointer
 * %pR output the address range in a struct resource
 *
 * The return value is the number of characters which would
 * be generated for the given input, excluding the trailing