static unsigned long xmon_taken = 1;
 static int xmon_owner;
 static int xmon_gate;
+#else
+#define xmon_owner 0
 #endif /* CONFIG_SMP */
 
 static unsigned long in_xmon __read_mostly = 0;
   di   dump instructions\n\
   df   dump float values\n\
   dd   dump double values\n\
-  dl    dump the kernel log buffer\n\
+  dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC64
+  "\
+  dp[#]        dump paca for current cpu, or cpu #\n\
+  dpa  dump paca for all possible cpus\n"
+#endif
+  "\
   dr   dump stream of raw bytes\n\
   e    print exception information\n\
   f    flush cache\n\
        printf("\n");
 }
 
+#ifdef CONFIG_PPC64
+static void dump_one_paca(int cpu)
+{
+       struct paca_struct *p;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       p = &paca[cpu];
+
+       printf("paca for cpu 0x%x @ %p:\n", cpu, p);
+
+       printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
+       printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
+
+#define DUMP(paca, name, format) \
+       printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
+               offsetof(struct paca_struct, name));
+
+       DUMP(p, lock_token, "x");
+       DUMP(p, paca_index, "x");
+       DUMP(p, kernel_toc, "lx");
+       DUMP(p, kernelbase, "lx");
+       DUMP(p, kernel_msr, "lx");
+#ifdef CONFIG_PPC_STD_MMU_64
+       DUMP(p, stab_real, "lx");
+       DUMP(p, stab_addr, "lx");
+#endif
+       DUMP(p, emergency_sp, "p");
+       DUMP(p, data_offset, "lx");
+       DUMP(p, hw_cpu_id, "x");
+       DUMP(p, cpu_start, "x");
+       DUMP(p, kexec_state, "x");
+       DUMP(p, __current, "p");
+       DUMP(p, kstack, "lx");
+       DUMP(p, stab_rr, "lx");
+       DUMP(p, saved_r1, "lx");
+       DUMP(p, trap_save, "x");
+       DUMP(p, soft_enabled, "x");
+       DUMP(p, irq_happened, "x");
+       DUMP(p, io_sync, "x");
+       DUMP(p, irq_work_pending, "x");
+       DUMP(p, nap_state_lost, "x");
+
+#undef DUMP
+
+       catch_memory_errors = 0;
+       sync();
+}
+
+static void dump_all_pacas(void)
+{
+       int cpu;
+
+       if (num_possible_cpus() == 0) {
+               printf("No possible cpus, use 'dp #' to dump individual cpus\n");
+               return;
+       }
+
+       for_each_possible_cpu(cpu)
+               dump_one_paca(cpu);
+}
+
+static void dump_pacas(void)
+{
+       unsigned long num;
+       int c;
+
+       c = inchar();
+       if (c == 'a') {
+               dump_all_pacas();
+               return;
+       }
+
+       termch = c;     /* Put c back, it wasn't 'a' */
+
+       if (scanhex(&num))
+               dump_one_paca(num);
+       else
+               dump_one_paca(xmon_owner);
+}
+#endif
+
 #define isxdigit(c)    (('0' <= (c) && (c) <= '9') \
                         || ('a' <= (c) && (c) <= 'f') \
                         || ('A' <= (c) && (c) <= 'F'))
        int c;
 
        c = inchar();
+
+#ifdef CONFIG_PPC64
+       if (c == 'p') {
+               dump_pacas();
+               return;
+       }
+#endif
+
        if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
                termch = c;
        scanhex((void *)&adrs);