Subject: [xmon PATCH 1/1] RFC: Add xmon command to dump process/task similar to ps(1)

From: Douglas Miller <[email-masked]>
Date: Tue, 10 Nov 2015 09:31:14 -0600

RFC: Not sure if I need locking when accessing task structs from xmon. 
Please comment.

I found this new xmon command indispensable while debugging a KDUMP 
problem. It dumps some task information similar to the ps(1) command, 
plus includes the kernel stack pointer for use with "t" traceback 
command. In the case of KDUMP on PKVM, it was running single-CPU so 
locking issues would likely not have shown up. Certainly if xmon runs in 
an environment where some CPUs are still running tasks, this information 
can be very fleeting.

Let me know what else needs to be done to make this patch ready.

Thanks,
Doug
>>From 5f2dd7c955443332835de86cfde2097e298fc657 Mon Sep 17 00:00:00 2001
From: Douglas Miller <[email-masked]>
Date: Thu, 5 Nov 2015 07:55:33 -0600
Subject: [PATCH] Add xmon command to dump process/task similar to ps(1)

---
 arch/powerpc/xmon/xmon.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 13c6e20..745ecf5 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -149,6 +149,7 @@ static int  cpu_cmd(void);
 static void csum(void);
 static void bootcmds(void);
 static void proccall(void);
+static void proclist(void);
 void dump_segments(void);
 static void symbol_lookup(void);
 static void xmon_show_stack(unsigned long sp, unsigned long lr,
@@ -228,6 +229,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
@@ -947,6 +949,9 @@ cmds(struct pt_regs *excp)
 		case 'p':
 			proccall();
 			break;
+		case 'P':
+			proclist();
+			break;
 #ifdef CONFIG_PPC_STD_MMU
 		case 'u':
 			dump_segments();
@@ -2450,6 +2455,38 @@ memzcan(void)
 		printf("%.8x\n", a - mskip);
 }
 
+static void procshow(struct task_struct *tsk)
+{
+	char state;
+	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 proclist(void)
+{
+	struct task_struct *tsk;
+
+	if (scanhex(&tsk)) {
+		procshow(tsk);
+	} else {
+		for_each_process(tsk) {
+			procshow(tsk);
+		}
+	}
+}
+
 static void proccall(void)
 {
 	unsigned long args[8];
-- 
1.7.1