Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/Makefile	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -364,8 +364,10 @@
 #
 
-ifeq ($(CONFIG_LOG),y)
+ifeq ($(CONFIG_TRACE),y)
 INSTRUMENTED_SOURCES = \
 	generic/src/cpu/cpu.c \
-	generic/src/main/kinit.c
+	generic/src/main/main.c \
+	generic/src/main/kinit.c \
+	generic/src/proc/the.c
 endif
 
Index: kernel/arch/abs32le/src/abs32le.c
===================================================================
--- kernel/arch/abs32le/src/abs32le.c	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/abs32le/src/abs32le.c	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -151,4 +151,8 @@
 }
 
+void early_putchar(wchar_t ch)
+{
+}
+
 /** @}
  */
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/amd64/Makefile.inc	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -71,5 +71,5 @@
 	arch/$(KARCH)/src/mm/page.c \
 	arch/$(KARCH)/src/mm/tlb.c \
-	arch/$(KARCH)/src/asm_utils.S \
+	arch/$(KARCH)/src/asm.S \
 	arch/$(KARCH)/src/cpu/cpu.c \
 	arch/$(KARCH)/src/proc/scheduler.c \
Index: kernel/arch/amd64/src/asm.S
===================================================================
--- kernel/arch/amd64/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
+++ kernel/arch/amd64/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2005 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define IREGISTER_SPACE  80
+
+#define IOFFSET_RAX  0x00
+#define IOFFSET_RCX  0x08
+#define IOFFSET_RDX  0x10
+#define IOFFSET_RSI  0x18
+#define IOFFSET_RDI  0x20
+#define IOFFSET_R8   0x28
+#define IOFFSET_R9   0x30
+#define IOFFSET_R10  0x38
+#define IOFFSET_R11  0x40
+#define IOFFSET_RBP  0x48
+
+/**
+ * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
+ * has no error word  and 1 means interrupt with error word
+ *
+ */
+#define ERROR_WORD_INTERRUPT_LIST  0x00027D00
+
+#include <arch/pm.h>
+#include <arch/mm/page.h>
+
+.text
+.global interrupt_handlers
+.global syscall_entry
+.global cpuid
+.global has_cpuid
+.global read_efer_flag
+.global set_efer_flag
+.global memsetb
+.global memsetw
+.global memcpy
+.global memcpy_from_uspace
+.global memcpy_to_uspace
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
+.global early_putchar
+
+/* Wrapper for generic memsetb */
+memsetb:
+	jmp _memsetb
+
+/* Wrapper for generic memsetw */
+memsetw:
+	jmp _memsetw
+
+#define MEMCPY_DST   %rdi
+#define MEMCPY_SRC   %rsi
+#define MEMCPY_SIZE  %rdx
+
+/**
+ * Copy memory from/to userspace.
+ *
+ * This is almost conventional memcpy().
+ * The difference is that there is a failover part
+ * to where control is returned from a page fault if
+ * the page fault occurs during copy_from_uspace()
+ * or copy_to_uspace().
+ *
+ * @param MEMCPY_DST  Destination address.
+ * @param MEMCPY_SRC  Source address.
+ * @param MEMCPY_SIZE Number of bytes to copy.
+ *
+ * @retrun MEMCPY_DST on success, 0 on failure.
+ *
+ */
+memcpy:
+memcpy_from_uspace:
+memcpy_to_uspace:
+	movq MEMCPY_DST, %rax
+	
+	movq MEMCPY_SIZE, %rcx
+	shrq $3, %rcx           /* size / 8 */
+	
+	rep movsq               /* copy as much as possible word by word */
+	
+	movq MEMCPY_SIZE, %rcx
+	andq $7, %rcx           /* size % 8 */
+	jz 0f
+	
+	rep movsb               /* copy the rest byte by byte */
+	
+	0:
+		ret                 /* return MEMCPY_SRC, success */
+
+memcpy_from_uspace_failover_address:
+memcpy_to_uspace_failover_address:
+	xorq %rax, %rax         /* return 0, failure */
+	ret
+
+/** Determine CPUID support
+*
+* @return 0 in EAX if CPUID is not support, 1 if supported.
+*
+*/
+has_cpuid:
+	/* Load RFLAGS */
+	pushfq
+	popq %rax
+	movq %rax, %rdx
+	
+	/* Flip the ID bit */
+	btcl $21, %edx
+	
+	/* Store RFLAGS */
+	pushq %rdx
+	popfq
+	pushfq
+	
+	/* Get the ID bit again */
+	popq %rdx
+	andl $(1 << 21), %eax
+	andl $(1 << 21), %edx
+	
+	/* 0 if not supported, 1 if supported */
+	xorl %edx, %eax
+	ret
+
+cpuid:
+	/* Preserve %rbx across function calls */
+	movq %rbx, %r10
+	
+	/* Load the command into %eax */
+	movl %edi, %eax
+	
+	cpuid
+	movl %eax, 0(%rsi)
+	movl %ebx, 4(%rsi)
+	movl %ecx, 8(%rsi)
+	movl %edx, 12(%rsi)
+	
+	movq %r10, %rbx
+	ret
+
+set_efer_flag:
+	movq $0xc0000080, %rcx
+	rdmsr
+	btsl %edi, %eax
+	wrmsr
+	ret
+
+read_efer_flag:
+	movq $0xc0000080, %rcx
+	rdmsr
+	ret
+
+/** Push all volatile general purpose registers on stack
+ *
+ */
+.macro save_all_gpr
+	movq %rax, IOFFSET_RAX(%rsp)
+	movq %rcx, IOFFSET_RCX(%rsp)
+	movq %rdx, IOFFSET_RDX(%rsp)
+	movq %rsi, IOFFSET_RSI(%rsp)
+	movq %rdi, IOFFSET_RDI(%rsp)
+	movq %r8, IOFFSET_R8(%rsp)
+	movq %r9, IOFFSET_R9(%rsp)
+	movq %r10, IOFFSET_R10(%rsp)
+	movq %r11, IOFFSET_R11(%rsp)
+	movq %rbp, IOFFSET_RBP(%rsp)
+.endm
+
+.macro restore_all_gpr
+	movq IOFFSET_RAX(%rsp), %rax
+	movq IOFFSET_RCX(%rsp), %rcx
+	movq IOFFSET_RDX(%rsp), %rdx
+	movq IOFFSET_RSI(%rsp), %rsi
+	movq IOFFSET_RDI(%rsp), %rdi
+	movq IOFFSET_R8(%rsp), %r8
+	movq IOFFSET_R9(%rsp), %r9
+	movq IOFFSET_R10(%rsp), %r10
+	movq IOFFSET_R11(%rsp), %r11
+	movq IOFFSET_RBP(%rsp), %rbp
+.endm
+
+#define INTERRUPT_ALIGN  128
+
+/** Declare interrupt handlers
+ *
+ * Declare interrupt handlers for n interrupt
+ * vectors starting at vector i.
+ *
+ * The handlers call exc_dispatch().
+ *
+ */
+.macro handler i n
+	
+	/*
+	 * Choose between version with error code and version without error
+	 * code. Both versions have to be of the same size. amd64 assembly is,
+	 * however, a little bit tricky. For instance, subq $0x80, %rsp and
+	 * subq $0x78, %rsp can result in two instructions with different
+	 * op-code lengths.
+	 * Therefore we align the interrupt handlers.
+	 */
+	
+	.iflt \i-32
+		.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
+			/*
+			 * Version with error word.
+			 */
+			subq $IREGISTER_SPACE, %rsp
+		.else
+			/*
+			 * Version without error word,
+			 */
+			subq $(IREGISTER_SPACE + 8), %rsp
+		.endif
+	.else
+		/*
+		 * Version without error word,
+		 */
+		subq $(IREGISTER_SPACE + 8), %rsp
+	.endif
+	
+	save_all_gpr
+	cld
+	
+	/*
+	 * Stop stack traces here if we came from userspace.
+	 */
+	movq %cs, %rax
+	xorq %rdx, %rdx
+	cmpq %rax, IREGISTER_SPACE+16(%rsp)
+	cmovneq %rdx, %rbp
+
+	movq $(\i), %rdi   /* %rdi - first argument */
+	movq %rsp, %rsi    /* %rsi - pointer to istate */
+	
+	/* Call exc_dispatch(i, istate) */
+	call exc_dispatch
+	
+	restore_all_gpr
+	
+	/* $8 = Skip error word */
+	addq $(IREGISTER_SPACE + 8), %rsp
+	iretq
+	
+	.align INTERRUPT_ALIGN
+	.if (\n - \i) - 1
+		handler "(\i + 1)", \n
+	.endif
+.endm
+
+.align INTERRUPT_ALIGN
+interrupt_handlers:
+	h_start:
+		handler 0 IDT_ITEMS
+	h_end:
+
+/** Low-level syscall handler
+ *
+ * Registers on entry:
+ *
+ * @param %rcx Userspace return address.
+ * @param %r11 Userspace RLFAGS.
+ *
+ * @param %rax Syscall number.
+ * @param %rdi 1st syscall argument.
+ * @param %rsi 2nd syscall argument.
+ * @param %rdx 3rd syscall argument.
+ * @param %r10 4th syscall argument. Used instead of RCX because
+ *             the SYSCALL instruction clobbers it.
+ * @param %r8  5th syscall argument.
+ * @param %r9  6th syscall argument.
+ *
+ * @return Return value is in %rax.
+ *
+ */
+syscall_entry:
+	/* Switch to hidden %gs */
+	swapgs
+	
+	/*
+	 * %gs:0 Scratch space for this thread's user RSP
+	 * %gs:8 Address to be used as this thread's kernel RSP
+	 */
+	
+	movq %rsp, %gs:0  /* save this thread's user RSP */
+	movq %gs:8, %rsp  /* set this thread's kernel RSP */
+	
+	/* Switch back to remain consistent */
+	swapgs
+	sti
+	
+	pushq %rcx
+	pushq %r11
+	pushq %rbp
+	
+	xorq %rbp, %rbp  /* stop the stack traces here */
+	
+	/* Copy the 4th argument where it is expected  */
+	movq %r10, %rcx
+	pushq %rax
+	
+	call syscall_handler
+	
+	addq $8, %rsp
+	
+	popq %rbp
+	popq %r11
+	popq %rcx
+	
+	cli
+	swapgs
+	
+	/* Restore the user RSP */
+	movq %gs:0, %rsp
+	swapgs
+	
+	sysretq
+
+/** Print Unicode character to EGA display.
+ *
+ * If CONFIG_EGA is undefined or CONFIG_FB is defined
+ * then this function does nothing.
+ *
+ * Since the EGA can only display Extended ASCII (usually
+ * ISO Latin 1) characters, some of the Unicode characters
+ * can be displayed in a wrong way. Only the newline character
+ * is interpreted, all other characters (even unprintable) are
+ * printed verbatim.
+ *
+ * @param %rdi Unicode character to be printed.
+ *
+ */
+early_putchar:
+	
+#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
+	
+	/* Prologue, save preserved registers */
+	pushq %rbp
+	movq %rsp, %rbp
+	pushq %rbx
+	
+	movq %rdi, %rsi
+	movq $(PA2KA(0xb8000)), %rdi  /* base of EGA text mode memory */
+	xorq %rax, %rax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb early_putchar_cursor_ok
+	
+		movw $1998, %ax
+	
+	early_putchar_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %rax
+	addq %rax, %rdi
+	
+	movq %rsi, %rax
+	
+	cmp $0x0a, %al
+	jne early_putchar_print
+	
+		/* Interpret newline */
+		
+		movw %bx, %ax  /* %bx -> %dx:%ax */
+		xorw %dx, %dx
+		
+		movw $80, %cx
+		idivw %cx, %ax  /* %dx = %bx % 80 */
+		
+		/* %bx <- %bx + 80 - (%bx % 80) */
+		addw %cx, %bx
+		subw %dx, %bx
+		
+		jmp early_putchar_newline
+	
+	early_putchar_print:
+	
+		/* Print character */
+		
+		movb $0x0e, %ah  /* black background, yellow foreground */
+		stosw
+	
+	early_putchar_newline:
+	
+	/* Sanity check for the cursor on the last line */
+	inc %bx
+	cmp $2000, %bx
+	jb early_putchar_no_scroll
+	
+		/* Scroll the screen (24 rows) */
+		movq $(PA2KA(0xb80a0)), %rsi
+		movq $(PA2KA(0xb8000)), %rdi
+		movq $1920, %rcx
+		rep movsw
+		
+		/* Clear the 24th row */
+		xorq %rax, %rax
+		movq $80, %rcx
+		rep stosw
+		
+		/* Go to row 24 */
+		movw $1920, %bx
+	
+	early_putchar_no_scroll:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	/* Epilogue, restore preserved registers */
+	popq %rbx
+	leave
+	
+#endif
+	
+	ret
+
+.data
+.global interrupt_handler_size
+
+interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Index: rnel/arch/amd64/src/asm_utils.S
===================================================================
--- kernel/arch/amd64/src/asm_utils.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ 	(revision )
@@ -1,344 +1,0 @@
-/*
- * Copyright (c) 2005 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define IREGISTER_SPACE  80
-
-#define IOFFSET_RAX  0x00
-#define IOFFSET_RCX  0x08
-#define IOFFSET_RDX  0x10
-#define IOFFSET_RSI  0x18
-#define IOFFSET_RDI  0x20
-#define IOFFSET_R8   0x28
-#define IOFFSET_R9   0x30
-#define IOFFSET_R10  0x38
-#define IOFFSET_R11  0x40
-#define IOFFSET_RBP  0x48
-
-/**
- * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
- * has no error word  and 1 means interrupt with error word
- *
- */
-#define ERROR_WORD_INTERRUPT_LIST  0x00027D00
-
-#include <arch/pm.h>
-#include <arch/mm/page.h>
-
-.text
-.global interrupt_handlers
-.global syscall_entry
-.global cpuid
-.global has_cpuid
-.global read_efer_flag
-.global set_efer_flag
-.global memsetb
-.global memsetw
-.global memcpy
-.global memcpy_from_uspace
-.global memcpy_to_uspace
-.global memcpy_from_uspace_failover_address
-.global memcpy_to_uspace_failover_address
-
-/* Wrapper for generic memsetb */
-memsetb:
-	jmp _memsetb
-
-/* Wrapper for generic memsetw */
-memsetw:
-	jmp _memsetw
-
-#define MEMCPY_DST   %rdi
-#define MEMCPY_SRC   %rsi
-#define MEMCPY_SIZE  %rdx
-
-/**
- * Copy memory from/to userspace.
- *
- * This is almost conventional memcpy().
- * The difference is that there is a failover part
- * to where control is returned from a page fault if
- * the page fault occurs during copy_from_uspace()
- * or copy_to_uspace().
- *
- * @param MEMCPY_DST  Destination address.
- * @param MEMCPY_SRC  Source address.
- * @param MEMCPY_SIZE Number of bytes to copy.
- *
- * @retrun MEMCPY_DST on success, 0 on failure.
- *
- */
-memcpy:
-memcpy_from_uspace:
-memcpy_to_uspace:
-	movq MEMCPY_DST, %rax
-	
-	movq MEMCPY_SIZE, %rcx
-	shrq $3, %rcx           /* size / 8 */
-	
-	rep movsq               /* copy as much as possible word by word */
-	
-	movq MEMCPY_SIZE, %rcx
-	andq $7, %rcx           /* size % 8 */
-	jz 0f
-	
-	rep movsb               /* copy the rest byte by byte */
-	
-	0:
-		ret                 /* return MEMCPY_SRC, success */
-
-memcpy_from_uspace_failover_address:
-memcpy_to_uspace_failover_address:
-	xorq %rax, %rax         /* return 0, failure */
-	ret
-
-/** Determine CPUID support
-*
-* @return 0 in EAX if CPUID is not support, 1 if supported.
-*
-*/
-has_cpuid:
-	/* Load RFLAGS */
-	pushfq
-	popq %rax
-	movq %rax, %rdx
-	
-	/* Flip the ID bit */
-	btcl $21, %edx
-	
-	/* Store RFLAGS */
-	pushq %rdx
-	popfq
-	pushfq
-	
-	/* Get the ID bit again */
-	popq %rdx
-	andl $(1 << 21), %eax
-	andl $(1 << 21), %edx
-	
-	/* 0 if not supported, 1 if supported */
-	xorl %edx, %eax
-	ret
-
-cpuid:
-	/* Preserve %rbx across function calls */
-	movq %rbx, %r10
-	
-	/* Load the command into %eax */
-	movl %edi, %eax
-	
-	cpuid
-	movl %eax, 0(%rsi)
-	movl %ebx, 4(%rsi)
-	movl %ecx, 8(%rsi)
-	movl %edx, 12(%rsi)
-	
-	movq %r10, %rbx
-	ret
-
-set_efer_flag:
-	movq $0xc0000080, %rcx
-	rdmsr
-	btsl %edi, %eax
-	wrmsr
-	ret
-
-read_efer_flag:
-	movq $0xc0000080, %rcx
-	rdmsr
-	ret
-
-/** Push all volatile general purpose registers on stack
- *
- */
-.macro save_all_gpr
-	movq %rax, IOFFSET_RAX(%rsp)
-	movq %rcx, IOFFSET_RCX(%rsp)
-	movq %rdx, IOFFSET_RDX(%rsp)
-	movq %rsi, IOFFSET_RSI(%rsp)
-	movq %rdi, IOFFSET_RDI(%rsp)
-	movq %r8, IOFFSET_R8(%rsp)
-	movq %r9, IOFFSET_R9(%rsp)
-	movq %r10, IOFFSET_R10(%rsp)
-	movq %r11, IOFFSET_R11(%rsp)
-	movq %rbp, IOFFSET_RBP(%rsp)
-.endm
-
-.macro restore_all_gpr
-	movq IOFFSET_RAX(%rsp), %rax
-	movq IOFFSET_RCX(%rsp), %rcx
-	movq IOFFSET_RDX(%rsp), %rdx
-	movq IOFFSET_RSI(%rsp), %rsi
-	movq IOFFSET_RDI(%rsp), %rdi
-	movq IOFFSET_R8(%rsp), %r8
-	movq IOFFSET_R9(%rsp), %r9
-	movq IOFFSET_R10(%rsp), %r10
-	movq IOFFSET_R11(%rsp), %r11
-	movq IOFFSET_RBP(%rsp), %rbp
-.endm
-
-#define INTERRUPT_ALIGN  128
-
-/** Declare interrupt handlers
- *
- * Declare interrupt handlers for n interrupt
- * vectors starting at vector i.
- *
- * The handlers call exc_dispatch().
- *
- */
-.macro handler i n
-	
-	/*
-	 * Choose between version with error code and version without error
-	 * code. Both versions have to be of the same size. amd64 assembly is,
-	 * however, a little bit tricky. For instance, subq $0x80, %rsp and
-	 * subq $0x78, %rsp can result in two instructions with different
-	 * op-code lengths.
-	 * Therefore we align the interrupt handlers.
-	 */
-	
-	.iflt \i-32
-		.if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
-			/*
-			 * Version with error word.
-			 */
-			subq $IREGISTER_SPACE, %rsp
-		.else
-			/*
-			 * Version without error word,
-			 */
-			subq $(IREGISTER_SPACE + 8), %rsp
-		.endif
-	.else
-		/*
-		 * Version without error word,
-		 */
-		subq $(IREGISTER_SPACE + 8), %rsp
-	.endif
-	
-	save_all_gpr
-	cld
-	
-	/*
-	 * Stop stack traces here if we came from userspace.
-	 */
-	movq %cs, %rax
-	xorq %rdx, %rdx
-	cmpq %rax, IREGISTER_SPACE+16(%rsp)
-	cmovneq %rdx, %rbp
-
-	movq $(\i), %rdi   /* %rdi - first argument */
-	movq %rsp, %rsi    /* %rsi - pointer to istate */
-	
-	/* Call exc_dispatch(i, istate) */
-	call exc_dispatch
-	
-	restore_all_gpr
-	
-	/* $8 = Skip error word */
-	addq $(IREGISTER_SPACE + 8), %rsp
-	iretq
-	
-	.align INTERRUPT_ALIGN
-	.if (\n - \i) - 1
-		handler "(\i + 1)", \n
-	.endif
-.endm
-
-.align INTERRUPT_ALIGN
-interrupt_handlers:
-	h_start:
-		handler 0 IDT_ITEMS
-	h_end:
-
-/** Low-level syscall handler
- *
- * Registers on entry:
- *
- * @param %rcx Userspace return address.
- * @param %r11 Userspace RLFAGS.
- *
- * @param %rax Syscall number.
- * @param %rdi 1st syscall argument.
- * @param %rsi 2nd syscall argument.
- * @param %rdx 3rd syscall argument.
- * @param %r10 4th syscall argument. Used instead of RCX because
- *             the SYSCALL instruction clobbers it.
- * @param %r8  5th syscall argument.
- * @param %r9  6th syscall argument.
- *
- * @return Return value is in %rax.
- *
- */
-syscall_entry:
-	/* Switch to hidden %gs */
-	swapgs
-	
-	/*
-	 * %gs:0 Scratch space for this thread's user RSP
-	 * %gs:8 Address to be used as this thread's kernel RSP
-	 */
-	
-	movq %rsp, %gs:0  /* save this thread's user RSP */
-	movq %gs:8, %rsp  /* set this thread's kernel RSP */
-	
-	/* Switch back to remain consistent */
-	swapgs
-	sti
-	
-	pushq %rcx
-	pushq %r11
-	pushq %rbp
-	
-	xorq %rbp, %rbp  /* stop the stack traces here */
-	
-	/* Copy the 4th argument where it is expected  */
-	movq %r10, %rcx
-	pushq %rax
-	
-	call syscall_handler
-	
-	addq $8, %rsp
-	
-	popq %rbp
-	popq %r11
-	popq %rcx
-	
-	cli
-	swapgs
-	
-	/* Restore the user RSP */
-	movq %gs:0, %rsp
-	swapgs
-	
-	sysretq
-
-.data
-.global interrupt_handler_size
-
-interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Index: kernel/arch/amd64/src/boot/boot.S
===================================================================
--- kernel/arch/amd64/src/boot/boot.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/amd64/src/boot/boot.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -192,5 +192,6 @@
  * some hints.
  *
- * @param %esi NULL-terminated string to print.
+ * @param %esi Pointer to the NULL-terminated string
+ *             to be print.
  *
  */
@@ -295,5 +296,6 @@
  * and CONFIG_FB is disabled.
  *
- * @param %esi NULL-terminated string to print.
+ * @param %esi Pointer to the NULL-terminated string
+ *             to be print.
  *
  */
@@ -450,5 +452,6 @@
  * then this function does nothing.
  *
- * @param %rdi NULL-terminated string to print.
+ * @param %rdi Pointer to the NULL-terminated string
+ *             to be printed.
  *
  */
Index: kernel/arch/arm32/src/asm.S
===================================================================
--- kernel/arch/arm32/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/arm32/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -36,4 +36,5 @@
 .global memcpy_from_uspace_failover_address
 .global memcpy_to_uspace_failover_address
+.global early_putchar
 
 memsetb:
@@ -108,2 +109,5 @@
 	mov r0, #0
 	ldmia sp!, {r4, r5, pc}
+
+early_putchar:
+	mov pc, lr
Index: kernel/arch/ia32/src/asm.S
===================================================================
--- kernel/arch/ia32/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/ia32/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -38,6 +38,8 @@
 #define ERROR_WORD_INTERRUPT_LIST  0x00027d00
 
+#include <arch/pm.h>
+#include <arch/mm/page.h>
+
 .text
-
 .global paging_on
 .global enable_l_apic_in_msr
@@ -50,5 +52,5 @@
 .global memcpy_to_uspace
 .global memcpy_to_uspace_failover_address
-
+.global early_putchar
 
 /* Wrapper for generic memsetb */
@@ -405,5 +407,5 @@
 	
 	.align INTERRUPT_ALIGN
-	.if (\n- \i) - 1
+	.if (\n - \i) - 1
 		handler "(\i + 1)", \n
 	.endif
@@ -411,5 +413,5 @@
 
 /* Keep in sync with pm.h! */
-IDT_ITEMS = 64
+#define IDT_ITEMS  64
 
 .align INTERRUPT_ALIGN
@@ -419,4 +421,138 @@
 	h_end:
 
+/** Print Unicode character to EGA display.
+ *
+ * If CONFIG_EGA is undefined or CONFIG_FB is defined
+ * then this function does nothing.
+ *
+ * Since the EGA can only display Extended ASCII (usually
+ * ISO Latin 1) characters, some of the Unicode characters
+ * can be displayed in a wrong way. Only the newline character
+ * is interpreted, all other characters (even unprintable) are
+ * printed verbatim.
+ *
+ * @param %ebp+0x08 Unicode character to be printed.
+ *
+ */
+early_putchar:
+	
+#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
+	
+	/* Prologue, save preserved registers */
+	pushl %ebp
+	movl %esp, %ebp
+	pushl %ebx
+	pushl %esi
+	pushl %edi
+	
+	movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
+	xorl %eax, %eax
+	
+	/* Read bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	shl $8, %ax
+	
+	/* Read bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	inb %dx, %al
+	
+	/* Sanity check for the cursor on screen */
+	cmp $2000, %ax
+	jb early_putchar_cursor_ok
+	
+		movw $1998, %ax
+	
+	early_putchar_cursor_ok:
+	
+	movw %ax, %bx
+	shl $1, %eax
+	addl %eax, %edi
+	
+	movl 0x08(%ebp), %eax
+	
+	cmp $0x0a, %al
+	jne early_putchar_print
+	
+		/* Interpret newline */
+		
+		movw %bx, %ax  /* %bx -> %dx:%ax */
+		xorw %dx, %dx
+		
+		movw $80, %cx
+		idivw %cx, %ax  /* %dx = %bx % 80 */
+		
+		/* %bx <- %bx + 80 - (%bx % 80) */
+		addw %cx, %bx
+		subw %dx, %bx
+		
+		jmp early_putchar_newline
+	
+	early_putchar_print:
+	
+		/* Print character */
+		
+		movb $0x0e, %ah  /* black background, yellow foreground */
+		stosw
+	
+	early_putchar_newline:
+	
+	/* Sanity check for the cursor on the last line */
+	inc %bx
+	cmp $2000, %bx
+	jb early_putchar_no_scroll
+	
+		/* Scroll the screen (24 rows) */
+		movl $(PA2KA(0xb80a0)), %esi
+		movl $(PA2KA(0xb8000)), %edi
+		movl $1920, %ecx
+		rep movsw
+		
+		/* Clear the 24th row */
+		xorl %eax, %eax
+		movl $80, %ecx
+		rep stosw
+		
+		/* Go to row 24 */
+		movw $1920, %bx
+	
+	early_putchar_no_scroll:
+	
+	/* Write bits 8 - 15 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xe, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bh, %al
+	outb %al, %dx
+	
+	/* Write bits 0 - 7 of the cursor address */
+	movw $0x3d4, %dx
+	movb $0xf, %al
+	outb %al, %dx
+	
+	movw $0x3d5, %dx
+	movb %bl, %al
+	outb %al, %dx
+	
+	/* Epilogue, restore preserved registers */
+	popl %edi
+	popl %esi
+	popl %ebx
+	leave
+	
+#endif
+	
+	ret
+
 .data
 .global interrupt_handler_size
Index: kernel/arch/ia64/src/asm.S
===================================================================
--- kernel/arch/ia64/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/ia64/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -200,2 +200,6 @@
 	
 	rfi ;;
+
+.global early_putchar
+early_putchar:
+	br.ret.sptk.many b0
Index: kernel/arch/mips32/src/asm.S
===================================================================
--- kernel/arch/mips32/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/mips32/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -307,2 +307,7 @@
 	j $ra
 	nop
+
+.global early_putchar
+early_putchar:
+	j $ra
+	nop
Index: kernel/arch/ppc32/src/asm.S
===================================================================
--- kernel/arch/ppc32/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/ppc32/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -284,2 +284,5 @@
 	xor r3, r3, r3
 	blr
+
+early_putchar:
+	blr
Index: kernel/arch/sparc64/src/asm.S
===================================================================
--- kernel/arch/sparc64/src/asm.S	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/arch/sparc64/src/asm.S	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -273,2 +273,7 @@
 	ba %xcc, _memsetw
 	nop
+
+.global early_putchar
+early_putchar:
+	retl
+	nop
Index: kernel/generic/include/console/console.h
===================================================================
--- kernel/generic/include/console/console.h	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/include/console/console.h	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -56,4 +56,6 @@
 extern outdev_t *stdout;
 
+extern void early_putchar(wchar_t);
+
 extern indev_t *stdin_wire(void);
 extern void stdout_wire(outdev_t *outdev);
Index: kernel/generic/include/context.h
===================================================================
--- kernel/generic/include/context.h	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/include/context.h	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -87,6 +87,8 @@
  *
  * @param ctx Context structure.
+ *
  */
-static inline void context_restore(context_t *ctx)
+static inline void __attribute__((no_instrument_function))
+    context_restore(context_t *ctx)
 {
 	context_restore_arch(ctx);
Index: kernel/generic/include/debug.h
===================================================================
--- kernel/generic/include/debug.h	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/include/debug.h	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -98,7 +98,4 @@
 	} while (0)
 
-extern void __cyg_profile_func_enter(void *, void *);
-extern void __cyg_profile_func_exit(void *, void *);
-
 #else /* CONFIG_LOG */
 
@@ -107,4 +104,11 @@
 #endif /* CONFIG_LOG */
 
+#ifdef CONFIG_TRACE
+
+extern void __cyg_profile_func_enter(void *, void *);
+extern void __cyg_profile_func_exit(void *, void *);
+
+#endif /* CONFIG_TRACE */
+
 #endif
 
Index: kernel/generic/include/macros.h
===================================================================
--- kernel/generic/include/macros.h	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/include/macros.h	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -47,5 +47,6 @@
  * @param sz2 Size of the second interval.
  */
-static inline int overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2)
+static inline int __attribute__((no_instrument_function))
+    overlaps(uintptr_t s1, size_t sz1, uintptr_t s2, size_t sz2)
 {
 	uintptr_t e1 = s1 + sz1;
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/src/console/console.c	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -294,5 +294,17 @@
 		stdout->op->write(stdout, ch, silent);
 	else {
-		/* The character is just in the kernel log */
+		/*
+		 * No standard output routine defined yet.
+		 * The character is still stored in the kernel log
+		 * for possible future output.
+		 *
+		 * The early_putchar() function is used to output
+		 * the character for low-level debugging purposes.
+		 * Note that the early_putc() function might be
+		 * a no-op on certain hardware configurations.
+		 *
+		 */
+		early_putchar(ch);
+		
 		if (klog_stored < klog_len)
 			klog_stored++;
Index: kernel/generic/src/debug/debug.c
===================================================================
--- kernel/generic/src/debug/debug.c	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/src/debug/debug.c	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -36,5 +36,5 @@
  */
 
-#ifdef CONFIG_LOG
+#ifdef CONFIG_TRACE
 
 #include <debug.h>
@@ -52,5 +52,6 @@
 	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
 	    &call_site_off) == EOK)
-		printf("%s:%p->%s\n", call_site_sym, call_site_off, fn_sym);
+		printf("%s+%" PRIp "->%s\n", call_site_sym, call_site_off,
+		    fn_sym);
 	else
 		printf("->%s\n", fn_sym);
@@ -66,10 +67,11 @@
 	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
 	    &call_site_off) == EOK)
-		printf("%s:%p<-%s\n", call_site_sym, call_site_off, fn_sym);
+		printf("%s+%" PRIp "<-%s\n", call_site_sym, call_site_off,
+		    fn_sym);
 	else
 		printf("<-%s\n", fn_sym);
 }
 
-#endif /* CONFIG_LOG */
+#endif /* CONFIG_TRACE */
 
 /** @}
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision ad8f03d212303cc4e32fd22699ca17c7d76a956c)
+++ kernel/generic/src/main/main.c	(revision da52547b3a8fc0b23125d3adbd5622075264ee53)
@@ -131,5 +131,5 @@
  *
  */
-void main_bsp(void)
+void __attribute__((no_instrument_function)) main_bsp(void)
 {
 	config.cpu_count = 1;
@@ -183,6 +183,6 @@
 	version_print();
 	
-	LOG("\nconfig.base=%#" PRIp " config.kernel_size=%" PRIs
-	    "\nconfig.stack_base=%#" PRIp " config.stack_size=%" PRIs,
+	LOG("\nconfig.base=%p config.kernel_size=%" PRIs
+	    "\nconfig.stack_base=%p config.stack_size=%" PRIs,
 	    config.base, config.kernel_size, config.stack_base,
 	    config.stack_size);
@@ -241,6 +241,6 @@
 		size_t i;
 		for (i = 0; i < init.cnt; i++)
-			LOG("init[%" PRIs "].addr=%#" PRIp ", init[%" PRIs
-			    "].size=%#" PRIs, i, init.tasks[i].addr, i,
+			LOG("init[%" PRIs "].addr=%p, init[%" PRIs
+			    "].size=%" PRIs, i, init.tasks[i].addr, i,
 			    init.tasks[i].size);
 	} else
