powerpc/xmon: Add xmon command to dump process/task similar to ps(1)
authorDouglas Miller <dougmill@linux.vnet.ibm.com>
Mon, 23 Nov 2015 15:01:15 +0000 (09:01 -0600)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 9 Feb 2016 23:22:04 +0000 (10:22 +1100)
Add 'P' command with optional task_struct address to dump all/one task's
information: task pointer, kernel stack pointer, PID, PPID, state
(interpreted), CPU where (last) running, and command.

Signed-off-by: Douglas Miller <dougmill@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/xmon/xmon.c

index 47e195d66a9aad43273bc56369263750ee646833..942796fa476750221133664d35d701a97b659499 100644 (file)
@@ -163,6 +163,7 @@ static int  cpu_cmd(void);
 static void csum(void);
 static void bootcmds(void);
 static void proccall(void);
+static void show_tasks(void);
 void dump_segments(void);
 static void symbol_lookup(void);
 static void xmon_show_stack(unsigned long sp, unsigned long lr,
@@ -238,6 +239,7 @@ Commands:\n\
   mz   zero a block of memory\n\
   mi   show information about memory allocation\n\
   p    call a procedure\n\
+  P    list processes/tasks\n\
   r    print registers\n\
   s    single step\n"
 #ifdef CONFIG_SPU_BASE
@@ -967,6 +969,9 @@ cmds(struct pt_regs *excp)
                case 'p':
                        proccall();
                        break;
+               case 'P':
+                       show_tasks();
+                       break;
 #ifdef CONFIG_PPC_STD_MMU
                case 'u':
                        dump_segments();
@@ -2566,6 +2571,61 @@ memzcan(void)
                printf("%.8x\n", a - mskip);
 }
 
+static void show_task(struct task_struct *tsk)
+{
+       char state;
+
+       /*
+        * Cloned from kdb_task_state_char(), which is not entirely
+        * appropriate for calling from xmon. This could be moved
+        * to a common, generic, routine used by both.
+        */
+       state = (tsk->state == 0) ? 'R' :
+               (tsk->state < 0) ? 'U' :
+               (tsk->state & TASK_UNINTERRUPTIBLE) ? 'D' :
+               (tsk->state & TASK_STOPPED) ? 'T' :
+               (tsk->state & TASK_TRACED) ? 'C' :
+               (tsk->exit_state & EXIT_ZOMBIE) ? 'Z' :
+               (tsk->exit_state & EXIT_DEAD) ? 'E' :
+               (tsk->state & TASK_INTERRUPTIBLE) ? 'S' : '?';
+
+       printf("%p %016lx %6d %6d %c %2d %s\n", tsk,
+               tsk->thread.ksp,
+               tsk->pid, tsk->parent->pid,
+               state, task_thread_info(tsk)->cpu,
+               tsk->comm);
+}
+
+static void show_tasks(void)
+{
+       unsigned long tskv;
+       struct task_struct *tsk = NULL;
+
+       printf("     task_struct     ->thread.ksp    PID   PPID S  P CMD\n");
+
+       if (scanhex(&tskv))
+               tsk = (struct task_struct *)tskv;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               catch_memory_errors = 0;
+               printf("*** Error dumping task %p\n", tsk);
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       if (tsk)
+               show_task(tsk);
+       else
+               for_each_process(tsk)
+                       show_task(tsk);
+
+       sync();
+       __delay(200);
+       catch_memory_errors = 0;
+}
+
 static void proccall(void)
 {
        unsigned long args[8];