linux/arch/x86/kernel/dumpstack_32.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 void *is_irq_stack(void *p, void *irq)
  20{
  21        if (p < irq || p >= (irq + THREAD_SIZE))
  22                return NULL;
  23        return irq + THREAD_SIZE;
  24}
  25
  26
  27static void *is_hardirq_stack(unsigned long *stack, int cpu)
  28{
  29        void *irq = per_cpu(hardirq_stack, cpu);
  30
  31        return is_irq_stack(stack, irq);
  32}
  33
  34static void *is_softirq_stack(unsigned long *stack, int cpu)
  35{
  36        void *irq = per_cpu(softirq_stack, cpu);
  37
  38        return is_irq_stack(stack, irq);
  39}
  40
  41void dump_trace(struct task_struct *task, struct pt_regs *regs,
  42                unsigned long *stack, unsigned long bp,
  43                const struct stacktrace_ops *ops, void *data)
  44{
  45        const unsigned cpu = get_cpu();
  46        int graph = 0;
  47        u32 *prev_esp;
  48
  49        if (!task)
  50                task = current;
  51
  52        if (!stack) {
  53                unsigned long dummy;
  54
  55                stack = &dummy;
  56                if (task != current)
  57                        stack = (unsigned long *)task->thread.sp;
  58        }
  59
  60        if (!bp)
  61                bp = stack_frame(task, regs);
  62
  63        for (;;) {
  64                void *end_stack;
  65
  66                end_stack = is_hardirq_stack(stack, cpu);
  67                if (!end_stack)
  68                        end_stack = is_softirq_stack(stack, cpu);
  69
  70                bp = ops->walk_stack(task, stack, bp, ops, data,
  71                                     end_stack, &graph);
  72
  73                /* Stop if not on irq stack */
  74                if (!end_stack)
  75                        break;
  76
  77                /* The previous esp is saved on the bottom of the stack */
  78                prev_esp = (u32 *)(end_stack - THREAD_SIZE);
  79                stack = (unsigned long *)*prev_esp;
  80                if (!stack)
  81                        break;
  82
  83                if (ops->stack(data, "IRQ") < 0)
  84                        break;
  85                touch_nmi_watchdog();
  86        }
  87        put_cpu();
  88}
  89EXPORT_SYMBOL(dump_trace);
  90
  91void
  92show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
  93                   unsigned long *sp, unsigned long bp, char *log_lvl)
  94{
  95        unsigned long *stack;
  96        int i;
  97
  98        if (sp == NULL) {
  99                if (task)
 100                        sp = (unsigned long *)task->thread.sp;
 101                else
 102                        sp = (unsigned long *)&sp;
 103        }
 104
 105        stack = sp;
 106        for (i = 0; i < kstack_depth_to_print; i++) {
 107                if (kstack_end(stack))
 108                        break;
 109                if ((i % STACKSLOTS_PER_LINE) == 0) {
 110                        if (i != 0)
 111                                pr_cont("\n");
 112                        printk("%s %08lx", log_lvl, *stack++);
 113                } else
 114                        pr_cont(" %08lx", *stack++);
 115                touch_nmi_watchdog();
 116        }
 117        pr_cont("\n");
 118        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 119}
 120
 121
 122void show_regs(struct pt_regs *regs)
 123{
 124        int i;
 125
 126        show_regs_print_info(KERN_EMERG);
 127        __show_regs(regs, !user_mode(regs));
 128
 129        /*
 130         * When in-kernel, we also print out the stack and code at the
 131         * time of the fault..
 132         */
 133        if (!user_mode(regs)) {
 134                unsigned int code_prologue = code_bytes * 43 / 64;
 135                unsigned int code_len = code_bytes;
 136                unsigned char c;
 137                u8 *ip;
 138
 139                pr_emerg("Stack:\n");
 140                show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
 141
 142                pr_emerg("Code:");
 143
 144                ip = (u8 *)regs->ip - code_prologue;
 145                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
 146                        /* try starting at IP */
 147                        ip = (u8 *)regs->ip;
 148                        code_len = code_len - code_prologue + 1;
 149                }
 150                for (i = 0; i < code_len; i++, ip++) {
 151                        if (ip < (u8 *)PAGE_OFFSET ||
 152                                        probe_kernel_address(ip, c)) {
 153                                pr_cont("  Bad EIP value.");
 154                                break;
 155                        }
 156                        if (ip == (u8 *)regs->ip)
 157                                pr_cont(" <%02x>", c);
 158                        else
 159                                pr_cont(" %02x", c);
 160                }
 161        }
 162        pr_cont("\n");
 163}
 164
 165int is_valid_bugaddr(unsigned long ip)
 166{
 167        unsigned short ud2;
 168
 169        if (ip < PAGE_OFFSET)
 170                return 0;
 171        if (probe_kernel_address((unsigned short *)ip, ud2))
 172                return 0;
 173
 174        return ud2 == 0x0b0f;
 175}
 176