@@ -51,6 +51,48 @@ int show_unhandled_signals = 1;
/*
* Dump out the contents of some memory nicely...
*/
+
+static void dump_mem64(const char *lvl, const char *str, unsigned long bottom,
+ unsigned long top)
+{
+ unsigned long first;
+ mm_segment_t fs;
+ int i;
+
+ /*
+ * We need to switch to kernel mode so that we can use __get_user
+ * to safely read from kernel space. Note that we now dump the
+ * code first, just in case the backtrace kills us.
+ */
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ pr_alert("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top);
+
+ for (first = bottom & ~31; first < top; first += 32) {
+ unsigned long p;
+ char str[sizeof(" 1234567812345678") * 8 + 1];
+
+ memset(str, ' ', sizeof(str));
+ str[sizeof(str) - 1] = '\0';
+
+ for (p = first, i = 0; i < 4 && p < top; i++, p += 8) {
+ if (p >= bottom && p < top) {
+ unsigned long val;
+
+ if (__get_user(val, (unsigned long *)p) == 0)
+ sprintf(str + i * 17, " %016lx", val);
+ else
+ sprintf(str + i * 17,
+ " ????????????????");
+ }
+ }
+ pr_alert("%s%04lx:%s\n", lvl, first & 0xffff, str);
+ }
+
+ set_fs(fs);
+}
+
static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
unsigned long top)
{
@@ -206,8 +248,24 @@ static int __die(const char *str, int err, struct thread_info *thread,
TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
if (!user_mode(regs) || in_interrupt()) {
- dump_mem(KERN_EMERG, "Stack: ", regs->sp,
- THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+
+ if (regs->sp > (unsigned long)task_stack_page(tsk)) {
+ dump_mem64(KERN_EMERG, "Stack: ", regs->sp,
+ THREAD_SIZE +
+ (unsigned long)task_stack_page(tsk));
+ } else {
+ if (compat_user_mode(regs)) {
+ dump_mem(KERN_EMERG, "Stack: ",
+ (unsigned long)task_stack_page(tsk),
+ THREAD_SIZE +
+ (unsigned long)task_stack_page(tsk));
+ } else {
+ dump_mem64(KERN_EMERG, "Stack: ",
+ (unsigned long)task_stack_page(tsk),
+ THREAD_SIZE +
+ (unsigned long)task_stack_page(tsk));
+ }
+ }
dump_backtrace(regs, tsk);
dump_instr(KERN_EMERG, regs);
}