summaryrefslogtreecommitdiff
path: root/arch/s390/boot/pgm_check_info.c
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2020-11-11 12:59:40 +0300
committerHeiko Carstens <hca@linux.ibm.com>2020-11-20 21:19:11 +0300
commit246218962e2175cd1dfa1e5467e9bffae5cc7b5e (patch)
tree537361b78c16c2f828237416477db73c61c67551 /arch/s390/boot/pgm_check_info.c
parentec55d1e1dbea990145644bd6838c061e8113cc4d (diff)
downloadlinux-246218962e2175cd1dfa1e5467e9bffae5cc7b5e.tar.xz
s390/decompressor: add symbols support
Information printed by print_pgm_check_info() is crucial for debugging decompressor problems. Printing instruction addresses is better than nothing, but turns further debugging into tedious job of figuring out which function those addresses correspond to. This change adds simplistic symbols resolution support. And adds %pS format specifier support to decompressor_printk(). Decompressor symbols list is extracted and sorted with nm -n -S: ... 0000000000010000 0000000000000014 T startup 0000000000010014 00000000000000b0 t startup_normal 0000000000010180 00000000000000b2 t startup_kdump ... Then functions are filtered and contracted to a form: "10000 14 startup\0""10014 b0 startup_normal\0""10180 b2 startup_kdump\0" ... Which makes it trivial to find beginning of an entry and names are 0 terminated, so could be used as is. Symbols are binary-searched. To get symbols list with final addresses and then get it into the decompressor's image the same trick as for kallsyms is used. Decompressor's vmlinux is linked twice. Symbols are stored in .decompressor.syms section, current size is about 2kb. Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/boot/pgm_check_info.c')
-rw-r--r--arch/s390/boot/pgm_check_info.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c
index 829548c22444..8ba8136adb4d 100644
--- a/arch/s390/boot/pgm_check_info.c
+++ b/arch/s390/boot/pgm_check_info.c
@@ -19,6 +19,65 @@ static char *as_hex(char *dst, unsigned long val, int pad)
return end;
}
+static char *symstart(char *p)
+{
+ while (*p)
+ p--;
+ return p + 1;
+}
+
+extern char _decompressor_syms_start[], _decompressor_syms_end[];
+static noinline char *findsym(unsigned long ip, unsigned short *off, unsigned short *len)
+{
+ /* symbol entries are in a form "10000 c4 startup\0" */
+ char *a = _decompressor_syms_start;
+ char *b = _decompressor_syms_end;
+ unsigned long start;
+ unsigned long size;
+ char *pivot;
+ char *endp;
+
+ while (a < b) {
+ pivot = symstart(a + (b - a) / 2);
+ start = simple_strtoull(pivot, &endp, 16);
+ size = simple_strtoull(endp + 1, &endp, 16);
+ if (ip < start) {
+ b = pivot;
+ continue;
+ }
+ if (ip > start + size) {
+ a = pivot + strlen(pivot) + 1;
+ continue;
+ }
+ *off = ip - start;
+ *len = size;
+ return endp + 1;
+ }
+ return NULL;
+}
+
+static noinline char *strsym(void *ip)
+{
+ static char buf[64];
+ unsigned short off;
+ unsigned short len;
+ char *p;
+
+ p = findsym((unsigned long)ip, &off, &len);
+ if (p) {
+ strncpy(buf, p, sizeof(buf));
+ /* reserve 15 bytes for offset/len in symbol+0x1234/0x1234 */
+ p = buf + strnlen(buf, sizeof(buf) - 15);
+ strcpy(p, "+0x");
+ p = as_hex(p + 3, off, 0);
+ strcpy(p, "/0x");
+ as_hex(p + 3, len, 0);
+ } else {
+ as_hex(buf, (unsigned long)ip, 16);
+ }
+ return buf;
+}
+
void decompressor_printk(const char *fmt, ...)
{
char buf[1024] = { 0 };
@@ -38,6 +97,11 @@ void decompressor_printk(const char *fmt, ...)
case 's':
p = buf + strlcat(buf, va_arg(args, char *), sizeof(buf));
break;
+ case 'p':
+ if (*++fmt != 'S')
+ goto out;
+ p = buf + strlcat(buf, strsym(va_arg(args, void *)), sizeof(buf));
+ break;
case 'l':
if (*++fmt != 'x' || end - p <= max(sizeof(long) * 2, pad))
goto out;
@@ -67,9 +131,10 @@ void print_pgm_check_info(void)
S390_lowcore.pgm_code, S390_lowcore.pgm_ilc >> 1);
if (kaslr_enabled)
decompressor_printk("Kernel random base: %lx\n", __kaslr_offset);
- decompressor_printk("PSW : %016lx %016lx\n",
+ decompressor_printk("PSW : %016lx %016lx (%pS)\n",
S390_lowcore.psw_save_area.mask,
- S390_lowcore.psw_save_area.addr);
+ S390_lowcore.psw_save_area.addr,
+ (void *)S390_lowcore.psw_save_area.addr);
decompressor_printk(
" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x P:%x AS:%x CC:%x PM:%x RI:%x EA:%x\n",
psw->per, psw->dat, psw->io, psw->ext, psw->key, psw->mcheck,