Index: arch/mips32/src/drivers/msim.c
===================================================================
--- arch/mips32/src/drivers/msim.c	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ arch/mips32/src/drivers/msim.c	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -38,9 +38,11 @@
 static void msim_enable(chardev_t *dev);
 static void msim_disable(chardev_t *dev);
+static char msim_do_read(chardev_t *dev);
 
 static chardev_operations_t msim_ops = {
 	.resume = msim_enable,
 	.suspend = msim_disable,
-	.write = msim_write
+	.write = msim_write,
+	.read = msim_do_read,
 };
 
@@ -64,8 +66,25 @@
 
 #include <print.h>
+/** Read character using polling, assume interrupts disabled */
+static char msim_do_read(chardev_t *dev)
+{
+	char ch;
+
+	while (1) {
+		ch = *((volatile char *) MSIM_KBD_ADDRESS);
+		if (ch) {
+			if (ch == '\r')
+				return '\n';
+			if (ch == 0x7f)
+				return '\b';
+			return ch;
+		}
+	}
+}
+
 /** Process keyboard interrupt. */
 static void msim_interrupt(int n, void *stack)
 {
-	char ch;
+	char ch = 0;
 
 	ch = *((char *) MSIM_KBD_ADDRESS);
Index: arch/mips32/src/drivers/serial.c
===================================================================
--- arch/mips32/src/drivers/serial.c	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ arch/mips32/src/drivers/serial.c	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -72,9 +72,19 @@
 }
 
-static chardev_operations_t serial_ops = {
-	.resume = serial_enable,
-	.suspend = serial_disable,
-	.write = serial_write
-};
+/** Read character from serial port, wait until available */
+static char serial_do_read(chardev_t *dev)
+{
+	serial_t *sd = (serial_t *)dev->data;
+	char ch;
+
+	while (!(SERIAL_READ_LSR(sd->port) & 1))
+		;
+	ch = SERIAL_READ(sd->port);
+
+	if (ch =='\r')
+		ch = '\n';
+	return ch;
+}
+
 
 /** Process keyboard interrupt. Does not work in simics? */
@@ -93,4 +103,12 @@
 }
 
+
+
+static chardev_operations_t serial_ops = {
+	.resume = serial_enable,
+	.suspend = serial_disable,
+	.write = serial_write,
+	.read = serial_do_read
+};
 
 iroutine old_timer;
Index: arch/mips32/src/panic.S
===================================================================
--- arch/mips32/src/panic.S	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ arch/mips32/src/panic.S	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -39,5 +39,10 @@
 /* From printf return directly to halt() */	
 panic_printf:
-	lui $ra, %hi(halt)
+	jal printf
+	nop
+	j halt
+	nop
+/* This code does not work, god knows why */		
+/*	lui $ra, %hi(halt)
 	j printf
-	ori $ra, %lo(halt)
+	ori $ra, %lo(halt) */
Index: generic/include/console/chardev.h
===================================================================
--- generic/include/console/chardev.h	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ generic/include/console/chardev.h	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -42,4 +42,6 @@
 	void (* resume)(chardev_t *); 		/**< Resume pushing characters. */
 	void (* write)(chardev_t *, char c);	/**< Write character to stream. */
+	/** Read character directly from device, assume interrupts disabled */
+	char (* read)(chardev_t *); 
 };
 
Index: generic/src/console/console.c
===================================================================
--- generic/src/console/console.c	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ generic/src/console/console.c	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -35,4 +35,6 @@
 #include <typedefs.h>
 #include <arch.h>
+#include <func.h>
+#include <print.h>
 
 /** Standard input character device. */
@@ -50,4 +52,16 @@
 	__u8 ch;
 	ipl_t ipl;
+
+	if (haltstate) {
+		/* If we are here, we are hopefully on the processor, that 
+		 * issued the 'halt' command, so proceed to read the character
+		 * directly from input
+		 */
+		if (chardev->op->read)
+			return chardev->op->read(chardev);
+		/* no other way of interacting with user, halt */
+		printf("cpu: halted - no kconsole\n");
+		cpu_halt();
+	}
 
 	waitq_sleep(&chardev->wq);
@@ -115,4 +129,5 @@
 void putchar(char c)
 {
-	stdout->op->write(stdout, c);
+	if (stdout->op->write)
+		stdout->op->write(stdout, c);
 }
Index: generic/src/console/kconsole.c
===================================================================
--- generic/src/console/kconsole.c	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ generic/src/console/kconsole.c	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -248,5 +248,5 @@
 			putchar(c);
 			break;
-		} if (c == '\b') {
+		} if (c == '\b') { /* Backspace */
 			if (position == 0)
 				continue;
@@ -262,5 +262,5 @@
 			continue;
 		}
-		if (c == '\t') {
+		if (c == '\t') { /* Tabulator */
 			int found;
 
@@ -310,5 +310,5 @@
 			continue;
 		}
-		if (c == 0x1b) {
+		if (c == 0x1b) { /* Special command */
 			mod = _getc(input);
 			c = _getc(input);
@@ -318,4 +318,5 @@
 
 			if (c == 0x33 && _getc(input) == 0x7e) {
+				/* Delete */
 				if (position == curlen)
 					continue;
@@ -332,5 +333,5 @@
 				position = 0;
 			} 
-			else if (c == 0x46) {
+			else if (c == 0x46) {  /* End */
 				for (i=position;i<curlen;i++)
 					putchar(current[i]);
@@ -356,5 +357,5 @@
 				rdln_print_c(' ',curlen);
 				rdln_print_c('\b',curlen);
-				if (c == 0x41)
+				if (c == 0x41) /* Up */
 					histposition--;
 				else
Index: generic/src/lib/func.c
===================================================================
--- generic/src/lib/func.c	(revision af9a7c57cb5b1118b9fe7512bf136d64c3eee3b2)
+++ generic/src/lib/func.c	(revision 93b84b3c39c5f623f2855694d31930674e24a165)
@@ -33,4 +33,5 @@
 #include <arch.h>
 #include <typedefs.h>
+#include <console/kconsole.h>
 
 __u32	haltstate = 0; /**< Halt flag */
@@ -46,4 +47,9 @@
 	haltstate = 1;
 	interrupts_disable();
+#ifdef CONFIG_DEBUG
+	printf("\n");
+	kconsole(NULL); /* Run kconsole as a last resort to user */
+#endif      
+
 	if (CPU)
 		printf("cpu%d: halted\n", CPU->id);
