diff --git a/console.c b/console.c
index 218a627311c20da042fb51ed63569c865a7fe753..52ccc101f119538ebbf753e7fe9502f9045d5edb 100644
--- a/console.c
+++ b/console.c
@@ -356,19 +356,29 @@ kbd_intr()
       c += 'a' - 'A';
   }
 
-  // Ignore unknown keystrokes.
-  if(c == 0x0) {
-    release(&kbd_lock);
-    return;
-  }
-
-  if(((kbd_w + 1) % KBD_BUF) != kbd_r){
-    kbd_buf[kbd_w++] = c;
-    if(kbd_w >= KBD_BUF)
-      kbd_w = 0;
-    wakeup(&kbd_r);
-  } else {
-    cprintf("kbd overflow\n");
+  switch(c){
+  case 0:
+    // Ignore unknown keystrokes.
+    break;
+  
+  case C('T'):
+    cprintf("#");  // Let user know we're still alive.
+    break;
+  
+  case C('P'):
+    procdump();
+    break;
+
+  default:
+    if(((kbd_w + 1) % KBD_BUF) != kbd_r){
+      kbd_buf[kbd_w++] = c;
+      if(kbd_w >= KBD_BUF)
+        kbd_w = 0;
+      wakeup(&kbd_r);
+    } else {
+      cprintf("kbd overflow\n");
+    }
+    break;
   }
 
   release(&kbd_lock);
diff --git a/defs.h b/defs.h
index 0225e5d2f9286058a2b81ef00a0c996b3e6a9717..a08690f7d09a7d5ed47637f8ef0534c6586d01eb 100644
--- a/defs.h
+++ b/defs.h
@@ -24,6 +24,7 @@ void proc_exit(void);
 int proc_kill(int);
 int proc_wait(void);
 void yield(void);
+void procdump(void);
 
 // swtch.S
 struct jmpbuf;
diff --git a/proc.c b/proc.c
index 3b7843fc25bc8137adbd453639a73f96ccadd396..37fd768fe855502f0ea6258170dc1308ed3be156 100644
--- a/proc.c
+++ b/proc.c
@@ -403,3 +403,19 @@ proc_wait(void)
   }
 }
 
+// Print a process listing to console.  For debugging.
+// Runs when user types ^P on console.
+// No lock to avoid wedging a stuck machine further.
+void
+procdump(void)
+{
+  int i;
+  struct proc *p;
+  
+  for(i = 0; i < NPROC; i++) {
+    p = &proc[i];
+    if(p->state == UNUSED)
+      continue;
+    cprintf("%d %d %p\n", p->pid, p->state);
+  }
+}