linux/arch/x86/kernel/dumpstack_64.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1991, 1992  Linus Torvalds
   3 *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
   4 */
   5#include <linux/kallsyms.h>
   6#include <linux/kprobes.h>
   7#include <linux/uaccess.h>
   8#include <linux/hardirq.h>
   9#include <linux/kdebug.h>
  10#include <linux/module.h>
  11#include <linux/ptrace.h>
  12#include <linux/kexec.h>
  13#include <linux/sysfs.h>
  14#include <linux/bug.h>
  15#include <linux/nmi.h>
  16
  17#include <asm/stacktrace.h>
  18
  19static char *exception_stack_names[N_EXCEPTION_STACKS] = {
  20                [ DOUBLEFAULT_STACK-1   ]       = "#DF",
  21                [ NMI_STACK-1           ]       = "NMI",
  22                [ DEBUG_STACK-1         ]       = "#DB",
  23                [ MCE_STACK-1           ]       = "#MC",
  24};
  25
  26static unsigned long exception_stack_sizes[N_EXCEPTION_STACKS] = {
  27        [0 ... N_EXCEPTION_STACKS - 1]          = EXCEPTION_STKSZ,
  28        [DEBUG_STACK - 1]                       = DEBUG_STKSZ
  29};
  30
  31void stack_type_str(enum stack_type type, const char **begin, const char **end)
  32{
  33        BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
  34
  35        switch (type) {
  36        case STACK_TYPE_IRQ:
  37                *begin = "IRQ";
  38                *end   = "EOI";
  39                break;
  40        case STACK_TYPE_EXCEPTION ... STACK_TYPE_EXCEPTION_LAST:
  41                *begin = exception_stack_names[type - STACK_TYPE_EXCEPTION];
  42                *end   = "EOE";
  43                break;
  44        default:
  45                *begin = NULL;
  46                *end   = NULL;
  47        }
  48}
  49
  50static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
  51{
  52        unsigned long *begin, *end;
  53        struct pt_regs *regs;
  54        unsigned k;
  55
  56        BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
  57
  58        for (k = 0; k < N_EXCEPTION_STACKS; k++) {
  59                end   = (unsigned long *)__this_cpu_ptr(&orig_ist)->ist[k];
  60                begin = end - (exception_stack_sizes[k] / sizeof(long));
  61                regs  = (struct pt_regs *)end - 1;
  62
  63                if (stack <= begin || stack >= end)
  64                        continue;
  65
  66                info->type      = STACK_TYPE_EXCEPTION + k;
  67                info->begin     = begin;
  68                info->end       = end;
  69                info->next_sp   = (unsigned long *)regs->sp;
  70
  71                return true;
  72        }
  73
  74        return false;
  75}
  76
  77static bool in_irq_stack(unsigned long *stack, struct stack_info *info)
  78{
  79        unsigned long *end   = (unsigned long *)this_cpu_read(irq_stack_ptr);
  80        unsigned long *begin = end - (IRQ_STACK_SIZE / sizeof(long));
  81
  82        /*
  83         * This is a software stack, so 'end' can be a valid stack pointer.
  84         * It just means the stack is empty.
  85         */
  86        if (stack <= begin || stack > end)
  87                return false;
  88
  89        info->type      = STACK_TYPE_IRQ;
  90        info->begin     = begin;
  91        info->end       = end;
  92
  93        /*
  94         * The next stack pointer is the first thing pushed by the entry code
  95         * after switching to the irq stack.
  96         */
  97        info->next_sp = (unsigned long *)*(end - 1);
  98
  99        return true;
 100}
 101
 102int get_stack_info(unsigned long *stack, struct task_struct *task,
 103                   struct stack_info *info, unsigned long *visit_mask)
 104{
 105        if (!stack)
 106                goto unknown;
 107
 108        task = task ? : current;
 109
 110        if (in_task_stack(stack, task, info))
 111                goto recursion_check;
 112
 113        if (task != current)
 114                goto unknown;
 115
 116        if (in_exception_stack(stack, info))
 117                goto recursion_check;
 118
 119        if (in_irq_stack(stack, info))
 120                goto recursion_check;
 121
 122        goto unknown;
 123
 124recursion_check:
 125        /*
 126         * Make sure we don't iterate through any given stack more than once.
 127         * If it comes up a second time then there's something wrong going on:
 128         * just break out and report an unknown stack type.
 129         */
 130        if (visit_mask) {
 131                if (*visit_mask & (1UL << info->type))
 132                        goto unknown;
 133                *visit_mask |= 1UL << info->type;
 134        }
 135
 136        return 0;
 137
 138unknown:
 139        info->type = STACK_TYPE_UNKNOWN;
 140        return -EINVAL;
 141}
 142
 143void show_regs(struct pt_regs *regs)
 144{
 145        int i;
 146
 147        show_regs_print_info(KERN_DEFAULT);
 148        __show_regs(regs, 1);
 149
 150        /*
 151         * When in-kernel, we also print out the stack and code at the
 152         * time of the fault..
 153         */
 154        if (!user_mode(regs)) {
 155                unsigned int code_prologue = code_bytes * 43 / 64;
 156                unsigned int code_len = code_bytes;
 157                unsigned char c;
 158                u8 *ip;
 159
 160                show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
 161
 162                printk(KERN_DEFAULT "Code: ");
 163
 164                ip = (u8 *)regs->ip - code_prologue;
 165                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
 166                        /* try starting at IP */
 167                        ip = (u8 *)regs->ip;
 168                        code_len = code_len - code_prologue + 1;
 169                }
 170                for (i = 0; i < code_len; i++, ip++) {
 171                        if (ip < (u8 *)PAGE_OFFSET ||
 172                                        probe_kernel_address(ip, c)) {
 173                                pr_cont(" Bad RIP value.");
 174                                break;
 175                        }
 176                        if (ip == (u8 *)regs->ip)
 177                                pr_cont("<%02x> ", c);
 178                        else
 179                                pr_cont("%02x ", c);
 180                }
 181        }
 182        pr_cont("\n");
 183}
 184
 185int is_valid_bugaddr(unsigned long ip)
 186{
 187        unsigned short ud2;
 188
 189        if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2)))
 190                return 0;
 191
 192        return ud2 == 0x0b0f;
 193}
 194