Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/amd64.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+ /** @addtogroup amd64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch.h>
+
+#include <arch/types.h>
+
+#include <config.h>
+
+#include <proc/thread.h>
+#include <arch/drivers/ega.h>
+#include <arch/drivers/vesa.h>
+#include <genarch/i8042/i8042.h>
+#include <arch/drivers/i8254.h>
+#include <arch/drivers/i8259.h>
+
+#include <arch/bios/bios.h>
+#include <arch/mm/memory_init.h>
+#include <arch/cpu.h>
+#include <print.h>
+#include <arch/cpuid.h>
+#include <genarch/acpi/acpi.h>
+#include <panic.h>
+#include <interrupt.h>
+#include <arch/syscall.h>
+#include <arch/debugger.h>
+#include <syscall/syscall.h>
+#include <console/console.h>
+
+
+/** Disable I/O on non-privileged levels
+ *
+ * Clean IOPL(12,13) and NT(14) flags in EFLAGS register
+ */
+static void clean_IOPL_NT_flags(void)
+{
+	asm
+	(
+		"pushfq;"
+		"pop %%rax;"
+		"and $~(0x7000),%%rax;"
+		"pushq %%rax;"
+		"popfq;"
+		:
+		:
+		:"%rax"
+	);
+}
+
+/** Disable alignment check
+ *
+ * Clean AM(18) flag in CR0 register 
+ */
+static void clean_AM_flag(void)
+{
+	asm
+	(
+		"mov %%cr0,%%rax;"
+		"and $~(0x40000),%%rax;"
+		"mov %%rax,%%cr0;"
+		:
+		:
+		:"%rax"
+	);
+}
+
+void arch_pre_mm_init(void)
+{
+	struct cpu_info cpuid_s;
+
+	cpuid(AMD_CPUID_EXTENDED,&cpuid_s);
+	if (! (cpuid_s.cpuid_edx & (1<<AMD_EXT_NOEXECUTE)))
+		panic("Processor does not support No-execute pages.\n");
+
+	cpuid(INTEL_CPUID_STANDARD,&cpuid_s);
+	if (! (cpuid_s.cpuid_edx & (1<<INTEL_FXSAVE)))
+		panic("Processor does not support FXSAVE/FXRESTORE.\n");
+	
+	if (! (cpuid_s.cpuid_edx & (1<<INTEL_SSE2)))
+		panic("Processor does not support SSE2 instructions.\n");
+
+	/* Enable No-execute pages */
+	set_efer_flag(AMD_NXE_FLAG);
+	/* Enable FPU */
+	cpu_setup_fpu();
+
+	/* Initialize segmentation */
+	pm_init();
+
+        /* Disable I/O on nonprivileged levels
+	 * clear the NT(nested-thread) flag 
+	 */
+	clean_IOPL_NT_flags();
+	/* Disable alignment check */
+	clean_AM_flag();
+
+	if (config.cpu_active == 1) {
+		bios_init();
+		i8259_init();	/* PIC */
+		i8254_init();	/* hard clock */
+
+		#ifdef CONFIG_SMP
+		exc_register(VECTOR_TLB_SHOOTDOWN_IPI, "tlb_shootdown",
+			     tlb_shootdown_ipi);
+		#endif /* CONFIG_SMP */
+	}
+}
+
+void arch_post_mm_init(void)
+{
+	if (config.cpu_active == 1) {
+#ifdef CONFIG_FB
+		if (vesa_present()) 
+			vesa_init();
+		else
+#endif
+			ega_init();	/* video */
+		/* Enable debugger */
+		debugger_init();
+		/* Merge all memory zones to 1 big zone */
+		zone_merge_all();
+	}
+	/* Setup fast SYSCALL/SYSRET */
+	syscall_setup_cpu();
+	
+}
+
+void arch_pre_smp_init(void)
+{
+	if (config.cpu_active == 1) {
+		memory_print_map();
+		
+		#ifdef CONFIG_SMP
+		acpi_init();
+		#endif /* CONFIG_SMP */
+	}
+}
+
+void arch_post_smp_init(void)
+{
+	i8042_init();	/* keyboard controller */
+}
+
+void calibrate_delay_loop(void)
+{
+	i8254_calibrate_delay_loop();
+	i8254_normal_operation();
+}
+
+/** Set thread-local-storage pointer
+ *
+ * TLS pointer is set in FS register. Unfortunately the 64-bit
+ * part can be set only in CPL0 mode.
+ *
+ * The specs say, that on %fs:0 there is stored contents of %fs register,
+ * we need not to go to CPL0 to read it.
+ */
+unative_t sys_tls_set(unative_t addr)
+{
+	THREAD->arch.tls = addr;
+	write_msr(AMD_MSR_FS, addr);
+	return 0;
+}
+
+/** Acquire console back for kernel
+ *
+ */
+void arch_grab_console(void)
+{
+	i8042_grab();
+}
+/** Return console to userspace
+ *
+ */
+void arch_release_console(void)
+{
+	i8042_release();
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/asm_utils.S
===================================================================
--- kernel/arch/amd64/src/asm_utils.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/asm_utils.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,303 @@
+#
+# 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 120
+
+#define IOFFSET_RAX 0x0
+#define IOFFSET_RBX 0x8
+#define IOFFSET_RCX 0x10
+#define IOFFSET_RDX 0x18
+#define IOFFSET_RSI 0x20
+#define IOFFSET_RDI 0x28
+#define IOFFSET_R8 0x30
+#define IOFFSET_R9 0x38
+#define IOFFSET_R10 0x40
+#define IOFFSET_R11 0x48
+#define IOFFSET_R12 0x50
+#define IOFFSET_R13 0x58
+#define IOFFSET_R14 0x60
+#define IOFFSET_R15 0x68
+#define IOFFSET_RBP 0x70
+
+#  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 panic_printf
+
+panic_printf:
+	movq $halt, (%rsp)
+	jmp printf
+
+.global cpuid
+.global has_cpuid
+.global rdtsc
+.global read_efer_flag
+.global set_efer_flag
+.global memcpy
+.global memcpy_from_uspace
+.global memcpy_to_uspace
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
+
+#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_SRC on success, 0 on failure.
+ */
+memcpy:
+memcpy_from_uspace:
+memcpy_to_uspace:
+	movq MEMCPY_SRC, %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:
+	pushfq			# store flags
+	popq %rax		# read flags
+	movq %rax,%rdx		# copy flags
+	btcl $21,%edx		# swap the ID bit
+	pushq %rdx
+	popfq			# propagate the change into flags
+	pushfq
+	popq %rdx		# read flags	
+	andl $(1<<21),%eax	# interested only in ID bit
+	andl $(1<<21),%edx
+	xorl %edx,%eax		# 0 if not supported, 1 if supported
+	ret
+
+cpuid:
+	movq %rbx, %r10  # we have to preserve rbx across function calls
+
+	movl %edi,%eax	# load the command into %eax
+
+	cpuid	
+	movl %eax,0(%rsi)
+	movl %ebx,4(%rsi)
+	movl %ecx,8(%rsi)
+	movl %edx,12(%rsi)
+
+	movq %r10, %rbx
+	ret
+
+rdtsc:
+	xorq %rax,%rax
+	rdtsc
+	ret
+
+set_efer_flag:
+	movq $0xc0000080, %rcx
+	rdmsr
+	btsl %edi, %eax
+	wrmsr
+	ret
+	
+read_efer_flag:	
+	movq $0xc0000080, %rcx
+	rdmsr
+	ret 		
+
+# Push all general purpose registers on stack except %rbp, %rsp
+.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)
+#ifdef CONFIG_DEBUG_ALLREGS	
+	movq %rbx, IOFFSET_RBX(%rsp)
+	movq %rbp, IOFFSET_RBP(%rsp)
+	movq %r12, IOFFSET_R12(%rsp)
+	movq %r13, IOFFSET_R13(%rsp)
+	movq %r14, IOFFSET_R14(%rsp)
+	movq %r15, IOFFSET_R15(%rsp)
+#endif
+.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
+#ifdef CONFIG_DEBUG_ALLREGS	
+	movq IOFFSET_RBX(%rsp), %rbx
+	movq IOFFSET_RBP(%rsp), %rbp
+	movq IOFFSET_R12(%rsp), %r12
+	movq IOFFSET_R13(%rsp), %r13
+	movq IOFFSET_R14(%rsp), %r14
+	movq IOFFSET_R15(%rsp), %r15
+#endif
+.endm
+
+#ifdef CONFIG_DEBUG_ALLREGS
+# define INTERRUPT_ALIGN 256
+#else
+# define INTERRUPT_ALIGN 128
+#endif
+	
+## 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
+
+	movq $(\i), %rdi   	# %rdi - first parameter
+	movq %rsp, %rsi   	# %rsi - pointer to istate
+	call exc_dispatch 	# exc_dispatch(i, istate)
+	
+	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:
+
+	
+syscall_entry:
+	# Switch to hidden gs	
+	swapgs
+	# %gs:0 now points to pointer to stack page
+	mov %gs:0, %r10     # We have a ptr to stack page in r10
+	addq $PAGE_SIZE-16, %r10 # We need some space to store old %sp
+	
+	movq %rsp, 0(%r10)  # Save old stack pointer to stack
+	movq %r10, %rsp     # Change to new stack
+	pushq %rcx          # Return address
+	pushq %r11          # Save flags
+
+	# Switch back to remain consistent
+	swapgs 
+
+	sti
+	movq %r9, %rcx      # Exchange last parameter as a third
+	
+	call syscall_handler
+	cli                 # We will be touching stack pointer
+		
+	popq %r11
+	popq %rcx
+	movq 0(%rsp), %rsp
+	sysretq
+		
+		
+.data
+.global interrupt_handler_size
+
+interrupt_handler_size: .quad (h_end-h_start)/IDT_ITEMS
Index: kernel/arch/amd64/src/bios
===================================================================
--- kernel/arch/amd64/src/bios	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/bios	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../ia32/src/bios
Index: kernel/arch/amd64/src/boot/boot.S
===================================================================
--- kernel/arch/amd64/src/boot/boot.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/boot/boot.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,515 @@
+#
+# Copyright (C) 2005 Ondrej Palkovsky
+# Copyright (C) 2006 Martin Decky
+# 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.
+#
+
+#include <arch/boot/boot.h>
+#include <arch/boot/memmap.h>
+#include <arch/mm/page.h>	
+#include <arch/mm/ptl.h>
+#include <arch/pm.h>
+#include <arch/cpu.h>
+#include <arch/cpuid.h>
+
+#define START_STACK	(BOOT_OFFSET - BOOT_STACK_SIZE)
+	
+.section K_TEXT_START, "ax"
+
+.code32
+.align 4
+.global multiboot_image_start
+multiboot_header:
+	.long MULTIBOOT_HEADER_MAGIC
+	.long MULTIBOOT_HEADER_FLAGS
+	.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)	# checksum
+	.long multiboot_header
+	.long unmapped_ktext_start
+	.long 0
+	.long 0
+	.long multiboot_image_start
+
+multiboot_image_start:
+	movl $START_STACK, %esp			# initialize stack pointer
+	lgdt bootstrap_gdtr				# initialize Global Descriptor Table register
+
+	movw $gdtselector(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %ds							# kernel data + stack
+	movw %cx, %ss
+	# Simics seems to remove hidden part of GS on entering user mode
+	#  when _visible_ part of GS does not point to user-mode segment
+	movw $gdtselector(UDATA_DES), %cx
+	movw %cx, %fs
+	movw %cx, %gs
+	
+	jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
+	multiboot_meeting_point:
+	
+	movl %eax, grub_eax							# save parameters from GRUB
+	movl %ebx, grub_ebx
+	
+#ifdef CONFIG_FB
+	mov $vesa_init, %esi;
+	mov $VESA_INIT_SEGMENT << 4, %edi
+	mov $e_vesa_init - vesa_init, %ecx
+	cld
+	rep movsb
+
+	mov $VESA_INIT_SEGMENT << 4, %edi
+	jmpl *%edi
+	
+	vesa_meeting_point:
+	
+	mov %esi, KA2PA(vesa_ph_addr)
+	mov %di, KA2PA(vesa_height)
+	shr $16, %edi
+	mov %di, KA2PA(vesa_width)
+	mov %bx, KA2PA(vesa_scanline)
+	shr $16, %ebx
+	mov %bx, KA2PA(vesa_bpp)
+#endif	
+
+	# Protected 32-bit. We want to reuse the code-seg descriptor,
+	# the Default operand size must not be 1 when entering long mode
+	
+	movl $0x80000000, %eax  
+ 	cpuid
+ 	cmp $0x80000000, %eax						# any function > 80000000h?
+	jbe long_mode_unsupported
+	movl $(AMD_CPUID_EXTENDED), %eax			# Extended function code 80000001
+	cpuid
+	bt $29, %edx								# Test if long mode is supported.
+ 	jc long_mode_supported
+
+	long_mode_unsupported:
+		cli
+		hlt
+	
+	long_mode_supported:
+	
+	# Enable 64-bit page transaltion entries - CR4.PAE = 1.
+	# Paging is not enabled until after long mode is enabled
+	
+	movl %cr4, %eax
+	btsl $5, %eax
+	movl %eax, %cr4
+
+	# Set up paging tables
+	
+	leal ptl_0, %eax
+	movl %eax, %cr3
+	
+	# Enable long mode
+	
+	movl $EFER_MSR_NUM, %ecx	# EFER MSR number
+	rdmsr						# Read EFER
+	btsl $AMD_LME_FLAG, %eax	# Set LME=1
+	wrmsr						# Write EFER
+	
+	# Enable paging to activate long mode (set CR0.PG=1)
+	
+	movl %cr0, %eax
+	btsl $31, %eax
+	movl %eax, %cr0
+	
+	# At this point we are in compatibility mode
+	
+	jmpl $gdtselector(KTEXT_DES), $start64
+
+.code64
+start64:
+	movq $(PA2KA(START_STACK)), %rsp
+	movl grub_eax, %eax
+	movl grub_ebx, %ebx
+	
+	cmpl $MULTIBOOT_LOADER_MAGIC, %eax				# compare GRUB signature
+	je valid_boot
+		
+		xorl %ecx, %ecx							# no memory size or map available
+		movl %ecx, e801memorysize
+		movl %ecx, e820counter
+		
+		jmp invalid_boot
+		
+	valid_boot:
+		
+		movl (%ebx), %eax						# ebx = physical address of struct multiboot_info
+		
+		bt $0, %eax								# mbi->flags[0] (mem_lower, mem_upper valid)
+		jc mem_valid
+			
+			xorl %ecx, %ecx
+			jmp mem_invalid
+			
+		mem_valid:
+		movl 4(%ebx), %ecx						# mbi->mem_lower
+		addl 8(%ebx), %ecx						# mbi->mem_upper
+		
+		mem_invalid:
+		movl %ecx, e801memorysize
+		
+		bt $3, %eax								# mbi->flags[3] (mods_count, mods_addr valid)
+		jc mods_valid
+			
+			xorq %rcx, %rcx
+			movq %rcx, init
+			jmp mods_end
+		
+		mods_valid:
+		
+		xorq %rcx, %rcx
+		movl 20(%ebx), %ecx						# mbi->mods_count
+		movq %rcx, init
+		
+		cmpl $0, %ecx
+		je mods_end
+		
+		movl 24(%ebx), %esi						# mbi->mods_addr
+		movq $init, %rdi
+		
+		mods_loop:
+			
+			xorq %rdx, %rdx
+			movl 0(%esi), %edx					# mods->mod_start
+			movq $0xffff800000000000, %r10
+			addq %r10, %rdx
+			movq %rdx, 8(%rdi)
+			
+			xorq %rdx, %rdx
+			movl 4(%esi), %edx
+			subl 0(%esi), %edx					# mods->mod_end - mods->mod_start
+			movq %rdx, 16(%rdi)
+			
+			addl $16, %esi
+			addq $16, %rdi
+			
+			loop mods_loop
+			
+		mods_end:
+		
+		bt $6, %eax								# mbi->flags[6] (mmap_length, mmap_addr valid)	
+		jc mmap_valid
+			
+			xorl %edx, %edx
+			jmp mmap_invalid
+			
+		mmap_valid:
+		movl 44(%ebx), %ecx						# mbi->mmap_length
+		movl 48(%ebx), %esi						# mbi->mmap_addr
+		movq $e820table, %rdi
+		xorl %edx, %edx
+		
+		mmap_loop:
+			cmpl $0, %ecx
+			jle mmap_end
+			
+			movl 4(%esi), %eax					# mmap->base_addr_low
+			movl %eax, (%rdi)
+			
+			movl 8(%esi), %eax					# mmap->base_addr_high
+			movl %eax, 4(%rdi)
+			
+			movl 12(%esi), %eax					# mmap->length_low
+			movl %eax, 8(%rdi)
+			
+			movl 16(%esi), %eax					# mmap->length_high
+			movl %eax, 12(%rdi)
+			
+			movl 20(%esi), %eax					# mmap->type
+			movl %eax, 16(%rdi)
+			
+			movl (%esi), %eax					# mmap->size
+			addl $0x4, %eax
+			addl %eax, %esi
+			subl %eax, %ecx
+			addq $MEMMAP_E820_RECORD_SIZE, %rdi
+			incl %edx
+			jmp mmap_loop
+		
+		mmap_end:
+		
+		mmap_invalid:
+		movl %edx, e820counter
+		
+	invalid_boot:
+	
+#ifdef CONFIG_SMP
+	
+	# copy AP bootstrap routines below 1 MB
+	
+	movq $BOOT_OFFSET, %rsi
+	movq $AP_BOOT_OFFSET, %rdi
+	movq $_hardcoded_unmapped_size, %rcx
+	cld
+	rep movsb
+	
+#endif
+	
+	call main_bsp   # never returns
+	
+	cli
+	hlt
+
+#ifdef CONFIG_FB
+.code32
+vesa_init:
+	jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
+	
+.code16
+vesa_init_real:
+	
+	mov %cr0, %eax
+	and $~1, %eax
+	mov %eax, %cr0
+	
+	jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
+	
+vesa_init_real2:
+	
+	mov $VESA_INIT_SEGMENT, %bx
+	
+	mov %bx, %es
+	mov %bx, %fs
+	mov %bx, %gs
+	mov %bx, %ds
+	mov %bx, %ss
+	
+	movl $0x0000fffc, %esp
+    movl $0x0000fffc, %ebp
+	
+#define VESA_INFO_SIZE 1024
+
+#define VESA_MODE_LIST_PTR_OFFSET 14
+#define VESA_MODE_WIDTH_OFFSET 18
+#define VESA_MODE_HEIGHT_OFFSET 20
+#define VESA_MODE_BPP_OFFSET 25
+#define VESA_MODE_SCANLINE_OFFSET 16
+#define VESA_MODE_PHADDR_OFFSET 40
+
+#define VESA_END_OF_MODES 0xffff
+
+#define VESA_OK 0x4f
+
+#define VESA_GET_INFO 0x4f00
+#define VESA_GET_MODE_INFO 0x4f01
+#define VESA_SET_MODE 0x4f02
+
+#define CONFIG_VESA_BPP_a 255
+
+#if CONFIG_VESA_BPP == 24
+#undef CONFIG_VESA_BPP_a
+#define CONFIG_VESA_BPP_a 32
+#endif
+	
+	mov $VESA_GET_INFO, %ax
+	mov $e_vesa_init - vesa_init, %di
+	push %di
+	int $0x10
+	
+	pop %di
+	cmp $VESA_OK, %al
+	jnz 0f
+	
+	mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
+	mov %si, %gs
+	mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
+	
+	add $VESA_INFO_SIZE, %di
+	
+1:# Try next mode
+	mov %gs:(%si), %cx
+	cmp $VESA_END_OF_MODES, %cx
+	jz 0f
+	
+	inc %si
+	inc %si
+	push %cx
+	push %di
+	push %si
+	mov $VESA_GET_MODE_INFO, %ax
+	int $0x10
+	
+	pop %si
+	pop %di
+	pop %cx
+	cmp $VESA_OK, %al
+	jnz 0f
+	
+	mov $CONFIG_VESA_WIDTH, %ax
+	cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
+	jnz 1b
+	
+	mov $CONFIG_VESA_HEIGHT, %ax
+	cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
+	jnz 1b
+	
+	mov $CONFIG_VESA_BPP, %al
+	cmp VESA_MODE_BPP_OFFSET(%di), %al
+	jz 2f
+	
+	mov $CONFIG_VESA_BPP_a, %al
+	cmp VESA_MODE_BPP_OFFSET(%di), %al
+	jnz 1b
+	
+2:
+	
+	mov %cx, %bx
+	or $0xc000, %bx
+	push %di
+	mov $VESA_SET_MODE, %ax
+	int $0x10
+	
+	pop %di
+	cmp $VESA_OK, %al
+	jnz 0f
+	
+	mov VESA_MODE_PHADDR_OFFSET(%di), %esi
+	mov VESA_MODE_WIDTH_OFFSET(%di), %ax
+	shl $16, %eax
+	mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
+	mov VESA_MODE_BPP_OFFSET(%di), %bl
+	xor %bh, %bh
+	shl $16, %ebx
+	mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
+	mov %eax, %edi
+	
+8:
+	
+	mov %cr0, %eax
+	or $1, %eax
+	mov %eax, %cr0
+	
+	jmp 9f
+9:
+	
+	ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
+	
+0:# No prefered mode found
+	mov $0x111, %cx
+	push %di
+	push %cx
+	mov $VESA_GET_MODE_INFO, %ax
+	int $0x10
+	
+	pop %cx
+	pop %di
+	cmp $VESA_OK, %al
+	jnz 1f
+	jz 2b						# Force relative jump
+
+1:
+	mov $0x0003, %ax
+	int $0x10
+	mov $0xffffffff, %edi		# EGA text mode used, because of problems with VESA
+	xor %ax, %ax
+	jz 8b						# Force relative jump
+	
+	
+.code32
+vesa_init_protect:
+	movw $gdtselector(KDATA_DES), %cx
+	movw %cx, %es
+	movw %cx, %ds							# kernel data + stack
+	movw %cx, %ss
+	# Simics seems to remove hidden part of GS on entering user mode
+	#  when _visible_ part of GS does not point to user-mode segment
+	movw $gdtselector(UDATA_DES), %cx
+	movw %cx, %fs
+	movw %cx, %gs
+	
+	jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
+	
+.align 4
+e_vesa_init:
+#endif	
+				
+.section K_DATA_START, "aw", @progbits
+.align 4096
+
+# Identical mapping of first 64MB and the same of -2GB -> 0	
+.global ptl_2
+ptl_2:	
+	.quad 0x0 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0xa00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0xc00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0xe00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x1e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x2e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3000000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3200000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3400000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3600000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3800000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3a00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3c00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	.quad 0x3e00000 | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
+	
+.align 4096
+.global ptl_1
+ptl_1:
+	.quad ptl_2 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 509,8,0
+	.quad ptl_2 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 1,8,0
+	
+.align 4096
+.global ptl_0
+ptl_0:
+	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 255,8,0
+	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
+	.fill 254,8,0
+	.quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
+
+.global bootstrap_gdtr
+bootstrap_gdtr:
+	.word gdtselector(GDT_ITEMS)
+	.long KA2PA(gdt)
+
+grub_eax:
+	.long 0
+
+grub_ebx:
+	.long 0
Index: kernel/arch/amd64/src/context.S
===================================================================
--- kernel/arch/amd64/src/context.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/context.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,78 @@
+#
+# Copyright (C) 2001-2004 Jakub Jermar
+# 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.
+#
+
+.text
+
+.global context_save_arch
+.global context_restore_arch
+
+#include <arch/context_offset.h>
+
+## Save current CPU context
+#
+# Save CPU context to context_t variable
+# pointed by the 1st argument. Returns 1 in EAX.
+#
+context_save_arch:
+	movq (%rsp), %rdx     # the caller's return %eip
+	# In %edi is passed 1st argument
+	movq %rdx, OFFSET_PC(%rdi)
+	movq %rsp, OFFSET_SP(%rdi)
+	
+	movq %rbx, OFFSET_RBX(%rdi)
+	movq %rbp, OFFSET_RBP(%rdi)
+	movq %r12, OFFSET_R12(%rdi)
+	movq %r13, OFFSET_R13(%rdi)
+	movq %r14, OFFSET_R14(%rdi)
+	movq %r15, OFFSET_R15(%rdi)
+	
+	xorq %rax,%rax		# context_save returns 1
+	incq %rax
+	ret
+
+
+## Restore current CPU context
+#
+# Restore CPU context from context_t variable
+# pointed by the 1st argument. Returns 0 in EAX.
+#
+context_restore_arch:	
+	movq OFFSET_R15(%rdi), %r15
+	movq OFFSET_R14(%rdi), %r14
+	movq OFFSET_R13(%rdi), %r13
+	movq OFFSET_R12(%rdi), %r12
+	movq OFFSET_RBP(%rdi), %rbp
+	movq OFFSET_RBX(%rdi), %rbx	
+	
+	movq OFFSET_SP(%rdi), %rsp   # ctx->sp -> %rsp
+	
+	movq OFFSET_PC(%rdi), %rdx
+	movq %rdx,(%rsp)
+
+	xorq %rax,%rax		# context_restore returns 0
+	ret
Index: kernel/arch/amd64/src/cpu/cpu.c
===================================================================
--- kernel/arch/amd64/src/cpu/cpu.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/cpu/cpu.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * 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.
+ */
+
+/** @addtogroup amd64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/cpu.h>
+#include <arch/cpuid.h>
+#include <arch/pm.h>
+
+#include <arch.h>
+#include <arch/types.h>
+#include <print.h>
+#include <typedefs.h>
+#include <fpu_context.h>
+
+/*
+ * Identification of CPUs.
+ * Contains only non-MP-Specification specific SMP code.
+ */
+#define AMD_CPUID_EBX	0x68747541
+#define AMD_CPUID_ECX 	0x444d4163
+#define AMD_CPUID_EDX 	0x69746e65
+
+#define INTEL_CPUID_EBX	0x756e6547
+#define INTEL_CPUID_ECX 0x6c65746e
+#define INTEL_CPUID_EDX 0x49656e69
+
+
+enum vendor {
+	VendorUnknown=0,
+	VendorAMD,
+	VendorIntel
+};
+
+static char *vendor_str[] = {
+	"Unknown Vendor",
+	"AuthenticAMD",
+	"GenuineIntel"
+};
+
+
+/** Setup flags on processor so that we can use the FPU
+ *
+ * cr0.osfxsr = 1 -> we do support fxstor/fxrestor
+ * cr0.em = 0 -> we do not emulate coprocessor
+ * cr0.mp = 1 -> we do want lazy context switch
+ */
+void cpu_setup_fpu(void)
+{
+	__asm__ volatile (
+		"movq %%cr0, %%rax;"
+		"btsq $1, %%rax;" /* cr0.mp */
+		"btrq $2, %%rax;"  /* cr0.em */
+		"movq %%rax, %%cr0;"
+
+		"movq %%cr4, %%rax;"
+		"bts $9, %%rax;" /* cr4.osfxsr */
+		"movq %%rax, %%cr4;"
+		:
+		:
+		:"%rax"
+		);
+}
+
+/** Set the TS flag to 1. 
+ *
+ * If a thread accesses coprocessor, exception is run, which 
+ * does a lazy fpu context switch.
+ *
+ */
+void fpu_disable(void)
+{
+	__asm__	volatile (
+		"mov %%cr0,%%rax;"
+		"bts $3,%%rax;"
+		"mov %%rax,%%cr0;"
+		:
+		:
+		:"%rax"
+		);
+}
+
+void fpu_enable(void)
+{
+	__asm__	volatile (
+		"mov %%cr0,%%rax;"
+		"btr $3,%%rax;"
+		"mov %%rax,%%cr0;"
+		:
+		:
+		:"%rax"
+		);	
+}
+
+void cpu_arch_init(void)
+{
+	CPU->arch.tss = tss_p;
+	CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss);
+	CPU->fpu_owner = NULL;
+}
+
+void cpu_identify(void)
+{
+	cpu_info_t info;
+
+	CPU->arch.vendor = VendorUnknown;
+	if (has_cpuid()) {
+		cpuid(0, &info);
+
+		/*
+		 * Check for AMD processor.
+		 */
+		if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) {
+			CPU->arch.vendor = VendorAMD;
+		}
+
+		/*
+		 * Check for Intel processor.
+		 */		
+		if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) {
+			CPU->arch.vendor = VendorIntel;
+		}
+				
+		cpuid(1, &info);
+		CPU->arch.family = (info.cpuid_eax>>8)&0xf;
+		CPU->arch.model = (info.cpuid_eax>>4)&0xf;
+		CPU->arch.stepping = (info.cpuid_eax>>0)&0xf;						
+	}
+}
+
+void cpu_print_report(cpu_t* m)
+{
+	printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n",
+		m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping,
+		m->frequency_mhz);
+}
+
+/** @}
+ */
Index: kernel/arch/amd64/src/ddi/ddi.c
===================================================================
--- kernel/arch/amd64/src/ddi/ddi.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/ddi/ddi.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * 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.
+ */
+
+ /** @addtogroup amd64ddi
+ * @{
+ */
+/** @file
+ */
+
+#include <ddi/ddi.h>
+#include <arch/ddi/ddi.h>
+#include <proc/task.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <adt/bitmap.h>
+#include <mm/slab.h>
+#include <arch/pm.h>
+#include <errno.h>
+#include <arch/cpu.h>
+#include <arch.h>
+#include <align.h>
+
+/** Enable I/O space range for task.
+ *
+ * Interrupts are disabled and task is locked.
+ *
+ * @param task Task.
+ * @param ioaddr Startign I/O space address.
+ * @param size Size of the enabled I/O range.
+ *
+ * @return 0 on success or an error code from errno.h.
+ */
+int ddi_iospace_enable_arch(task_t *task, uintptr_t ioaddr, size_t size)
+{
+	count_t bits;
+
+	bits = ioaddr + size;
+	if (bits > IO_PORTS)
+		return ENOENT;
+
+	if (task->arch.iomap.bits < bits) {
+		bitmap_t oldiomap;
+		uint8_t *newmap;
+	
+		/*
+		 * The I/O permission bitmap is too small and needs to be grown.
+		 */
+		
+		newmap = (uint8_t *) malloc(BITS2BYTES(bits), FRAME_ATOMIC);
+		if (!newmap)
+			return ENOMEM;
+		
+		bitmap_initialize(&oldiomap, task->arch.iomap.map, task->arch.iomap.bits);
+		bitmap_initialize(&task->arch.iomap, newmap, bits);
+
+		/*
+		 * Mark the new range inaccessible.
+		 */
+		bitmap_set_range(&task->arch.iomap, oldiomap.bits, bits - oldiomap.bits);
+
+		/*
+		 * In case there really existed smaller iomap,
+		 * copy its contents and deallocate it.
+		 */		
+		if (oldiomap.bits) {
+			bitmap_copy(&task->arch.iomap, &oldiomap, oldiomap.bits);
+			free(oldiomap.map);
+		}
+	}
+
+	/*
+	 * Enable the range and we are done.
+	 */
+	bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
+
+	/*
+	 * Increment I/O Permission bitmap generation counter.
+	 */
+	task->arch.iomapver++;
+
+	return 0;
+}
+
+/** Install I/O Permission bitmap.
+ *
+ * Current task's I/O permission bitmap, if any, is installed
+ * in the current CPU's TSS.
+ *
+ * Interrupts must be disabled prior this call.
+ */
+void io_perm_bitmap_install(void)
+{
+	count_t bits;
+	ptr_16_64_t cpugdtr;
+	descriptor_t *gdt_p;
+	tss_descriptor_t *tss_desc;
+	count_t ver;
+
+	/* First, copy the I/O Permission Bitmap. */
+	spinlock_lock(&TASK->lock);
+	ver = TASK->arch.iomapver;
+	if ((bits = TASK->arch.iomap.bits)) {
+		bitmap_t iomap;
+	
+		ASSERT(TASK->arch.iomap.map);
+		bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
+		bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
+		/*
+		 * It is safe to set the trailing eight bits because of the extra
+		 * convenience byte in TSS_IOMAP_SIZE.
+		 */
+		bitmap_set_range(&iomap, ALIGN_UP(TASK->arch.iomap.bits, 8), 8);
+	}
+	spinlock_unlock(&TASK->lock);
+
+	/*
+	 * Second, adjust TSS segment limit.
+	 * Take the extra ending byte will all bits set into account. 
+	 */
+	gdtr_store(&cpugdtr);
+	gdt_p = (descriptor_t *) cpugdtr.base;
+	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits));
+	gdtr_load(&cpugdtr);
+	
+	/*
+         * Before we load new TSS limit, the current TSS descriptor
+         * type must be changed to describe inactive TSS.
+         */
+	tss_desc = (tss_descriptor_t *)	&gdt_p[TSS_DES];
+	tss_desc->type = AR_TSS;
+	tr_load(gdtselector(TSS_DES));
+	
+	/*
+	 * Update the generation count so that faults caused by
+	 * early accesses can be serviced.
+	 */
+	CPU->arch.iomapver_copy = ver;
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/debugger.c
===================================================================
--- kernel/arch/amd64/src/debugger.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/debugger.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+ /** @addtogroup amd64debug
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/debugger.h>
+#include <console/kconsole.h>
+#include <console/cmd.h>
+#include <symtab.h>
+#include <print.h>
+#include <panic.h>
+#include <interrupt.h>
+#include <arch/asm.h>
+#include <arch/cpu.h>
+#include <debug.h>
+#include <func.h>
+#include <smp/ipi.h>
+
+typedef struct  {
+	uintptr_t address;      /**< Breakpoint address */
+	int flags;              /**< Flags regarding breakpoint */
+	int counter;            /**< How many times the exception occured */
+} bpinfo_t;
+
+static bpinfo_t breakpoints[BKPOINTS_MAX];
+SPINLOCK_INITIALIZE(bkpoint_lock);
+
+static int cmd_print_breakpoints(cmd_arg_t *argv);
+static cmd_info_t bkpts_info = {
+	.name = "bkpts",
+	.description = "Print breakpoint table.",
+	.func = cmd_print_breakpoints,
+	.argc = 0,
+};
+
+#ifndef CONFIG_DEBUG_AS_WATCHPOINT
+
+static int cmd_del_breakpoint(cmd_arg_t *argv);
+static cmd_arg_t del_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t delbkpt_info = {
+	.name = "delbkpt",
+	.description = "delbkpt <number> - Delete breakpoint.",
+	.func = cmd_del_breakpoint,
+	.argc = 1,
+	.argv = &del_argv
+};
+
+static int cmd_add_breakpoint(cmd_arg_t *argv);
+static cmd_arg_t add_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t addbkpt_info = {
+	.name = "addbkpt",
+	.description = "addbkpt <&symbol> - new breakpoint.",
+	.func = cmd_add_breakpoint,
+	.argc = 1,
+	.argv = &add_argv
+};
+
+static cmd_arg_t addw_argv = {
+	.type = ARG_TYPE_INT
+};
+static cmd_info_t addwatchp_info = {
+	.name = "addwatchp",
+	.description = "addbwatchp <&symbol> - new write watchpoint.",
+	.func = cmd_add_breakpoint,
+	.argc = 1,
+	.argv = &addw_argv
+};
+
+#endif
+
+/** Print table of active breakpoints */
+int cmd_print_breakpoints(cmd_arg_t *argv)
+{
+	int i;
+	char *symbol;
+
+	printf("Breakpoint table.\n");
+	for (i=0; i < BKPOINTS_MAX; i++)
+		if (breakpoints[i].address) {
+			symbol = get_symtab_entry(breakpoints[i].address);
+			printf("%d. %p in %s\n",i,
+			       breakpoints[i].address, symbol);
+			printf("     Count(%d) ", breakpoints[i].counter);
+			printf("\n");
+		}
+	return 1;
+}
+
+/* Setup DR register according to table */
+static void setup_dr(int curidx)
+{
+	unative_t dr7;
+	bpinfo_t *cur = &breakpoints[curidx];
+	int flags = breakpoints[curidx].flags;
+
+	/* Disable breakpoint in DR7 */
+	dr7 = read_dr7();
+	dr7 &= ~(0x2 << (curidx*2));
+
+	if (cur->address) { /* Setup DR register */
+		/* Set breakpoint to debug registers */
+		switch (curidx) {
+		case 0:
+			write_dr0(cur->address);
+			break;
+		case 1:
+			write_dr1(cur->address);
+			break;
+		case 2:
+			write_dr2(cur->address);
+			break;
+		case 3:
+			write_dr3(cur->address);
+			break;
+		}
+		/* Set type to requested breakpoint & length*/
+		dr7 &= ~ (0x3 << (16 + 4*curidx));
+		dr7 &= ~ (0x3 << (18 + 4*curidx));
+		if ((flags & BKPOINT_INSTR)) {
+			;
+		} else {
+			if (sizeof(int) == 4)
+				dr7 |= ((unative_t) 0x3) << (18 + 4*curidx);
+			else /* 8 */
+				dr7 |= ((unative_t) 0x2) << (18 + 4*curidx);
+			
+			if ((flags & BKPOINT_WRITE))
+				dr7 |= ((unative_t) 0x1) << (16 + 4*curidx);
+			else if ((flags & BKPOINT_READ_WRITE))
+				dr7 |= ((unative_t) 0x3) << (16 + 4*curidx);
+		}
+
+		/* Enable global breakpoint */
+		dr7 |= 0x2 << (curidx*2);
+
+		write_dr7(dr7);
+		
+	} 
+}
+	
+/** Enable hardware breakpoint
+ *
+ *
+ * @param where Address of HW breakpoint
+ * @param flags Type of breakpoint (EXECUTE, WRITE)
+ * @return Debug slot on success, -1 - no available HW breakpoint
+ */
+int breakpoint_add(void * where, int flags, int curidx)
+{
+	ipl_t ipl;
+	int i;
+	bpinfo_t *cur;
+
+	ASSERT( flags & (BKPOINT_INSTR | BKPOINT_WRITE | BKPOINT_READ_WRITE));
+
+	ipl = interrupts_disable();
+	spinlock_lock(&bkpoint_lock);
+	
+	if (curidx == -1) {
+		/* Find free space in slots */
+		for (i=0; i<BKPOINTS_MAX; i++)
+			if (!breakpoints[i].address) {
+				curidx = i;
+				break;
+			}
+		if (curidx == -1) {
+			/* Too many breakpoints */
+			spinlock_unlock(&bkpoint_lock);
+			interrupts_restore(ipl);
+			return -1;
+		}
+	}
+	cur = &breakpoints[curidx];
+
+	cur->address = (uintptr_t) where;
+	cur->flags = flags;
+	cur->counter = 0;
+
+	setup_dr(curidx);
+
+	spinlock_unlock(&bkpoint_lock);
+	interrupts_restore(ipl);
+
+	/* Send IPI */
+#ifdef CONFIG_SMP
+//	ipi_broadcast(VECTOR_DEBUG_IPI);	
+#endif	
+
+	return curidx;
+}
+
+#ifdef amd64
+# define getip(x)  ((x)->rip)
+#else
+# define getip(x)  ((x)->eip)
+#endif
+
+static void handle_exception(int slot, istate_t *istate)
+{
+	ASSERT(breakpoints[slot].address);
+
+	/* Handle zero checker */
+	if (! (breakpoints[slot].flags & BKPOINT_INSTR)) {
+		if ((breakpoints[slot].flags & BKPOINT_CHECK_ZERO)) {
+			if (*((unative_t *) breakpoints[slot].address) != 0)
+				return;
+			printf("**** Found ZERO on address %p ****\n",
+			       slot, breakpoints[slot].address);
+		} else {
+			printf("Data watchpoint - new data: %p\n",
+			       *((unative_t *) breakpoints[slot].address));
+		}
+	}
+	printf("Reached breakpoint %d:%p(%s)\n", slot, getip(istate),
+	       get_symtab_entry(getip(istate)));
+	printf("***Type 'exit' to exit kconsole.\n");
+	atomic_set(&haltstate,1);
+	kconsole("debug");
+	atomic_set(&haltstate,0);
+}
+
+void breakpoint_del(int slot)
+{
+	bpinfo_t *cur;
+	ipl_t ipl;
+
+	ipl = interrupts_disable();
+	spinlock_lock(&bkpoint_lock);
+
+	cur = &breakpoints[slot];
+	if (!cur->address) {
+		spinlock_unlock(&bkpoint_lock);
+		interrupts_restore(ipl);
+		return;
+	}
+
+	cur->address = NULL;
+
+	setup_dr(slot);
+
+	spinlock_unlock(&bkpoint_lock);
+	interrupts_restore(ipl);
+#ifdef CONFIG_SMP
+//	ipi_broadcast(VECTOR_DEBUG_IPI);	
+#endif
+}
+
+#ifndef CONFIG_DEBUG_AS_WATCHPOINT
+
+/** Remove breakpoint from table */
+int cmd_del_breakpoint(cmd_arg_t *argv)
+{
+	if (argv->intval < 0 || argv->intval > BKPOINTS_MAX) {
+		printf("Invalid breakpoint number.\n");
+		return 0;
+	}
+	breakpoint_del(argv->intval);
+	return 1;
+}
+
+/** Add new breakpoint to table */
+static int cmd_add_breakpoint(cmd_arg_t *argv)
+{
+	int flags;
+	int id;
+
+	if (argv == &add_argv) {
+		flags = BKPOINT_INSTR;
+	} else { /* addwatchp */
+		flags = BKPOINT_WRITE;
+	}
+	printf("Adding breakpoint on address: %p\n", argv->intval);
+	id = breakpoint_add((void *)argv->intval, flags, -1);
+	if (id < 0)
+		printf("Add breakpoint failed.\n");
+	else
+		printf("Added breakpoint %d.\n", id);
+	
+	return 1;
+}
+#endif
+
+static void debug_exception(int n, istate_t *istate)
+{
+	unative_t dr6;
+	int i;
+	
+	/* Set RF to restart the instruction  */
+#ifdef amd64       
+	istate->rflags |= RFLAGS_RF;
+#else
+	istate->eflags |= EFLAGS_RF;
+#endif
+
+	dr6 = read_dr6();
+	for (i=0; i < BKPOINTS_MAX; i++) {
+		if (dr6 & (1 << i)) {
+			dr6 &= ~ (1 << i);
+			write_dr6(dr6);
+			
+			handle_exception(i, istate);
+		}
+	}
+}
+
+#ifdef CONFIG_SMP
+static void debug_ipi(int n, istate_t *istate)
+{
+	int i;
+
+	spinlock_lock(&bkpoint_lock);
+	for (i=0; i < BKPOINTS_MAX; i++)
+		setup_dr(i);
+	spinlock_unlock(&bkpoint_lock);
+}
+#endif
+
+/** Initialize debugger */
+void debugger_init()
+{
+	int i;
+
+	for (i=0; i<BKPOINTS_MAX; i++)
+		breakpoints[i].address = NULL;
+	
+	cmd_initialize(&bkpts_info);
+	if (!cmd_register(&bkpts_info))
+		panic("could not register command %s\n", bkpts_info.name);
+
+#ifndef CONFIG_DEBUG_AS_WATCHPOINT
+	cmd_initialize(&delbkpt_info);
+	if (!cmd_register(&delbkpt_info))
+		panic("could not register command %s\n", delbkpt_info.name);
+
+	cmd_initialize(&addbkpt_info);
+	if (!cmd_register(&addbkpt_info))
+		panic("could not register command %s\n", addbkpt_info.name);
+
+	cmd_initialize(&addwatchp_info);
+	if (!cmd_register(&addwatchp_info))
+		panic("could not register command %s\n", addwatchp_info.name);
+#endif
+	
+	exc_register(VECTOR_DEBUG, "debugger",
+		     debug_exception);
+#ifdef CONFIG_SMP
+	exc_register(VECTOR_DEBUG_IPI, "debugger_smp",
+		     debug_ipi);
+#endif
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/delay.S
===================================================================
--- kernel/arch/amd64/src/delay.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/delay.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,46 @@
+#
+# Copyright (C) 2001-2004 Jakub Jermar
+# 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.
+#
+
+#
+# Micro second delay loop functions.
+#
+
+.text
+
+.global asm_delay_loop
+.global asm_fake_loop
+
+asm_delay_loop:
+0:	dec %rdi
+	jnz 0b
+	ret
+
+asm_fake_loop:
+0:	dec %rdi
+	jz 0b
+	ret
Index: kernel/arch/amd64/src/drivers
===================================================================
--- kernel/arch/amd64/src/drivers	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/drivers	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../ia32/src/drivers
Index: kernel/arch/amd64/src/fpu_context.c
===================================================================
--- kernel/arch/amd64/src/fpu_context.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/fpu_context.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2005 Jakub Vana
+ * 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.
+ */
+
+ /** @addtogroup amd64	
+ * @{
+ */
+/** @file
+ *
+ */
+
+#include <fpu_context.h>
+#include <arch.h>
+#include <cpu.h>
+
+/** Save FPU (mmx, sse) context using fxsave instruction */
+void fpu_context_save(fpu_context_t *fctx)
+{
+	__asm__ volatile (
+		"fxsave %0"
+		: "=m"(*fctx)
+		);
+}
+
+/** Restore FPU (mmx,sse) context using fxrstor instruction */
+void fpu_context_restore(fpu_context_t *fctx)
+{
+	__asm__ volatile (
+		"fxrstor %0"
+		: "=m"(*fctx)
+		);
+}
+
+void fpu_init()
+{
+	/* TODO: Zero all SSE, MMX etc. registers */
+	__asm__ volatile (
+		"fninit;"
+	);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/interrupt.c
===================================================================
--- kernel/arch/amd64/src/interrupt.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/interrupt.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * 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.
+ */
+
+ /** @addtogroup amd64interrupt
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/interrupt.h>
+#include <print.h>
+#include <debug.h>
+#include <panic.h>
+#include <arch/drivers/i8259.h>
+#include <func.h>
+#include <cpu.h>
+#include <arch/asm.h>
+#include <mm/tlb.h>
+#include <mm/as.h>
+#include <arch.h>
+#include <symtab.h>
+#include <arch/asm.h>
+#include <proc/scheduler.h>
+#include <proc/thread.h>
+#include <proc/task.h>
+#include <synch/spinlock.h>
+#include <arch/ddi/ddi.h>
+#include <interrupt.h>
+#include <ipc/irq.h>
+
+void print_info_errcode(int n, istate_t *istate)
+{
+	char *symbol;
+/*	uint64_t *x = &istate->stack[0]; */
+
+	if (!(symbol=get_symtab_entry(istate->rip)))
+		symbol = "";
+
+	printf("-----EXCEPTION(%d) OCCURED----- ( %s )\n",n, __FUNCTION__);
+	printf("%%rip: %#llx (%s)\n",istate->rip, symbol);
+	printf("ERROR_WORD=%#llx\n", istate->error_word);
+	printf("%%rcs=%#llx, flags=%#llx, %%cr0=%#llx\n", istate->cs, istate->rflags, read_cr0());
+	printf("%%rax=%#llx, %%rcx=%#llx, %%rdx=%#llx\n", istate->rax, istate->rcx, istate->rdx);
+	printf("%%rsi=%#llx, %%rdi=%#llx, %%r8 =%#llx\n", istate->rsi, istate->rdi, istate->r8);
+	printf("%%r9 =%#llx, %%r10 =%#llx, %%r11=%#llx\n", istate->r9, istate->r10, istate->r11);
+#ifdef CONFIG_DEBUG_ALLREGS	
+	printf("%%r12=%#llx, %%r13=%#llx, %%r14=%#llx\n", istate->r12, istate->r13, istate->r14);
+	printf("%%r15=%#llx, %%rbx=%#llx, %%rbp=%#llx\n", istate->r15, istate->rbx, &istate->rbp);
+#endif
+	printf("%%rsp=%#llx\n", &istate->stack[0]);
+}
+
+/*
+ * Interrupt and exception dispatching.
+ */
+
+void (* disable_irqs_function)(uint16_t irqmask) = NULL;
+void (* enable_irqs_function)(uint16_t irqmask) = NULL;
+void (* eoi_function)(void) = NULL;
+
+void null_interrupt(int n, istate_t *istate)
+{
+	fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
+	print_info_errcode(n, istate);
+	panic("unserviced interrupt\n");
+}
+
+/** General Protection Fault. */
+void gp_fault(int n, istate_t *istate)
+{
+	if (TASK) {
+		count_t ver;
+
+		spinlock_lock(&TASK->lock);
+		ver = TASK->arch.iomapver;
+		spinlock_unlock(&TASK->lock);
+
+		if (CPU->arch.iomapver_copy != ver) {
+			/*
+			 * This fault can be caused by an early access
+			 * to I/O port because of an out-dated
+			 * I/O Permission bitmap installed on CPU.
+			 * Install the fresh copy and restart
+			 * the instruction.
+			 */
+			io_perm_bitmap_install();
+			return;
+		}
+		fault_if_from_uspace(istate, "general protection fault");
+	}
+
+	print_info_errcode(n, istate);
+	panic("general protection fault\n");
+}
+
+void ss_fault(int n, istate_t *istate)
+{
+	fault_if_from_uspace(istate, "stack fault");
+	print_info_errcode(n, istate);
+	panic("stack fault\n");
+}
+
+void nm_fault(int n, istate_t *istate)
+{
+#ifdef CONFIG_FPU_LAZY     
+	scheduler_fpu_lazy_request();
+#else
+	fault_if_from_uspace(istate, "fpu fault");
+	panic("fpu fault");
+#endif
+}
+
+void tlb_shootdown_ipi(int n, istate_t *istate)
+{
+	trap_virtual_eoi();
+	tlb_shootdown_ipi_recv();
+}
+
+void trap_virtual_enable_irqs(uint16_t irqmask)
+{
+	if (enable_irqs_function)
+		enable_irqs_function(irqmask);
+	else
+		panic("no enable_irqs_function\n");
+}
+
+void trap_virtual_disable_irqs(uint16_t irqmask)
+{
+	if (disable_irqs_function)
+		disable_irqs_function(irqmask);
+	else
+		panic("no disable_irqs_function\n");
+}
+
+void trap_virtual_eoi(void)
+{
+	if (eoi_function)
+		eoi_function();
+	else
+		panic("no eoi_function\n");
+
+}
+
+static void ipc_int(int n, istate_t *istate)
+{
+	ipc_irq_send_notif(n-IVT_IRQBASE);
+	trap_virtual_eoi();
+}
+
+
+/* Reregister irq to be IPC-ready */
+void irq_ipc_bind_arch(unative_t irq)
+{
+	if (irq == IRQ_CLK)
+		return;
+	exc_register(IVT_IRQBASE+irq, "ipc_int", ipc_int);
+	trap_virtual_enable_irqs(1 << irq);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/mm/as.c
===================================================================
--- kernel/arch/amd64/src/mm/as.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/mm/as.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/mm/as.c
Index: kernel/arch/amd64/src/mm/frame.c
===================================================================
--- kernel/arch/amd64/src/mm/frame.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/mm/frame.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/mm/frame.c
Index: kernel/arch/amd64/src/mm/memory_init.c
===================================================================
--- kernel/arch/amd64/src/mm/memory_init.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/mm/memory_init.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005 Josef Cejka
+ * 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.
+ */
+
+ /** @addtogroup amd64mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/boot/memmap.h>
+#include <arch/mm/memory_init.h>
+#include <arch/mm/page.h>
+#include <print.h>
+
+uint8_t e820counter = 0xff;
+struct e820memmap_ e820table[MEMMAP_E820_MAX_RECORDS];
+uint32_t e801memorysize;
+
+size_t get_memory_size(void) 
+{
+	return e801memorysize*1024;
+}
+
+void memory_print_map(void)
+{
+	uint8_t i;
+	
+	for (i=0;i<e820counter;i++) {
+		printf("E820 base: %#llx size: %#llx type: ", e820table[i].base_address, e820table[i].size);
+		switch (e820table[i].type) {
+			case MEMMAP_MEMORY_AVAILABLE: 
+				printf("available memory\n");
+				break;
+			case MEMMAP_MEMORY_RESERVED: 
+				printf("reserved memory\n");
+				break;
+			case MEMMAP_MEMORY_ACPI: 
+				printf("ACPI table\n");
+				break;
+			case MEMMAP_MEMORY_NVS: 
+				printf("NVS\n");
+				break;
+			case MEMMAP_MEMORY_UNUSABLE: 
+				printf("unusable memory\n");
+				break;
+			default:
+				printf("undefined memory type\n");
+		}
+	}
+
+}
+
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/mm/page.c
===================================================================
--- kernel/arch/amd64/src/mm/page.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/mm/page.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * 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.
+ */
+
+ /** @addtogroup amd64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/page.h>
+#include <genarch/mm/page_pt.h>
+#include <arch/mm/frame.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <mm/as.h>
+#include <arch/interrupt.h>
+#include <arch/asm.h>
+#include <config.h>
+#include <memstr.h>
+#include <interrupt.h>
+#include <print.h>
+#include <panic.h>
+#include <align.h>
+
+/* Definitions for identity page mapper */
+pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE)));
+pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE)));
+pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE)));
+extern pte_t ptl_0; /* From boot.S */
+
+#define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
+#define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
+#define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
+
+#define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page))))
+#define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page))))
+#define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page))))
+
+#define SETUP_PTL1(ptl0, page, tgt)  {	\
+	SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
+        SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
+    }
+#define SETUP_PTL2(ptl1, page, tgt)  {	\
+	SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
+        SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
+    }
+#define SETUP_PTL3(ptl2, page, tgt)  {	\
+	SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
+        SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
+    }
+#define SETUP_FRAME(ptl3, page, tgt)  {	\
+	SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
+        SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
+    }
+
+
+void page_arch_init(void)
+{
+	uintptr_t cur;
+	int i;
+	int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL;
+
+	if (config.cpu_active == 1) {
+		page_mapping_operations = &pt_mapping_operations;
+		
+		/*
+		 * PA2KA(identity) mapping for all frames.
+		 */
+		for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
+			/* Standard identity mapping */
+			page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
+		}
+		/* Upper kernel mapping
+		 * - from zero to top of kernel (include bottom addresses
+		 *   because some are needed for init )
+		 */
+		for (cur = PA2KA_CODE(0); cur < config.base+config.kernel_size; cur += FRAME_SIZE) {
+			page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
+		}
+		for (i=0; i < init.cnt; i++) {
+			for (cur=init.tasks[i].addr;cur < init.tasks[i].size; cur += FRAME_SIZE) {
+				page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
+			}
+		}
+
+		exc_register(14, "page_fault", (iroutine)page_fault);
+		write_cr3((uintptr_t) AS_KERNEL->page_table);
+	}
+	else {
+		write_cr3((uintptr_t) AS_KERNEL->page_table);
+	}
+}
+
+
+/** Identity page mapper
+ *
+ * We need to map whole physical memory identically before the page subsystem
+ * is initializaed. This thing clears page table and fills in the specific
+ * items.
+ */
+void ident_page_fault(int n, istate_t *istate)
+{
+	uintptr_t page;
+	static uintptr_t oldpage = 0;
+	pte_t *aptl_1, *aptl_2, *aptl_3;
+
+	page = read_cr2();
+	if (oldpage) {
+		/* Unmap old address */
+		aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
+		aptl_2 = PTL2_ADDR(aptl_1, oldpage);
+		aptl_3 = PTL3_ADDR(aptl_2, oldpage);
+
+		SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
+		if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
+			SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
+		if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
+			SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
+		if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
+			SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
+	}
+	if (PTL1_PRESENT(&ptl_0, page))
+		aptl_1 = PTL1_ADDR(&ptl_0, page);
+	else {
+		SETUP_PTL1(&ptl_0, page, helper_ptl1);
+		aptl_1 = helper_ptl1;
+	}
+	    
+	if (PTL2_PRESENT(aptl_1, page)) 
+		aptl_2 = PTL2_ADDR(aptl_1, page);
+	else {
+		SETUP_PTL2(aptl_1, page, helper_ptl2);
+		aptl_2 = helper_ptl2;
+	}
+
+	if (PTL3_PRESENT(aptl_2, page))
+		aptl_3 = PTL3_ADDR(aptl_2, page);
+	else {
+		SETUP_PTL3(aptl_2, page, helper_ptl3);
+		aptl_3 = helper_ptl3;
+	}
+	
+	SETUP_FRAME(aptl_3, page, page);
+
+	oldpage = page;
+}
+
+
+void page_fault(int n, istate_t *istate)
+{
+	uintptr_t page;
+	pf_access_t access;
+	
+	page = read_cr2();
+	
+	if (istate->error_word & PFERR_CODE_RSVD)
+		panic("Reserved bit set in page table entry.\n");
+	
+	if (istate->error_word & PFERR_CODE_RW)
+		access = PF_ACCESS_WRITE;
+	else if (istate->error_word & PFERR_CODE_ID)
+		access = PF_ACCESS_EXEC;
+	else
+		access = PF_ACCESS_READ;
+	
+	if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
+		fault_if_from_uspace(istate, "Page fault: %#x", page);
+
+		print_info_errcode(n, istate);
+		printf("Page fault address: %llx\n", page);
+		panic("page fault\n");
+	}
+}
+
+
+uintptr_t hw_map(uintptr_t physaddr, size_t size)
+{
+	if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
+		panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
+	
+	uintptr_t virtaddr = PA2KA(last_frame);
+	pfn_t i;
+	for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
+		page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE);
+	
+	last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
+	
+	return virtaddr;
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/mm/tlb.c
===================================================================
--- kernel/arch/amd64/src/mm/tlb.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/mm/tlb.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/mm/tlb.c
Index: kernel/arch/amd64/src/pm.c
===================================================================
--- kernel/arch/amd64/src/pm.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/pm.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2001-2004 Jakub Jermar
+ * Copyright (C) 2005-2006 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.
+ */
+
+ /** @addtogroup amd64	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/pm.h>
+#include <arch/mm/page.h>
+#include <arch/types.h>
+#include <arch/interrupt.h>
+#include <arch/asm.h>
+#include <interrupt.h>
+#include <mm/as.h>
+
+#include <config.h>
+
+#include <memstr.h>
+#include <mm/slab.h>
+#include <debug.h>
+
+/*
+ * There is no segmentation in long mode so we set up flat mode. In this
+ * mode, we use, for each privilege level, two segments spanning the
+ * whole memory. One is for code and one is for data.
+ */
+
+descriptor_t gdt[GDT_ITEMS] = {
+	/* NULL descriptor */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+	/* KTEXT descriptor */
+	{ .limit_0_15  = 0xffff, 
+	  .base_0_15   = 0, 
+	  .base_16_23  = 0, 
+	  .access      = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE , 
+	  .limit_16_19 = 0xf, 
+	  .available   = 0, 
+	  .longmode    = 1, 
+	  .special     = 0,
+	  .granularity = 1, 
+	  .base_24_31  = 0 },
+	/* KDATA descriptor */
+	{ .limit_0_15  = 0xffff, 
+	  .base_0_15   = 0, 
+	  .base_16_23  = 0, 
+	  .access      = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL, 
+	  .limit_16_19 = 0xf, 
+	  .available   = 0, 
+	  .longmode    = 0, 
+	  .special     = 0, 
+	  .granularity = 1, 
+	  .base_24_31  = 0 },
+	/* UDATA descriptor */
+	{ .limit_0_15  = 0xffff, 
+	  .base_0_15   = 0, 
+	  .base_16_23  = 0, 
+	  .access      = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER, 
+	  .limit_16_19 = 0xf, 
+	  .available   = 0, 
+	  .longmode    = 0, 
+	  .special     = 1, 
+	  .granularity = 1, 
+	  .base_24_31  = 0 },
+	/* UTEXT descriptor */
+	{ .limit_0_15  = 0xffff, 
+	  .base_0_15   = 0, 
+	  .base_16_23  = 0, 
+	  .access      = AR_PRESENT | AR_CODE | DPL_USER, 
+	  .limit_16_19 = 0xf, 
+	  .available   = 0, 
+	  .longmode    = 1, 
+	  .special     = 0, 
+	  .granularity = 1, 
+	  .base_24_31  = 0 },
+	/* KTEXT 32-bit protected, for protected mode before long mode */
+	{ .limit_0_15  = 0xffff, 
+	  .base_0_15   = 0, 
+	  .base_16_23  = 0, 
+	  .access      = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE, 
+	  .limit_16_19 = 0xf, 
+	  .available   = 0, 
+	  .longmode    = 0, 
+	  .special     = 1,
+	  .granularity = 1, 
+	  .base_24_31  = 0 },
+	/* TSS descriptor - set up will be completed later,
+	 * on AMD64 it is 64-bit - 2 items in table */
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+	/* VESA Init descriptor */
+#ifdef CONFIG_FB	
+	{ 0xffff, 0, VESA_INIT_SEGMENT>>12, AR_PRESENT | AR_CODE | DPL_KERNEL, 0xf, 0, 0, 0, 0, 0 }
+#endif
+};
+
+idescriptor_t idt[IDT_ITEMS];
+
+ptr_16_64_t gdtr = {.limit = sizeof(gdt), .base= (uint64_t) gdt };
+ptr_16_64_t idtr = {.limit = sizeof(idt), .base= (uint64_t) idt };
+
+static tss_t tss;
+tss_t *tss_p = NULL;
+
+void gdt_tss_setbase(descriptor_t *d, uintptr_t base)
+{
+	tss_descriptor_t *td = (tss_descriptor_t *) d;
+
+	td->base_0_15 = base & 0xffff;
+	td->base_16_23 = ((base) >> 16) & 0xff;
+	td->base_24_31 = ((base) >> 24) & 0xff;
+	td->base_32_63 = ((base) >> 32);
+}
+
+void gdt_tss_setlimit(descriptor_t *d, uint32_t limit)
+{
+	struct tss_descriptor *td = (tss_descriptor_t *) d;
+
+	td->limit_0_15 = limit & 0xffff;
+	td->limit_16_19 = (limit >> 16) & 0xf;
+}
+
+void idt_setoffset(idescriptor_t *d, uintptr_t offset)
+{
+	/*
+	 * Offset is a linear address.
+	 */
+	d->offset_0_15 = offset & 0xffff;
+	d->offset_16_31 = offset >> 16 & 0xffff;
+	d->offset_32_63 = offset >> 32;
+}
+
+void tss_initialize(tss_t *t)
+{
+	memsetb((uintptr_t) t, sizeof(tss_t), 0);
+}
+
+/*
+ * This function takes care of proper setup of IDT and IDTR.
+ */
+void idt_init(void)
+{
+	idescriptor_t *d;
+	int i;
+
+	for (i = 0; i < IDT_ITEMS; i++) {
+		d = &idt[i];
+
+		d->unused = 0;
+		d->selector = gdtselector(KTEXT_DES);
+
+		d->present = 1;
+		d->type = AR_INTERRUPT;	/* masking interrupt */
+
+		idt_setoffset(d, ((uintptr_t) interrupt_handlers) + i*interrupt_handler_size);
+		exc_register(i, "undef", (iroutine)null_interrupt);
+	}
+
+	exc_register( 7, "nm_fault", nm_fault);
+	exc_register(12, "ss_fault", ss_fault);
+	exc_register(13, "gp_fault", gp_fault);
+	exc_register(14, "ident_mapper", ident_page_fault);
+}
+
+/** Initialize segmentation - code/data/idt tables
+ *
+ */
+void pm_init(void)
+{
+	descriptor_t *gdt_p = (struct descriptor *) gdtr.base;
+	tss_descriptor_t *tss_desc;
+
+	/*
+	 * Each CPU has its private GDT and TSS.
+	 * All CPUs share one IDT.
+	 */
+
+	if (config.cpu_active == 1) {
+		idt_init();
+		/*
+		 * NOTE: bootstrap CPU has statically allocated TSS, because
+		 * the heap hasn't been initialized so far.
+		 */
+		tss_p = &tss;
+	}
+	else {
+		/* We are going to use malloc, which may return
+		 * non boot-mapped pointer, initialize the CR3 register
+		 * ahead of page_init */
+		write_cr3((uintptr_t) AS_KERNEL->page_table);
+
+		tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC);
+		if (!tss_p)
+			panic("could not allocate TSS\n");
+	}
+
+	tss_initialize(tss_p);
+
+	tss_desc = (tss_descriptor_t *) (&gdt_p[TSS_DES]);
+	tss_desc->present = 1;
+	tss_desc->type = AR_TSS;
+	tss_desc->dpl = PL_KERNEL;
+	
+	gdt_tss_setbase(&gdt_p[TSS_DES], (uintptr_t) tss_p);
+	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1);
+
+	gdtr_load(&gdtr);
+	idtr_load(&idtr);
+	/*
+	 * As of this moment, the current CPU has its own GDT pointing
+	 * to its own TSS. We just need to load the TR register.
+	 */
+	tr_load(gdtselector(TSS_DES));
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/proc/scheduler.c
===================================================================
--- kernel/arch/amd64/src/proc/scheduler.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/proc/scheduler.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+ /** @addtogroup amd64proc
+ * @{
+ */
+/** @file
+ */
+
+#include <proc/scheduler.h>
+#include <cpu.h>
+#include <proc/task.h>
+#include <proc/thread.h>
+#include <arch.h>
+#include <arch/context.h>	/* SP_DELTA */
+#include <arch/asm.h>
+#include <arch/debugger.h>
+#include <print.h>
+#include <arch/pm.h>
+#include <arch/ddi/ddi.h>
+
+/** Perform amd64 specific tasks needed before the new task is run.
+ *
+ * Interrupts are disabled.
+ */
+void before_task_runs_arch(void)
+{
+	io_perm_bitmap_install();
+}
+
+/** Perform amd64 specific tasks needed before the new thread is scheduled. */
+void before_thread_runs_arch(void)
+{
+	CPU->arch.tss->rsp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE-SP_DELTA];
+
+	/* Syscall support - write address of thread stack pointer to 
+	 * hidden part of gs */
+	swapgs();
+	write_msr(AMD_MSR_GS, (uint64_t)&THREAD->kstack);
+	swapgs();
+
+	/* TLS support - set FS to thread local storage */
+	write_msr(AMD_MSR_FS, THREAD->arch.tls);
+
+#ifdef CONFIG_DEBUG_AS_WATCHPOINT
+	/* Set watchpoint on AS to ensure that nobody sets it to zero */
+	if (CPU->id < BKPOINTS_MAX)
+		breakpoint_add(&((the_t *) THREAD->kstack)->as, 
+			       BKPOINT_WRITE | BKPOINT_CHECK_ZERO,
+			       CPU->id);
+#endif
+}
+
+void after_thread_ran_arch(void)
+{
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/proc/task.c
===================================================================
--- kernel/arch/amd64/src/proc/task.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/proc/task.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * 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.
+ */
+
+ /** @addtogroup amd64proc
+ * @{
+ */
+/** @file
+ */
+
+#include <proc/task.h>
+#include <mm/slab.h>
+#include <arch/types.h>
+
+/** Perform amd64 specific task initialization.
+ *
+ * @param t Task to be initialized.
+ */
+void task_create_arch(task_t *t)
+{
+	t->arch.iomapver = 0;
+	bitmap_initialize(&t->arch.iomap, NULL, 0);
+}
+
+/** Perform amd64 specific task destruction.
+ *
+ * @param t Task to be initialized.
+ */
+void task_destroy_arch(task_t *t)
+{
+	if (t->arch.iomap.map)
+		free(t->arch.iomap.map);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/proc/thread.c
===================================================================
--- kernel/arch/amd64/src/proc/thread.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/proc/thread.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * 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.
+ */
+
+ /** @addtogroup amd64proc
+ * @{
+ */
+/** @file
+ */
+
+#include <proc/thread.h>
+
+/** Perform amd64 specific thread initialization.
+ *
+ * @param t Thread to be initialized.
+ */
+void thread_create_arch(thread_t *t)
+{
+	t->arch.tls = 0;
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/smp/ap.S
===================================================================
--- kernel/arch/amd64/src/smp/ap.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/smp/ap.S	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,115 @@
+#
+# Copyright (C) 2001-2004 Jakub Jermar
+# Copyright (C) 2005-2006 Martin Decky
+# 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.
+#
+
+#
+# Init code for application processors.
+#
+
+#include <arch/boot/boot.h>
+#include <arch/boot/memmap.h>
+#include <arch/mm/page.h>
+#include <arch/pm.h>
+#include <arch/cpu.h>
+#include <arch/cpuid.h>
+
+.section K_TEXT_START, "ax"
+
+#ifdef CONFIG_SMP
+
+.global unmapped_ap_boot
+
+# This piece of code is real-mode and is meant to be alligned at 4K boundary.
+# The requirement for such an alignment comes from MP Specification's STARTUP IPI
+# requirements.
+
+.align 4096
+unmapped_ap_boot:
+.code16
+	cli
+	xorw %ax, %ax
+	movw %ax, %ds
+
+	lgdtl ap_gdtr		# initialize Global Descriptor Table register
+	
+	movl %cr0, %eax
+	orl $1, %eax
+	movl %eax, %cr0				# switch to protected mode
+	jmpl $gdtselector(KTEXT32_DES), $jump_to_kernel - BOOT_OFFSET + AP_BOOT_OFFSET
+	
+jump_to_kernel:
+.code32
+	movw $gdtselector(KDATA_DES), %ax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %ss
+	movw $gdtselector(UDATA_DES), %ax
+	movw %ax, %gs
+	
+	# Enable 64-bit page transaltion entries - CR4.PAE = 1.
+	# Paging is not enabled until after long mode is enabled
+	
+	movl %cr4, %eax
+	btsl $5, %eax
+	movl %eax, %cr4
+
+	leal ptl_0, %eax
+	movl %eax, %cr3
+	
+	# Enable long mode
+	movl $EFER_MSR_NUM, %ecx   # EFER MSR number
+	rdmsr                   # Read EFER
+	btsl $AMD_LME_FLAG, %eax            # Set LME=1
+	wrmsr                   # Write EFER
+	
+	# Enable paging to activate long mode (set CR0.PG=1)
+	movl %cr0, %eax
+	btsl $31, %eax
+	movl %eax, %cr0
+	
+	# At this point we are in compatibility mode
+	jmpl $gdtselector(KTEXT_DES), $start64 - BOOT_OFFSET + AP_BOOT_OFFSET
+
+.code64
+start64:
+	movq (ctx), %rsp
+	call main_ap - AP_BOOT_OFFSET + BOOT_OFFSET   # never returns
+
+#endif /* CONFIG_SMP */
+
+.section K_DATA_START, "aw", @progbits
+
+#ifdef CONFIG_SMP
+
+.global unmapped_ap_gdtr
+
+unmapped_ap_gdtr:
+	.word 0
+	.long 0
+
+#endif /* CONFIG_SMP */
Index: kernel/arch/amd64/src/smp/apic.c
===================================================================
--- kernel/arch/amd64/src/smp/apic.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/smp/apic.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/smp/apic.c
Index: kernel/arch/amd64/src/smp/ipi.c
===================================================================
--- kernel/arch/amd64/src/smp/ipi.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/smp/ipi.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/smp/ipi.c
Index: kernel/arch/amd64/src/smp/mps.c
===================================================================
--- kernel/arch/amd64/src/smp/mps.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/smp/mps.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/smp/mps.c
Index: kernel/arch/amd64/src/smp/smp.c
===================================================================
--- kernel/arch/amd64/src/smp/smp.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/smp/smp.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,1 @@
+../../../ia32/src/smp/smp.c
Index: kernel/arch/amd64/src/syscall.c
===================================================================
--- kernel/arch/amd64/src/syscall.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/syscall.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+ /** @addtogroup amd64
+ * @{
+ */
+/** @file
+ */
+
+#include <syscall/syscall.h>
+#include <arch/syscall.h>
+#include <panic.h>
+#include <arch/cpu.h>
+#include <arch/pm.h>
+#include <arch/asm.h>
+
+#include <print.h>
+#include <arch/cpu.h>
+
+extern void syscall_entry(void);
+
+/** Enable & setup support for SYSCALL/SYSRET */
+void syscall_setup_cpu(void)
+{
+	/* Enable SYSCALL/SYSRET */
+	set_efer_flag(AMD_SCE_FLAG);
+
+	/* Setup syscall entry address */
+	
+	/* This is _mess_ - the 64-bit CS is argument+16,
+	 * the SS is argument+8. The order is:
+	 * +0(KDATA_DES), +8(UDATA_DES), +16(UTEXT_DES)
+	 */
+	write_msr(AMD_MSR_STAR,
+		  ((uint64_t)(gdtselector(KDATA_DES) | PL_USER)<<48) \
+		  | ((uint64_t)(gdtselector(KTEXT_DES) | PL_KERNEL)<<32));
+	write_msr(AMD_MSR_LSTAR, (uint64_t)syscall_entry);
+	/* Mask RFLAGS on syscall 
+	 * - disable interrupts, until we exchange the stack register
+	 *   (mask the IE bit)
+	 */
+	write_msr(AMD_MSR_SFMASK, 0x200);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/amd64/src/userspace.c
===================================================================
--- kernel/arch/amd64/src/userspace.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/amd64/src/userspace.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+ /** @addtogroup amd64	
+ * @{
+ */
+/** @file
+ */
+
+#include <userspace.h>
+#include <arch/pm.h>
+#include <arch/types.h>
+#include <arch.h>
+#include <proc/uarg.h>
+#include <mm/as.h>
+
+
+/** Enter userspace
+ *
+ * Change CPU protection level to 3, enter userspace.
+ *
+ */
+void userspace(uspace_arg_t *kernel_uarg)
+{
+	ipl_t ipl;
+	
+	ipl = interrupts_disable();
+
+	/* Clear CF,PF,AF,ZF,SF,DF,OF */
+	ipl &= ~(0xcd4);
+
+	__asm__ volatile (""
+			  "pushq %0\n"
+			  "pushq %1\n"
+			  "pushq %2\n"
+			  "pushq %3\n"
+			  "pushq %4\n"
+			  "movq %5, %%rax\n"
+			  "iretq\n"
+			  : : 
+			  "i" (gdtselector(UDATA_DES) | PL_USER), 
+			  "r" (kernel_uarg->uspace_stack+THREAD_STACK_SIZE), 
+			  "r" (ipl), 
+			  "i" (gdtselector(UTEXT_DES) | PL_USER), 
+			  "r" (kernel_uarg->uspace_entry),
+			  "r" (kernel_uarg->uspace_uarg)
+			  : "rax"
+			  );
+	
+	/* Unreachable */
+	for(;;)
+		;
+}
+
+ /** @}
+ */
+
