Index: kernel/arch/xen32/src/asm.S
===================================================================
--- kernel/arch/xen32/src/asm.S	(revision 5b23a82c8d68ae8b01f1fbb9ace30e2377050d55)
+++ kernel/arch/xen32/src/asm.S	(revision 7c5a8dd4544d607500ff99d7bd9652675324b53e)
@@ -38,5 +38,4 @@
 .global xen_failsafe_callback
 .global enable_l_apic_in_msr
-.global interrupt_handlers
 .global memcpy
 .global memcpy_from_uspace
@@ -124,148 +123,2 @@
 	pop %eax
 	ret
-
-# Clear nested flag
-# overwrites %ecx
-.macro CLEAR_NT_FLAG
-	pushfl
-	pop %ecx
-	and $0xffffbfff,%ecx
-	push %ecx
-	popfl
-.endm	
-
-## Declare interrupt handlers
-#
-# Declare interrupt handlers for n interrupt
-# vectors starting at vector i.
-#
-# The handlers setup data segment registers
-# and call exc_dispatch().
-#
-#define INTERRUPT_ALIGN 64
-.macro handler i n
-
-.ifeq \i-0x30     # Syscall handler
-	push %ds
-	push %es
-	push %fs
-	push %gs
-
-	# Push arguments on stack
-	push %edi
-	push %esi
-	push %edx
-	push %ecx
-	push %eax
-	
-	# we must fill the data segment registers
-	movw $16,%ax
-	movw %ax,%ds
-	movw %ax,%es
-	
-	sti
-	
-	call syscall_handler   # syscall_handler(ax,cx,dx,si,di)
-	cli
-	addl $20, %esp         # clean-up of parameters
-	
-	pop %gs
-	pop %fs
-	pop %es
-	pop %ds
-	
-	CLEAR_NT_FLAG
-	iret
-.else	
-	/*
-	 * This macro distinguishes between two versions of ia32 exceptions.
-	 * One version has error word and the other does not have it.
-	 * The latter version fakes the error word on the stack so that the
-	 * handlers and istate_t can be the same for both types.
-	 */
-	.iflt \i-32
-		.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
-			/* 
-			 * With error word, do nothing
-			 */
-                .else
-                        /*
-                         * Version without error word,
-                         */
-			subl $4, %esp
-                .endif
-        .else
-                /*
-                 * Version without error word,
-                 */
-		subl $4, %esp
-	.endif
-	
-	push %ds
-	push %es
-	push %fs
-	push %gs
-
-#ifdef CONFIG_DEBUG_ALLREGS
-	push %ebx
-	push %ebp
-	push %edi
-	push %esi
-#else
-	sub $16, %esp
-#endif
-	push %edx
-	push %ecx
-	push %eax
-	
-	# we must fill the data segment registers
-	movw $16,%ax
-	movw %ax,%ds
-	movw %ax,%es
-
-	pushl %esp          # *istate
-	pushl $(\i)         # intnum
-	call exc_dispatch   # excdispatch(intnum, *istate)
-	addl $8,%esp        # Clear arguments from stack
-
-	CLEAR_NT_FLAG # Modifies %ecx
-	
-	pop %eax
-	pop %ecx
-	pop %edx
-#ifdef CONFIG_DEBUG_ALLREGS
-	pop %esi
-	pop %edi
-	pop %ebp
-	pop %ebx
-#else
-	add $16, %esp
-#endif	
-	
-	pop %gs
-	pop %fs
-	pop %es
-	pop %ds
-
-	addl $4,%esp	# Skip error word, no matter whether real or fake.
-	iret
-.endif
-
-	.align INTERRUPT_ALIGN
-	.if (\n-\i)-1
-	handler "(\i+1)",\n
-	.endif
-.endm
-
-# keep in sync with pm.h !!!
-IDT_ITEMS=64
-.align INTERRUPT_ALIGN
-interrupt_handlers:
-h_start:
-	handler 0 IDT_ITEMS
-h_end:
-
-.data
-.global interrupt_handler_size
-
-interrupt_handler_size: .long (h_end-h_start)/IDT_ITEMS
Index: kernel/arch/xen32/src/drivers/xconsole.c
===================================================================
--- kernel/arch/xen32/src/drivers/xconsole.c	(revision 5b23a82c8d68ae8b01f1fbb9ace30e2377050d55)
+++ kernel/arch/xen32/src/drivers/xconsole.c	(revision 7c5a8dd4544d607500ff99d7bd9652675324b53e)
@@ -40,5 +40,18 @@
 #include <console/console.h>
 #include <arch/hypercall.h>
+#include <mm/frame.h>
 
+#define MASK_INDEX(index, ring) ((index) & (sizeof(ring) - 1))
+
+typedef struct {
+	char in[1024];
+	char out[2048];
+    uint32_t in_cons;
+	uint32_t in_prod;
+    uint32_t out_cons;
+	uint32_t out_prod;
+} xencons_t;
+
+static bool asynchronous = false;
 static void xen_putchar(chardev_t *d, const char ch);
 
@@ -52,9 +65,31 @@
 	chardev_initialize("xen_out", &xen_console, &xen_ops);
 	stdout = &xen_console;
+	if (!(start_info.flags & SIF_INITDOMAIN))
+		asynchronous = true;
 }
 
 void xen_putchar(chardev_t *d, const char ch)
 {
-	xen_console_io(CONSOLE_IO_WRITE, 1, &ch);
+	if (asynchronous) {
+		xencons_t *console = (xencons_t *) PA2KA(MA2PA(PFN2ADDR(start_info.console_mfn)));
+		uint32_t cons = console->out_cons;
+		uint32_t prod = console->out_prod;
+		
+		memory_barrier();
+		
+		if ((prod - cons) > sizeof(console->out))
+			return;
+		
+		if (ch == '\n')
+			console->out[MASK_INDEX(prod++, console->out)] = '\r';
+		console->out[MASK_INDEX(prod++, console->out)] = ch;
+		
+		write_barrier();
+		
+		console->out_prod = prod;
+		
+		xen_notify_remote(start_info.console_evtchn);
+	} else
+		xen_console_io(CONSOLE_IO_WRITE, 1, &ch);
 }
 
Index: kernel/arch/xen32/src/pm.c
===================================================================
--- kernel/arch/xen32/src/pm.c	(revision 5b23a82c8d68ae8b01f1fbb9ace30e2377050d55)
+++ kernel/arch/xen32/src/pm.c	(revision 7c5a8dd4544d607500ff99d7bd9652675324b53e)
@@ -104,4 +104,8 @@
 }
 
+static void trap(void)
+{
+}
+
 void traps_init(void)
 {
@@ -117,5 +121,5 @@
 		
 		traps[i].cs = XEN_CS;
-		traps[i].address = ((uintptr_t) interrupt_handlers) + i * interrupt_handler_size;
+		traps[i].address = trap;
 		exc_register(i, "undef", (iroutine) null_interrupt);
 	}
