Index: kernel/arch/xen32/Makefile.inc
===================================================================
--- kernel/arch/xen32/Makefile.inc	(revision ba5e61817fecf671819cbab9c0c9abb329220bea)
+++ kernel/arch/xen32/Makefile.inc	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -110,5 +110,4 @@
 	arch/$(ARCH)/src/proc/thread.c \
 	arch/$(ARCH)/src/bios/bios.c \
-	arch/$(ARCH)/src/smp/ap.S \
 	arch/$(ARCH)/src/smp/apic.c \
 	arch/$(ARCH)/src/smp/mps.c \
Index: kernel/arch/xen32/_link.ld.in
===================================================================
--- kernel/arch/xen32/_link.ld.in	(revision ba5e61817fecf671819cbab9c0c9abb329220bea)
+++ kernel/arch/xen32/_link.ld.in	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -3,6 +3,7 @@
 
 #define __ASM__
-#include <arch/boot/boot.h>
 #include <arch/mm/page.h>
+
+ENTRY(kernel_image_start)
 
 SECTIONS {
Index: kernel/arch/xen32/include/mm/as.h
===================================================================
--- kernel/arch/xen32/include/mm/as.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/as.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005 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 xen32mm	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef __xen32_AS_H__
+#define __xen32_AS_H__
+
+#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH	0
+
+#define KERNEL_ADDRESS_SPACE_START_ARCH		((unsigned long) 0x80000000)
+#define KERNEL_ADDRESS_SPACE_END_ARCH		((unsigned long) 0xffffffff)
+#define USER_ADDRESS_SPACE_START_ARCH		((unsigned long) 0x00000000)
+#define USER_ADDRESS_SPACE_END_ARCH		((unsigned long) 0x7fffffff)
+
+#define USTACK_ADDRESS_ARCH	(USER_ADDRESS_SPACE_END_ARCH-(PAGE_SIZE-1))
+
+#define as_install_arch(as)
+
+extern void as_arch_init(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/include/mm/asid.h
===================================================================
--- kernel/arch/xen32/include/mm/asid.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/asid.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2005 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 xen32mm	
+ * @{
+ */
+/** @file
+ * @ingroup xen32mm
+ */
+
+/*
+ * xen32 has no hardware support for address space identifiers.
+ * This file is provided to do nop-implementation of mm/asid.h
+ * interface.
+ */
+
+#ifndef __xen32_ASID_H__
+#define __xen32_ASID_H__
+
+typedef int asid_t;
+
+#define ASID_MAX_ARCH		3
+
+#define asid_get()		(ASID_START+1)
+#define asid_put(asid)
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/include/mm/frame.h
===================================================================
--- kernel/arch/xen32/include/mm/frame.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/frame.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,57 @@
+/*
+ * 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 xen32mm	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef __xen32_FRAME_H__
+#define __xen32_FRAME_H__
+
+#define FRAME_WIDTH	12	/* 4K */
+#define FRAME_SIZE	(1<<FRAME_WIDTH)
+
+
+#ifdef KERNEL
+#ifndef __ASM__
+
+#include <arch/types.h>
+
+extern uintptr_t last_frame;
+
+extern void frame_arch_init(void);
+
+#endif /* __ASM__ */
+#endif /* KERNEL */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/include/mm/memory_init.h
===================================================================
--- kernel/arch/xen32/include/mm/memory_init.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/memory_init.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,48 @@
+/*
+ * 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 xen32mm	
+ * @{
+ */
+/** @file
+ * @ingroup xen32mm
+ */
+
+#ifndef __xen32_MEMORY_INIT_H__
+#define __xen32_MEMORY_INIT_H__
+
+#include <typedefs.h>
+
+size_t get_memory_size(void);
+
+void memory_print_map(void);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/include/mm/page.h
===================================================================
--- kernel/arch/xen32/include/mm/page.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/page.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,172 @@
+/*
+ * 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 xen32mm	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef __xen32_PAGE_H__
+#define __xen32_PAGE_H__
+
+#include <arch/mm/frame.h>
+
+#define PAGE_WIDTH	FRAME_WIDTH
+#define PAGE_SIZE	FRAME_SIZE
+
+#ifdef KERNEL
+
+#ifndef __ASM__
+#	define KA2PA(x)	(((uintptr_t) (x)) - 0x80000000)
+#	define PA2KA(x)	(((uintptr_t) (x)) + 0x80000000)
+#else
+#	define KA2PA(x)	((x) - 0x80000000)
+#	define PA2KA(x)	((x) + 0x80000000)
+#endif
+
+/*
+ * Implementation of generic 4-level page table interface.
+ * IA-32 has 2-level page tables, so PTL1 and PTL2 are left out.
+ */
+#define PTL0_ENTRIES_ARCH	1024
+#define PTL1_ENTRIES_ARCH	0
+#define PTL2_ENTRIES_ARCH	0
+#define PTL3_ENTRIES_ARCH	1024
+
+#define PTL0_INDEX_ARCH(vaddr)	(((vaddr)>>22)&0x3ff)
+#define PTL1_INDEX_ARCH(vaddr)	0
+#define PTL2_INDEX_ARCH(vaddr)	0
+#define PTL3_INDEX_ARCH(vaddr)	(((vaddr)>>12)&0x3ff)
+
+#define GET_PTL1_ADDRESS_ARCH(ptl0, i)		((pte_t *)((((pte_t *)(ptl0))[(i)].frame_address)<<12))
+#define GET_PTL2_ADDRESS_ARCH(ptl1, i)		(ptl1)
+#define GET_PTL3_ADDRESS_ARCH(ptl2, i)		(ptl2)
+#define GET_FRAME_ADDRESS_ARCH(ptl3, i)		((uintptr_t)((((pte_t *)(ptl3))[(i)].frame_address)<<12))
+
+#define SET_PTL0_ADDRESS_ARCH(ptl0)		(write_cr3((uintptr_t) (ptl0)))
+#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)	(((pte_t *)(ptl0))[(i)].frame_address = (a)>>12)
+#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
+#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
+#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)	(((pte_t *)(ptl3))[(i)].frame_address = (a)>>12)
+
+#define GET_PTL1_FLAGS_ARCH(ptl0, i)		get_pt_flags((pte_t *)(ptl0), (index_t)(i))
+#define GET_PTL2_FLAGS_ARCH(ptl1, i)		PAGE_PRESENT
+#define GET_PTL3_FLAGS_ARCH(ptl2, i)		PAGE_PRESENT
+#define GET_FRAME_FLAGS_ARCH(ptl3, i)		get_pt_flags((pte_t *)(ptl3), (index_t)(i))
+
+#define SET_PTL1_FLAGS_ARCH(ptl0, i, x)		set_pt_flags((pte_t *)(ptl0), (index_t)(i), (x))
+#define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
+#define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
+#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)	set_pt_flags((pte_t *)(ptl3), (index_t)(i), (x))
+
+#define PTE_VALID_ARCH(p)			(*((uint32_t *) (p)) != 0)
+#define PTE_PRESENT_ARCH(p)			((p)->present != 0)
+#define PTE_GET_FRAME_ARCH(p)			((p)->frame_address<<FRAME_WIDTH)
+#define PTE_WRITABLE_ARCH(p)			((p)->writeable != 0)
+#define PTE_EXECUTABLE_ARCH(p)			1
+
+#ifndef __ASM__
+
+#include <mm/page.h>
+#include <arch/types.h>
+#include <arch/mm/frame.h>
+#include <typedefs.h>
+
+/* Page fault error codes. */
+
+/** When bit on this position is 0, the page fault was caused by a not-present page. */
+#define PFERR_CODE_P		(1<<0)
+
+/** When bit on this position is 1, the page fault was caused by a write. */
+#define PFERR_CODE_RW		(1<<1)
+
+/** When bit on this position is 1, the page fault was caused in user mode. */
+#define PFERR_CODE_US		(1<<2)
+
+/** When bit on this position is 1, a reserved bit was set in page directory. */ 
+#define PFERR_CODE_RSVD		(1<<3)	
+
+/** Page Table Entry. */
+struct page_specifier {
+	unsigned present : 1;
+	unsigned writeable : 1;
+	unsigned uaccessible : 1;
+	unsigned page_write_through : 1;
+	unsigned page_cache_disable : 1;
+	unsigned accessed : 1;
+	unsigned dirty : 1;
+	unsigned pat : 1;
+	unsigned global : 1;
+	unsigned soft_valid : 1;	/**< Valid content even if the present bit is not set. */
+	unsigned avl : 2;
+	unsigned frame_address : 20;
+} __attribute__ ((packed));
+
+static inline int get_pt_flags(pte_t *pt, index_t i)
+{
+	pte_t *p = &pt[i];
+	
+	return (
+		(!p->page_cache_disable)<<PAGE_CACHEABLE_SHIFT |
+		(!p->present)<<PAGE_PRESENT_SHIFT |
+		p->uaccessible<<PAGE_USER_SHIFT |
+		1<<PAGE_READ_SHIFT |
+		p->writeable<<PAGE_WRITE_SHIFT |
+		1<<PAGE_EXEC_SHIFT |
+		p->global<<PAGE_GLOBAL_SHIFT
+	);
+}
+
+static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
+{
+	pte_t *p = &pt[i];
+	
+	p->page_cache_disable = !(flags & PAGE_CACHEABLE);
+	p->present = !(flags & PAGE_NOT_PRESENT);
+	p->uaccessible = (flags & PAGE_USER) != 0;
+	p->writeable = (flags & PAGE_WRITE) != 0;
+	p->global = (flags & PAGE_GLOBAL) != 0;
+	
+	/*
+	 * Ensure that there is at least one bit set even if the present bit is cleared.
+	 */
+	p->soft_valid = true;
+}
+
+extern void page_arch_init(void);
+extern void page_fault(int n, istate_t *istate);
+
+#endif /* __ASM__ */
+
+#endif /* KERNEL */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/include/mm/tlb.h
===================================================================
--- kernel/arch/xen32/include/mm/tlb.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/include/mm/tlb.h	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2005 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 xen32mm	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef __xen32_TLB_H__
+#define __xen32_TLB_H__
+
+#define tlb_arch_init()
+#define tlb_print()
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/xen32/src/boot/boot.S
===================================================================
--- kernel/arch/xen32/src/boot/boot.S	(revision ba5e61817fecf671819cbab9c0c9abb329220bea)
+++ kernel/arch/xen32/src/boot/boot.S	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -40,6 +40,4 @@
 	.byte   0
 
-#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
-
 .section K_TEXT_START, "ax"
 
@@ -49,17 +47,7 @@
 .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
+.global kernel_image_start
+	
+kernel_image_start:
 	lgdt KA2PA(bootstrap_gdtr)		# initialize Global Descriptor Table register
 
@@ -102,78 +90,4 @@
 	popl %eax
 	popl %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
-			
-			xorl %ecx, %ecx
-			movl %ecx, init
-			jmp mods_end
-		
-		mods_valid:
-		
-		movl 20(%ebx), %ecx						# mbi->mods_count
-		movl %ecx, init
-		
-		cmpl $0, %ecx
-		je mods_end
-		
-		movl 24(%ebx), %esi						# mbi->mods_addr
-		movl $init, %edi
-		
-		mods_loop:
-		
-			movl 0(%esi), %edx					# mods->mod_start
-			addl $0x80000000, %edx
-			movl %edx, 4(%edi)
-			
-			movl 4(%esi), %edx
-			subl 0(%esi), %edx					# mods->mod_end - mods->mod_start
-			movl %edx, 8(%edi)
-			
-			addl $16, %esi
-			addl $8	, %edi
-			
-			loop mods_loop
-			
-		mods_end:
-		
-	invalid_boot:
-	
-#ifdef CONFIG_SMP
-	
-	# copy AP bootstrap routines below 1 MB
-	
-	movl $BOOT_OFFSET, %esi
-	movl $AP_BOOT_OFFSET, %edi
-	movl $_hardcoded_unmapped_size, %ecx
-	cld
-	rep movsb
-	
-#endif
 	
 	call main_bsp								# never returns
Index: kernel/arch/xen32/src/mm/as.c
===================================================================
--- kernel/arch/xen32/src/mm/as.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/mm/as.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,46 @@
+/*
+ * 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 xen32mm
+ * @{
+ */
+/** @file
+ * @ingroup xen32mm
+ */
+
+#include <arch/mm/as.h>
+#include <genarch/mm/as_pt.h>
+
+/** Architecture dependent address space init. */
+void as_arch_init(void)
+{
+	as_operations = &as_pt_operations;
+}
+
+/** @}
+ */
Index: kernel/arch/xen32/src/mm/frame.c
===================================================================
--- kernel/arch/xen32/src/mm/frame.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/mm/frame.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,73 @@
+/*
+ * 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 xen32mm
+ * @{
+ */
+/** @file
+ * @ingroup xen32mm
+ */
+
+#include <mm/frame.h>
+#include <arch/mm/frame.h>
+#include <mm/as.h>
+#include <config.h>
+#include <arch/boot/boot.h>
+#include <panic.h>
+#include <debug.h>
+#include <align.h>
+#include <macros.h>
+
+#include <print.h>
+#include <console/cmd.h>
+#include <console/kconsole.h>
+
+uintptr_t last_frame = 0;
+
+void frame_arch_init(void)
+{
+	static pfn_t minconf;
+
+	if (config.cpu_active == 1) {
+		minconf = 1;
+#ifdef CONFIG_SIMICS_FIX
+		minconf = max(minconf, ADDR2PFN(0x10000));
+#endif
+
+		/* Reserve frame 0 (BIOS data) */
+		frame_mark_unavailable(0, 1);
+		
+#ifdef CONFIG_SIMICS_FIX
+		/* Don't know why, but these addresses help */
+		frame_mark_unavailable(0xd000 >> FRAME_WIDTH,3);
+#endif
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/xen32/src/mm/memory_init.c
===================================================================
--- kernel/arch/xen32/src/mm/memory_init.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/mm/memory_init.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,50 @@
+/*
+ * 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 xen32mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/memory_init.h>
+#include <arch/mm/page.h>
+#include <print.h>
+
+size_t get_memory_size(void) 
+{
+	return 0;
+}
+
+void memory_print_map(void)
+{
+}
+
+
+/** @}
+ */
Index: kernel/arch/xen32/src/mm/page.c
===================================================================
--- kernel/arch/xen32/src/mm/page.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/mm/page.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,121 @@
+/*
+ * 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 xen32mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/page.h>
+#include <genarch/mm/page_pt.h>
+#include <arch/mm/frame.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <mm/as.h>
+#include <arch/types.h>
+#include <align.h>
+#include <config.h>
+#include <func.h>
+#include <arch/interrupt.h>
+#include <arch/asm.h>
+#include <debug.h>
+#include <memstr.h>
+#include <print.h>
+#include <interrupt.h>
+
+void page_arch_init(void)
+{
+	uintptr_t cur;
+	int flags;
+
+	if (config.cpu_active == 1) {
+		page_mapping_operations = &pt_mapping_operations;
+	
+		/*
+		 * PA2KA(identity) mapping for all frames until last_frame.
+		 */
+		for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
+			flags = PAGE_CACHEABLE;
+			if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size))
+				flags |= PAGE_GLOBAL;
+			page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, 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);
+	}
+
+	paging_on();
+}
+
+
+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;
+}
+
+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 directory.\n");
+
+	if (istate->error_word & PFERR_CODE_RW)
+		access = PF_ACCESS_WRITE;
+	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(istate);
+                printf("page fault address: %#x\n", page);
+                panic("page fault\n");
+        }
+}
+
+/** @}
+ */
Index: kernel/arch/xen32/src/mm/tlb.c
===================================================================
--- kernel/arch/xen32/src/mm/tlb.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/mm/tlb.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2005 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 xen32mm	
+ * @{
+ */
+/** @file
+ * @ingroup xen32mm
+ */
+
+#include <mm/tlb.h>
+#include <arch/mm/asid.h>
+#include <arch/asm.h>
+#include <arch/types.h>
+
+/** Invalidate all entries in TLB. */
+void tlb_invalidate_all(void)
+{
+	write_cr3(read_cr3());
+}
+
+/** Invalidate all entries in TLB that belong to specified address space.
+ *
+ * @param asid This parameter is ignored as the architecture doesn't support it.
+ */
+void tlb_invalidate_asid(asid_t asid)
+{
+	tlb_invalidate_all();
+}
+
+/** Invalidate TLB entries for specified page range belonging to specified address space.
+ *
+ * @param asid This parameter is ignored as the architecture doesn't support it.
+ * @param page Address of the first page whose entry is to be invalidated.
+ * @param cnt Number of entries to invalidate.
+ */
+void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++)
+		invlpg(page + i * PAGE_SIZE);
+}
+
+/** @}
+ */
Index: kernel/arch/xen32/src/smp/apic.c
===================================================================
--- kernel/arch/xen32/src/smp/apic.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/smp/apic.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,580 @@
+/*
+ * 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 xen32	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/types.h>
+#include <arch/smp/apic.h>
+#include <arch/smp/ap.h>
+#include <arch/smp/mps.h>
+#include <arch/boot/boot.h>
+#include <mm/page.h>
+#include <time/delay.h>
+#include <interrupt.h>
+#include <arch/interrupt.h>
+#include <print.h>
+#include <arch/asm.h>
+#include <arch.h>
+
+#ifdef CONFIG_SMP
+
+/*
+ * Advanced Programmable Interrupt Controller for SMP systems.
+ * Tested on:
+ *	Bochs 2.0.2 - Bochs 2.2.6 with 2-8 CPUs
+ *	Simics 2.0.28 - Simics 2.2.19 2-15 CPUs
+ *	VMware Workstation 5.5 with 2 CPUs
+ *	QEMU 0.8.0 with 2-15 CPUs
+ *	ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs
+ *	ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs
+ *	MSI K7D Master-L with 2x 2100MHz Athlon MP CPUs
+ */
+
+/*
+ * These variables either stay configured as initilalized, or are changed by
+ * the MP configuration code.
+ *
+ * Pay special attention to the volatile keyword. Without it, gcc -O2 would
+ * optimize the code too much and accesses to l_apic and io_apic, that must
+ * always be 32-bit, would use byte oriented instructions.
+ */
+volatile uint32_t *l_apic = (uint32_t *) 0xfee00000;
+volatile uint32_t *io_apic = (uint32_t *) 0xfec00000;
+
+uint32_t apic_id_mask = 0;
+
+static int apic_poll_errors(void);
+
+#ifdef LAPIC_VERBOSE
+static char *delmod_str[] = {
+	"Fixed",
+	"Lowest Priority",
+	"SMI",
+	"Reserved",
+	"NMI",
+	"INIT",
+	"STARTUP",
+	"ExtInt"
+};
+
+static char *destmod_str[] = {
+	"Physical",
+	"Logical"
+};
+
+static char *trigmod_str[] = {
+	"Edge",
+	"Level"
+};
+
+static char *mask_str[] = {
+	"Unmasked",
+	"Masked"
+};
+
+static char *delivs_str[] = {
+	"Idle",
+	"Send Pending"
+};
+
+static char *tm_mode_str[] = {
+	"One-shot",
+	"Periodic"
+};
+
+static char *intpol_str[] = {
+	"Polarity High",
+	"Polarity Low"
+};
+#endif /* LAPIC_VERBOSE */
+
+
+static void apic_spurious(int n, istate_t *istate);
+static void l_apic_timer_interrupt(int n, istate_t *istate);
+
+/** Initialize APIC on BSP. */
+void apic_init(void)
+{
+	io_apic_id_t idreg;
+	int i;
+
+	exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious);
+
+	enable_irqs_function = io_apic_enable_irqs;
+	disable_irqs_function = io_apic_disable_irqs;
+	eoi_function = l_apic_eoi;
+	
+	/*
+	 * Configure interrupt routing.
+	 * IRQ 0 remains masked as the time signal is generated by l_apic's themselves.
+	 * Other interrupts will be forwarded to the lowest priority CPU.
+	 */
+	io_apic_disable_irqs(0xffff);
+	exc_register(VECTOR_CLK, "l_apic_timer", (iroutine) l_apic_timer_interrupt);
+	for (i = 0; i < IRQ_COUNT; i++) {
+		int pin;
+	
+		if ((pin = smp_irq_to_pin(i)) != -1) {
+			io_apic_change_ioredtbl(pin, DEST_ALL, IVT_IRQBASE+i, LOPRI);
+		}
+	}
+	
+	/*
+	 * Ensure that io_apic has unique ID.
+	 */
+	idreg.value = io_apic_read(IOAPICID);
+	if ((1<<idreg.apic_id) & apic_id_mask) {	/* see if IO APIC ID is used already */
+		for (i = 0; i < APIC_ID_COUNT; i++) {
+			if (!((1<<i) & apic_id_mask)) {
+				idreg.apic_id = i;
+				io_apic_write(IOAPICID, idreg.value);
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Configure the BSP's lapic.
+	 */
+	l_apic_init();
+
+	l_apic_debug();	
+}
+
+/** APIC spurious interrupt handler.
+ *
+ * @param n Interrupt vector.
+ * @param istate Interrupted state.
+ */
+void apic_spurious(int n, istate_t *istate)
+{
+#ifdef CONFIG_DEBUG
+	printf("cpu%d: APIC spurious interrupt\n", CPU->id);
+#endif
+}
+
+/** Poll for APIC errors.
+ *
+ * Examine Error Status Register and report all errors found.
+ *
+ * @return 0 on error, 1 on success.
+ */
+int apic_poll_errors(void)
+{
+	esr_t esr;
+	
+	esr.value = l_apic[ESR];
+	
+	if (esr.send_checksum_error)
+		printf("Send Checksum Error\n");
+	if (esr.receive_checksum_error)
+		printf("Receive Checksum Error\n");
+	if (esr.send_accept_error)
+		printf("Send Accept Error\n");
+	if (esr.receive_accept_error)
+		printf("Receive Accept Error\n");
+	if (esr.send_illegal_vector)
+		printf("Send Illegal Vector\n");
+	if (esr.received_illegal_vector)
+		printf("Received Illegal Vector\n");
+	if (esr.illegal_register_address)
+		printf("Illegal Register Address\n");
+
+	return !esr.err_bitmap;
+}
+
+/** Send all CPUs excluding CPU IPI vector.
+ *
+ * @param vector Interrupt vector to be sent.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+int l_apic_broadcast_custom_ipi(uint8_t vector)
+{
+	icr_t icr;
+
+	icr.lo = l_apic[ICRlo];
+	icr.delmod = DELMOD_FIXED;
+	icr.destmod = DESTMOD_LOGIC;
+	icr.level = LEVEL_ASSERT;
+	icr.shorthand = SHORTHAND_ALL_EXCL;
+	icr.trigger_mode = TRIGMOD_LEVEL;
+	icr.vector = vector;
+
+	l_apic[ICRlo] = icr.lo;
+
+	icr.lo = l_apic[ICRlo];
+	if (icr.delivs == DELIVS_PENDING) {
+#ifdef CONFIG_DEBUG
+		printf("IPI is pending.\n");
+#endif
+	}
+
+	return apic_poll_errors();
+}
+
+/** Universal Start-up Algorithm for bringing up the AP processors.
+ *
+ * @param apicid APIC ID of the processor to be brought up.
+ *
+ * @return 0 on failure, 1 on success.
+ */
+int l_apic_send_init_ipi(uint8_t apicid)
+{
+	icr_t icr;
+	int i;
+
+	/*
+	 * Read the ICR register in and zero all non-reserved fields.
+	 */
+	icr.lo = l_apic[ICRlo];
+	icr.hi = l_apic[ICRhi];
+	
+	icr.delmod = DELMOD_INIT;
+	icr.destmod = DESTMOD_PHYS;
+	icr.level = LEVEL_ASSERT;
+	icr.trigger_mode = TRIGMOD_LEVEL;
+	icr.shorthand = SHORTHAND_NONE;
+	icr.vector = 0;
+	icr.dest = apicid;
+	
+	l_apic[ICRhi] = icr.hi;
+	l_apic[ICRlo] = icr.lo;
+
+	/*
+	 * According to MP Specification, 20us should be enough to
+	 * deliver the IPI.
+	 */
+	delay(20);
+
+	if (!apic_poll_errors())
+		return 0;
+
+	icr.lo = l_apic[ICRlo];
+	if (icr.delivs == DELIVS_PENDING) {
+#ifdef CONFIG_DEBUG
+		printf("IPI is pending.\n");
+#endif
+	}
+
+	icr.delmod = DELMOD_INIT;
+	icr.destmod = DESTMOD_PHYS;
+	icr.level = LEVEL_DEASSERT;
+	icr.shorthand = SHORTHAND_NONE;
+	icr.trigger_mode = TRIGMOD_LEVEL;
+	icr.vector = 0;
+	l_apic[ICRlo] = icr.lo;
+
+	/*
+	 * Wait 10ms as MP Specification specifies.
+	 */
+	delay(10000);
+
+	if (!is_82489DX_apic(l_apic[LAVR])) {
+		/*
+		 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's.
+		 */
+		for (i = 0; i<2; i++) {
+			icr.lo = l_apic[ICRlo];
+			icr.delmod = DELMOD_STARTUP;
+			icr.destmod = DESTMOD_PHYS;
+			icr.level = LEVEL_ASSERT;
+			icr.shorthand = SHORTHAND_NONE;
+			icr.trigger_mode = TRIGMOD_LEVEL;
+			l_apic[ICRlo] = icr.lo;
+			delay(200);
+		}
+	}
+	
+	return apic_poll_errors();
+}
+
+/** Initialize Local APIC. */
+void l_apic_init(void)
+{
+	lvt_error_t error;
+	lvt_lint_t lint;
+	tpr_t tpr;
+	svr_t svr;
+	icr_t icr;
+	tdcr_t tdcr;
+	lvt_tm_t tm;
+	ldr_t ldr;
+	dfr_t dfr;
+	uint32_t t1, t2;
+
+	/* Initialize LVT Error register. */
+	error.value = l_apic[LVT_Err];
+	error.masked = true;
+	l_apic[LVT_Err] = error.value;
+
+	/* Initialize LVT LINT0 register. */
+	lint.value = l_apic[LVT_LINT0];
+	lint.masked = true;
+	l_apic[LVT_LINT0] = lint.value;
+
+	/* Initialize LVT LINT1 register. */
+	lint.value = l_apic[LVT_LINT1];
+	lint.masked = true;
+	l_apic[LVT_LINT1] = lint.value;
+
+	/* Task Priority Register initialization. */
+	tpr.value = l_apic[TPR];
+	tpr.pri_sc = 0;
+	tpr.pri = 0;
+	l_apic[TPR] = tpr.value;
+	
+	/* Spurious-Interrupt Vector Register initialization. */
+	svr.value = l_apic[SVR];
+	svr.vector = VECTOR_APIC_SPUR;
+	svr.lapic_enabled = true;
+	svr.focus_checking = true;
+	l_apic[SVR] = svr.value;
+
+	if (CPU->arch.family >= 6)
+		enable_l_apic_in_msr();
+	
+	/* Interrupt Command Register initialization. */
+	icr.lo = l_apic[ICRlo];
+	icr.delmod = DELMOD_INIT;
+	icr.destmod = DESTMOD_PHYS;
+	icr.level = LEVEL_DEASSERT;
+	icr.shorthand = SHORTHAND_ALL_INCL;
+	icr.trigger_mode = TRIGMOD_LEVEL;
+	l_apic[ICRlo] = icr.lo;
+	
+	/* Timer Divide Configuration Register initialization. */
+	tdcr.value = l_apic[TDCR];
+	tdcr.div_value = DIVIDE_1;
+	l_apic[TDCR] = tdcr.value;
+
+	/* Program local timer. */
+	tm.value = l_apic[LVT_Tm];
+	tm.vector = VECTOR_CLK;
+	tm.mode = TIMER_PERIODIC;
+	tm.masked = false;
+	l_apic[LVT_Tm] = tm.value;
+
+	/*
+	 * Measure and configure the timer to generate timer
+	 * interrupt with period 1s/HZ seconds.
+	 */
+	t1 = l_apic[CCRT];
+	l_apic[ICRT] = 0xffffffff;
+
+	while (l_apic[CCRT] == t1)
+		;
+		
+	t1 = l_apic[CCRT];
+	delay(1000000/HZ);
+	t2 = l_apic[CCRT];
+	
+	l_apic[ICRT] = t1-t2;
+	
+	/* Program Logical Destination Register. */
+	ldr.value = l_apic[LDR];
+	if (CPU->id < sizeof(CPU->id)*8)	/* size in bits */
+		ldr.id = (1<<CPU->id);
+	l_apic[LDR] = ldr.value;
+	
+	/* Program Destination Format Register for Flat mode. */
+	dfr.value = l_apic[DFR];
+	dfr.model = MODEL_FLAT;
+	l_apic[DFR] = dfr.value;
+}
+
+/** Local APIC End of Interrupt. */
+void l_apic_eoi(void)
+{
+	l_apic[EOI] = 0;
+}
+
+/** Dump content of Local APIC registers. */
+void l_apic_debug(void)
+{
+#ifdef LAPIC_VERBOSE
+	lvt_tm_t tm;
+	lvt_lint_t lint;
+	lvt_error_t error;	
+	
+	printf("LVT on cpu%d, LAPIC ID: %d\n", CPU->id, l_apic_id());
+
+	tm.value = l_apic[LVT_Tm];
+	printf("LVT Tm: vector=%hhd, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]);
+	lint.value = l_apic[LVT_LINT0];
+	printf("LVT LINT0: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]);
+	lint.value = l_apic[LVT_LINT1];	
+	printf("LVT LINT1: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]);	
+	error.value = l_apic[LVT_Err];
+	printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]);
+#endif
+}
+
+/** Local APIC Timer Interrupt.
+ *
+ * @param n Interrupt vector number.
+ * @param istate Interrupted state.
+ */
+void l_apic_timer_interrupt(int n, istate_t *istate)
+{
+	l_apic_eoi();
+	clock();
+}
+
+/** Get Local APIC ID.
+ *
+ * @return Local APIC ID.
+ */
+uint8_t l_apic_id(void)
+{
+	l_apic_id_t idreg;
+	
+	idreg.value = l_apic[L_APIC_ID];
+	return idreg.apic_id;
+}
+
+/** Read from IO APIC register.
+ *
+ * @param address IO APIC register address.
+ *
+ * @return Content of the addressed IO APIC register.
+ */
+uint32_t io_apic_read(uint8_t address)
+{
+	io_regsel_t regsel;
+	
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	return io_apic[IOWIN];
+}
+
+/** Write to IO APIC register.
+ *
+ * @param address IO APIC register address.
+ * @param x Content to be written to the addressed IO APIC register.
+ */
+void io_apic_write(uint8_t address, uint32_t x)
+{
+	io_regsel_t regsel;
+	
+	regsel.value = io_apic[IOREGSEL];
+	regsel.reg_addr = address;
+	io_apic[IOREGSEL] = regsel.value;
+	io_apic[IOWIN] = x;
+}
+
+/** Change some attributes of one item in I/O Redirection Table.
+ *
+ * @param pin IO APIC pin number.
+ * @param dest Interrupt destination address.
+ * @param v Interrupt vector to trigger.
+ * @param flags Flags.
+ */
+void io_apic_change_ioredtbl(int pin, int dest, uint8_t v, int flags)
+{
+	io_redirection_reg_t reg;
+	int dlvr = DELMOD_FIXED;
+	
+	if (flags & LOPRI)
+		dlvr = DELMOD_LOWPRI;
+
+	reg.lo = io_apic_read(IOREDTBL + pin*2);
+	reg.hi = io_apic_read(IOREDTBL + pin*2 + 1);
+	
+	reg.dest = dest;
+	reg.destmod = DESTMOD_LOGIC;
+	reg.trigger_mode = TRIGMOD_EDGE;
+	reg.intpol = POLARITY_HIGH;
+	reg.delmod = dlvr;
+	reg.intvec = v;
+
+	io_apic_write(IOREDTBL + pin*2, reg.lo);
+	io_apic_write(IOREDTBL + pin*2 + 1, reg.hi);
+}
+
+/** Mask IRQs in IO APIC.
+ *
+ * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask).
+ */
+void io_apic_disable_irqs(uint16_t irqmask)
+{
+	io_redirection_reg_t reg;
+	int i, pin;
+	
+	for (i=0;i<16;i++) {
+		if (irqmask & (1<<i)) {
+			/*
+			 * Mask the signal input in IO APIC if there is a
+			 * mapping for the respective IRQ number.
+			 */
+			pin = smp_irq_to_pin(i);
+			if (pin != -1) {
+				reg.lo = io_apic_read(IOREDTBL + pin*2);
+				reg.masked = true;
+				io_apic_write(IOREDTBL + pin*2, reg.lo);
+			}
+			
+		}
+	}
+}
+
+/** Unmask IRQs in IO APIC.
+ *
+ * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask).
+ */
+void io_apic_enable_irqs(uint16_t irqmask)
+{
+	int i, pin;
+	io_redirection_reg_t reg;	
+	
+	for (i=0;i<16;i++) {
+		if (irqmask & (1<<i)) {
+			/*
+			 * Unmask the signal input in IO APIC if there is a
+			 * mapping for the respective IRQ number.
+			 */
+			pin = smp_irq_to_pin(i);
+			if (pin != -1) {
+				reg.lo = io_apic_read(IOREDTBL + pin*2);
+				reg.masked = false;
+				io_apic_write(IOREDTBL + pin*2, reg.lo);
+			}
+			
+		}
+	}
+}
+
+#endif /* CONFIG_SMP */
+
+/** @}
+ */
Index: kernel/arch/xen32/src/smp/ipi.c
===================================================================
--- kernel/arch/xen32/src/smp/ipi.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/smp/ipi.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005 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 xen32	
+ * @{
+ */
+/** @file
+ */
+
+#ifdef CONFIG_SMP
+
+#include <smp/ipi.h>
+#include <arch/smp/apic.h>
+
+void ipi_broadcast_arch(int ipi)
+{
+	(void) l_apic_broadcast_custom_ipi((uint8_t) ipi);
+}
+
+#endif /* CONFIG_SMP */
+
+/** @}
+ */
Index: kernel/arch/xen32/src/smp/mps.c
===================================================================
--- kernel/arch/xen32/src/smp/mps.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/smp/mps.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2001-2005 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 xen32	
+ * @{
+ */
+/** @file
+ */
+
+#ifdef CONFIG_SMP
+
+#include <config.h>
+#include <print.h>
+#include <debug.h>
+#include <arch/smp/mps.h>
+#include <arch/smp/apic.h>
+#include <arch/smp/smp.h>
+#include <func.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <cpu.h>
+#include <arch/asm.h>
+#include <arch/bios/bios.h>
+#include <mm/frame.h>
+
+/*
+ * MultiProcessor Specification detection code.
+ */
+
+#define	FS_SIGNATURE	0x5f504d5f
+#define CT_SIGNATURE 	0x504d4350
+
+int mps_fs_check(uint8_t *base);
+int mps_ct_check(void);
+
+int configure_via_ct(void);
+int configure_via_default(uint8_t n);
+
+int ct_processor_entry(struct __processor_entry *pr);
+void ct_bus_entry(struct __bus_entry *bus);
+void ct_io_apic_entry(struct __io_apic_entry *ioa);
+void ct_io_intr_entry(struct __io_intr_entry *iointr);
+void ct_l_intr_entry(struct __l_intr_entry *lintr);
+
+void ct_extended_entries(void);
+
+static struct mps_fs *fs;
+static struct mps_ct *ct;
+
+struct __processor_entry *processor_entries = NULL;
+struct __bus_entry *bus_entries = NULL;
+struct __io_apic_entry *io_apic_entries = NULL;
+struct __io_intr_entry *io_intr_entries = NULL;
+struct __l_intr_entry *l_intr_entries = NULL;
+
+int processor_entry_cnt = 0;
+int bus_entry_cnt = 0;
+int io_apic_entry_cnt = 0;
+int io_intr_entry_cnt = 0;
+int l_intr_entry_cnt = 0;
+
+waitq_t ap_completion_wq;
+
+/*
+ * Implementation of IA-32 SMP configuration interface.
+ */
+static count_t get_cpu_count(void);
+static bool is_cpu_enabled(index_t i);
+static bool is_bsp(index_t i);
+static uint8_t get_cpu_apic_id(index_t i);
+static int mps_irq_to_pin(int irq);
+
+struct smp_config_operations mps_config_operations = {
+	.cpu_count = get_cpu_count,
+	.cpu_enabled = is_cpu_enabled,
+	.cpu_bootstrap = is_bsp,
+	.cpu_apic_id = get_cpu_apic_id,
+	.irq_to_pin = mps_irq_to_pin
+};
+
+count_t get_cpu_count(void)
+{
+	return processor_entry_cnt;
+}
+
+bool is_cpu_enabled(index_t i)
+{
+	ASSERT(i < processor_entry_cnt);
+	return processor_entries[i].cpu_flags & 0x1;
+}
+
+bool is_bsp(index_t i)
+{
+	ASSERT(i < processor_entry_cnt);
+	return processor_entries[i].cpu_flags & 0x2;
+}
+
+uint8_t get_cpu_apic_id(index_t i)
+{
+	ASSERT(i < processor_entry_cnt);
+	return processor_entries[i].l_apic_id;
+}
+
+
+/*
+ * Used to check the integrity of the MP Floating Structure.
+ */
+int mps_fs_check(uint8_t *base)
+{
+	int i;
+	uint8_t sum;
+	
+	for (i = 0, sum = 0; i < 16; i++)
+		sum += base[i];
+	
+	return !sum;
+}
+
+/*
+ * Used to check the integrity of the MP Configuration Table.
+ */
+int mps_ct_check(void)
+{
+	uint8_t *base = (uint8_t *) ct;
+	uint8_t *ext = base + ct->base_table_length;
+	uint8_t sum;
+	int i;	
+	
+	/* count the checksum for the base table */
+	for (i=0,sum=0; i < ct->base_table_length; i++)
+		sum += base[i];
+		
+	if (sum)
+		return 0;
+		
+	/* count the checksum for the extended table */
+	for (i=0,sum=0; i < ct->ext_table_length; i++)
+		sum += ext[i];
+		
+	return sum == ct->ext_table_checksum;
+}
+
+void mps_init(void)
+{
+	uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) };
+	int i, j, length[2] = { 1024, 64*1024 };
+	
+
+	/*
+	 * Find MP Floating Pointer Structure
+	 * 1a. search first 1K of EBDA
+	 * 1b. if EBDA is undefined, search last 1K of base memory
+	 *  2. search 64K starting at 0xf0000
+	 */
+
+	addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024);
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < length[i]; j += 16) {
+			if (*((uint32_t *) &addr[i][j]) == FS_SIGNATURE && mps_fs_check(&addr[i][j])) {
+				fs = (struct mps_fs *) &addr[i][j];
+				goto fs_found;
+			}
+		}
+	}
+
+	return;
+	
+fs_found:
+	printf("%p: MPS Floating Pointer Structure\n", fs);
+
+	if (fs->config_type == 0 && fs->configuration_table) {
+		if (fs->mpfib2 >> 7) {
+			printf("%s: PIC mode not supported\n", __FUNCTION__);
+			return;
+		}
+
+		ct = (struct mps_ct *)PA2KA((uintptr_t)fs->configuration_table);
+		config.cpu_count = configure_via_ct();
+	} 
+	else
+		config.cpu_count = configure_via_default(fs->config_type);
+
+	return;
+}
+
+int configure_via_ct(void)
+{
+	uint8_t *cur;
+	int i, cnt;
+		
+	if (ct->signature != CT_SIGNATURE) {
+		printf("%s: bad ct->signature\n", __FUNCTION__);
+		return 1;
+	}
+	if (!mps_ct_check()) {
+		printf("%s: bad ct checksum\n", __FUNCTION__);
+		return 1;
+	}
+	if (ct->oem_table) {
+		printf("%s: ct->oem_table not supported\n", __FUNCTION__);
+		return 1;
+	}
+	
+	l_apic = (uint32_t *)(uintptr_t)ct->l_apic;
+
+	cnt = 0;
+	cur = &ct->base_table[0];
+	for (i=0; i < ct->entry_count; i++) {
+		switch (*cur) {
+			/* Processor entry */
+			case 0:	
+				processor_entries = processor_entries ? processor_entries : (struct __processor_entry *) cur;
+				processor_entry_cnt++;
+				cnt += ct_processor_entry((struct __processor_entry *) cur);
+				cur += 20;
+				break;
+
+			/* Bus entry */
+			case 1:
+				bus_entries = bus_entries ? bus_entries : (struct __bus_entry *) cur;
+				bus_entry_cnt++;
+				ct_bus_entry((struct __bus_entry *) cur);
+				cur += 8;
+				break;
+				
+			/* I/O Apic */
+			case 2:
+				io_apic_entries = io_apic_entries ? io_apic_entries : (struct __io_apic_entry *) cur;
+				io_apic_entry_cnt++;
+				ct_io_apic_entry((struct __io_apic_entry *) cur);
+				cur += 8;
+				break;
+				
+			/* I/O Interrupt Assignment */
+			case 3:
+				io_intr_entries = io_intr_entries ? io_intr_entries : (struct __io_intr_entry *) cur;
+				io_intr_entry_cnt++;
+				ct_io_intr_entry((struct __io_intr_entry *) cur);
+				cur += 8;
+				break;
+
+			/* Local Interrupt Assignment */
+			case 4:
+				l_intr_entries = l_intr_entries ? l_intr_entries : (struct __l_intr_entry *) cur;
+				l_intr_entry_cnt++;
+				ct_l_intr_entry((struct __l_intr_entry *) cur);
+				cur += 8;
+				break;
+
+			default:
+				/*
+				 * Something is wrong. Fallback to UP mode.
+				 */
+				 
+				printf("%s: ct badness\n", __FUNCTION__);
+				return 1;
+		}
+	}
+	
+	/*
+	 * Process extended entries.
+	 */
+	ct_extended_entries();
+	return cnt;
+}
+
+int configure_via_default(uint8_t n)
+{
+	/*
+	 * Not yet implemented.
+	 */
+	printf("%s: not supported\n", __FUNCTION__);
+	return 1;
+}
+
+
+int ct_processor_entry(struct __processor_entry *pr)
+{
+	/*
+	 * Ignore processors which are not marked enabled.
+	 */
+	if ((pr->cpu_flags & (1<<0)) == 0)
+		return 0;
+	
+	apic_id_mask |= (1<<pr->l_apic_id); 
+	return 1;
+}
+
+void ct_bus_entry(struct __bus_entry *bus)
+{
+#ifdef MPSCT_VERBOSE
+	char buf[7];
+	memcpy((void *) buf, (void *) bus->bus_type, 6);
+	buf[6] = 0;
+	printf("bus%d: %s\n", bus->bus_id, buf);
+#endif
+}
+
+void ct_io_apic_entry(struct __io_apic_entry *ioa)
+{
+	static int io_apic_count = 0;
+
+	/* this ioapic is marked unusable */
+	if ((ioa->io_apic_flags & 1) == 0)
+		return;
+	
+	if (io_apic_count++ > 0) {
+		/*
+		 * Multiple IO APIC's are currently not supported.
+		 */
+		return;
+	}
+	
+	io_apic = (uint32_t *)(uintptr_t)ioa->io_apic;
+}
+
+//#define MPSCT_VERBOSE
+void ct_io_intr_entry(struct __io_intr_entry *iointr)
+{
+#ifdef MPSCT_VERBOSE
+	switch (iointr->intr_type) {
+	    case 0: printf("INT"); break;
+	    case 1: printf("NMI"); break;
+	    case 2: printf("SMI"); break;
+	    case 3: printf("ExtINT"); break;
+	}
+	putchar(',');
+	switch (iointr->poel&3) {
+	    case 0: printf("bus-like"); break;
+	    case 1: printf("active high"); break;
+	    case 2: printf("reserved"); break;
+	    case 3: printf("active low"); break;
+	}
+	putchar(',');
+	switch ((iointr->poel>>2)&3) {
+	    case 0: printf("bus-like"); break;
+	    case 1: printf("edge-triggered"); break;
+	    case 2: printf("reserved"); break;
+	    case 3: printf("level-triggered"); break;
+	}
+	putchar(',');
+	printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
+	putchar(',');
+	printf("io_apic%d,pin%d", iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
+	putchar('\n');	
+#endif
+}
+
+void ct_l_intr_entry(struct __l_intr_entry *lintr)
+{
+#ifdef MPSCT_VERBOSE
+	switch (lintr->intr_type) {
+	    case 0: printf("INT"); break;
+	    case 1: printf("NMI"); break;
+	    case 2: printf("SMI"); break;
+	    case 3: printf("ExtINT"); break;
+	}
+	putchar(',');
+	switch (lintr->poel&3) {
+	    case 0: printf("bus-like"); break;
+	    case 1: printf("active high"); break;
+	    case 2: printf("reserved"); break;
+	    case 3: printf("active low"); break;
+	}
+	putchar(',');
+	switch ((lintr->poel>>2)&3) {
+	    case 0: printf("bus-like"); break;
+	    case 1: printf("edge-triggered"); break;
+	    case 2: printf("reserved"); break;
+	    case 3: printf("level-triggered"); break;
+	}
+	putchar(',');
+	printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
+	putchar(',');
+	printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
+	putchar('\n');
+#endif
+}
+
+void ct_extended_entries(void)
+{
+	uint8_t *ext = (uint8_t *) ct + ct->base_table_length;
+	uint8_t *cur;
+
+	for (cur = ext; cur < ext + ct->ext_table_length; cur += cur[CT_EXT_ENTRY_LEN]) {
+		switch (cur[CT_EXT_ENTRY_TYPE]) {
+			default:
+				printf("%p: skipping MP Configuration Table extended entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]);
+				break;
+		}
+	}
+}
+
+int mps_irq_to_pin(int irq)
+{
+	int i;
+	
+	for(i=0;i<io_intr_entry_cnt;i++) {
+		if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0)
+			return io_intr_entries[i].dst_io_apic_pin;
+	}
+	
+	return -1;
+}
+
+#endif /* CONFIG_SMP */
+
+/** @}
+ */
Index: kernel/arch/xen32/src/smp/smp.c
===================================================================
--- kernel/arch/xen32/src/smp/smp.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
+++ kernel/arch/xen32/src/smp/smp.c	(revision 983cd37421607bd0fcff257f1c42e6d26cae0ca0)
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2005 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 xen32	
+ * @{
+ */
+/** @file
+ */
+
+#include <smp/smp.h>
+#include <arch/smp/smp.h>
+#include <arch/smp/mps.h>
+#include <arch/smp/ap.h>
+#include <arch/boot/boot.h>
+#include <genarch/acpi/acpi.h>
+#include <genarch/acpi/madt.h>
+#include <config.h>
+#include <synch/waitq.h>
+#include <synch/synch.h>
+#include <arch/pm.h>
+#include <func.h>
+#include <panic.h>
+#include <debug.h>
+#include <arch/asm.h>
+#include <mm/frame.h>
+#include <mm/page.h>
+#include <mm/slab.h>
+#include <mm/as.h>
+#include <print.h>
+#include <memstr.h>
+#include <arch/drivers/i8259.h>
+
+#ifdef CONFIG_SMP
+
+static struct smp_config_operations *ops = NULL;
+
+void smp_init(void)
+{
+	uintptr_t l_apic_address, io_apic_address;
+
+	if (acpi_madt) {
+		acpi_madt_parse();
+		ops = &madt_config_operations;
+	}
+	if (config.cpu_count == 1) {
+		mps_init();
+		ops = &mps_config_operations;
+	}
+
+	l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_ATOMIC | FRAME_KA);
+	if (!l_apic_address)
+		panic("cannot allocate address for l_apic\n");
+
+	io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME, FRAME_ATOMIC | FRAME_KA);
+	if (!io_apic_address)
+		panic("cannot allocate address for io_apic\n");
+
+	if (config.cpu_count > 1) {		
+		page_mapping_insert(AS_KERNEL, l_apic_address, (uintptr_t) l_apic, 
+				  PAGE_NOT_CACHEABLE);
+		page_mapping_insert(AS_KERNEL, io_apic_address, (uintptr_t) io_apic,
+				  PAGE_NOT_CACHEABLE);
+				  
+		l_apic = (uint32_t *) l_apic_address;
+		io_apic = (uint32_t *) io_apic_address;
+        }
+}
+
+/*
+ * Kernel thread for bringing up application processors. It becomes clear
+ * that we need an arrangement like this (AP's being initialized by a kernel
+ * thread), for a thread has its dedicated stack. (The stack used during the
+ * BSP initialization (prior the very first call to scheduler()) will be used
+ * as an initialization stack for each AP.)
+ */
+void kmp(void *arg)
+{
+	int i;
+	
+	ASSERT(ops != NULL);
+
+	waitq_initialize(&ap_completion_wq);
+
+	/*
+	 * We need to access data in frame 0.
+	 * We boldly make use of kernel address space mapping.
+	 */
+
+	/*
+	 * Save 0xa to address 0xf of the CMOS RAM.
+	 * BIOS will not do the POST after the INIT signal.
+	 */
+	outb(0x70,0xf);
+	outb(0x71,0xa);
+
+	pic_disable_irqs(0xffff);
+	apic_init();
+
+	for (i = 0; i < ops->cpu_count(); i++) {
+		struct descriptor *gdt_new;
+	
+		/*
+		 * Skip processors marked unusable.
+		 */
+		if (!ops->cpu_enabled(i))
+			continue;
+
+		/*
+		 * The bootstrap processor is already up.
+		 */
+		if (ops->cpu_bootstrap(i))
+			continue;
+
+		if (ops->cpu_apic_id(i) == l_apic_id()) {
+			printf("%s: bad processor entry #%d, will not send IPI to myself\n", __FUNCTION__, i);
+			continue;
+		}
+		
+		/*
+		 * Prepare new GDT for CPU in question.
+		 */
+		if (!(gdt_new = (struct descriptor *) malloc(GDT_ITEMS*sizeof(struct descriptor), FRAME_ATOMIC)))
+			panic("couldn't allocate memory for GDT\n");
+
+		memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor));
+		memsetb((uintptr_t)(&gdt_new[TSS_DES]), sizeof(struct descriptor), 0);
+		gdtr.base = (uintptr_t) gdt_new;
+
+		if (l_apic_send_init_ipi(ops->cpu_apic_id(i))) {
+			/*
+			 * There may be just one AP being initialized at
+			 * the time. After it comes completely up, it is
+			 * supposed to wake us up.
+			 */
+			if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) == ESYNCH_TIMEOUT)
+				printf("%s: waiting for cpu%d (APIC ID = %d) timed out\n", __FUNCTION__, config.cpu_active > i ? config.cpu_active : i, ops->cpu_apic_id(i));
+		} else
+			printf("INIT IPI for l_apic%d failed\n", ops->cpu_apic_id(i));
+	}
+}
+
+int smp_irq_to_pin(int irq)
+{
+	ASSERT(ops != NULL);
+	return ops->irq_to_pin(irq);
+}
+
+#endif /* CONFIG_SMP */
+
+/** @}
+ */
