Index: arch/ppc32/include/asm/regname.h
===================================================================
--- arch/ppc32/include/asm/regname.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc32/include/asm/regname.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -220,7 +220,3 @@
 #define hid0_dci	(1 << 10)
 
-/* Cache sizes */
-#define L1_CACHE_LINES (128 * 8)
-#define L1_CACHE_BYTES 5
-
 #endif
Index: arch/ppc32/include/mm/asid.h
===================================================================
--- arch/ppc32/include/mm/asid.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc32/include/mm/asid.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -27,10 +27,4 @@
  */
 
-/*
- * ia32 has no hardware support for address space identifiers.
- * This file is provided to do nop-implementation of mm/asid.h
- * interface.
- */
-
 #ifndef __ppc32_ASID_H__
 #define __ppc32_ASID_H__
Index: arch/ppc32/include/types.h
===================================================================
--- arch/ppc32/include/types.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc32/include/types.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -34,5 +34,5 @@
 typedef signed char __s8;
 typedef signed short __s16;
-typedef signed long __s32;
+typedef signed int __s32;
 typedef signed long long __s64;
 
Index: arch/ppc64/Makefile.inc
===================================================================
--- arch/ppc64/Makefile.inc	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/Makefile.inc	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -39,5 +39,5 @@
 #
 
-CFLAGS += -mcpu=powerpc64 -m64
+CFLAGS += -mcpu=powerpc64 -msoft-float -m64
 AFLAGS += -a64
 LFLAGS += -no-check-sections -N
@@ -57,5 +57,4 @@
 
 ARCH_SOURCES = \
-	arch/$(ARCH)/src/console.c \
 	arch/$(ARCH)/src/context.S \
 	arch/$(ARCH)/src/debug/panic.s \
@@ -68,8 +67,9 @@
 	arch/$(ARCH)/src/asm.S \
 	arch/$(ARCH)/src/cpu/cpu.c \
+	arch/$(ARCH)/src/proc/scheduler.c \
 	arch/$(ARCH)/src/ddi/ddi.c \
-	arch/$(ARCH)/src/proc/scheduler.c \
 	arch/$(ARCH)/src/mm/as.c \
 	arch/$(ARCH)/src/mm/frame.c \
 	arch/$(ARCH)/src/mm/memory_init.c \
-	arch/$(ARCH)/src/mm/page.c 
+	arch/$(ARCH)/src/mm/page.c \
+	arch/$(ARCH)/src/mm/tlb.c
Index: arch/ppc64/include/asm.h
===================================================================
--- arch/ppc64/include/asm.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/asm.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -40,9 +40,10 @@
  * @return Old interrupt priority level.
  */
-static inline ipl_t interrupts_enable(void) {
+static inline ipl_t interrupts_enable(void)
+{
 	ipl_t v;
 	ipl_t tmp;
 	
-	__asm__ volatile (
+	asm volatile (
 		"mfmsr %0\n"
 		"mfmsr %1\n"
@@ -61,9 +62,10 @@
  * @return Old interrupt priority level.
  */
-static inline ipl_t interrupts_disable(void) {
+static inline ipl_t interrupts_disable(void)
+{
 	ipl_t v;
 	ipl_t tmp;
 	
-	__asm__ volatile (
+	asm volatile (
 		"mfmsr %0\n"
 		"mfmsr %1\n"
@@ -81,8 +83,9 @@
  * @param ipl Saved interrupt priority level.
  */
-static inline void interrupts_restore(ipl_t ipl) {
+static inline void interrupts_restore(ipl_t ipl)
+{
 	ipl_t tmp;
 	
-	__asm__ volatile (
+	asm volatile (
 		"mfmsr %1\n"
 		"rlwimi  %0, %1, 0, 17, 15\n"
@@ -93,4 +96,5 @@
 		: "=r" (ipl), "=r" (tmp)
 		: "0" (ipl)
+		: "cr0"
 	);
 }
@@ -102,7 +106,9 @@
  * @return Current interrupt priority level.
  */
-static inline ipl_t interrupts_read(void) {
+static inline ipl_t interrupts_read(void)
+{
 	ipl_t v;
-	__asm__ volatile (
+	
+	asm volatile (
 		"mfmsr %0\n"
 		: "=r" (v)
@@ -121,6 +127,9 @@
 	__address v;
 	
-	__asm__ volatile ("and %0, %%sp, %1\n" : "=r" (v) : "r" (~(STACK_SIZE-1)));
-	
+	asm volatile (
+		"and %0, %%sp, %1\n"
+		: "=r" (v)
+		: "r" (~(STACK_SIZE - 1))
+	);
 	return v;
 }
@@ -133,3 +142,5 @@
 void asm_delay_loop(__u32 t);
 
+extern void userspace_asm(__address uspace_uarg, __address stack, __address entry);
+
 #endif
Index: arch/ppc64/include/asm/regname.h
===================================================================
--- arch/ppc64/include/asm/regname.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/asm/regname.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -195,4 +195,6 @@
 #define msr_ir	(1 << 4)
 #define msr_dr	(1 << 5)
+#define msr_pr	(1 << 14)
+#define msr_ee	(1 << 15)
 
 /* HID0 bits */
Index: arch/ppc64/include/atomic.h
===================================================================
--- arch/ppc64/include/atomic.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/atomic.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -34,5 +34,5 @@
 	long tmp;
 
-	asm __volatile__ (
+	asm volatile (
 		"1:\n"
 		"lwarx %0, 0, %2\n"
@@ -42,5 +42,6 @@
 		: "=&r" (tmp), "=m" (val->count)
 		: "r" (&val->count), "m" (val->count)
-		: "cc");
+		: "cc"
+	);
 }
 
@@ -49,5 +50,5 @@
 	long tmp;
 
-	asm __volatile__(
+	asm volatile (
 		"1:\n"
 		"lwarx %0, 0, %2\n"
@@ -57,5 +58,6 @@
 		: "=&r" (tmp), "=m" (val->count)
 		: "r" (&val->count), "m" (val->count)
-		: "cc");
+		: "cc"
+	);
 }
 
Index: arch/ppc64/include/barrier.h
===================================================================
--- arch/ppc64/include/barrier.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/barrier.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -30,10 +30,10 @@
 #define __ppc64_BARRIER_H__
 
-#define CS_ENTER_BARRIER()	__asm__ volatile ("" ::: "memory")
-#define CS_LEAVE_BARRIER()	__asm__ volatile ("" ::: "memory")
+#define CS_ENTER_BARRIER()	asm volatile ("" ::: "memory")
+#define CS_LEAVE_BARRIER()	asm volatile ("" ::: "memory")
 
-#define memory_barrier() __asm__ volatile ("sync" ::: "memory")
-#define read_barrier() __asm__ volatile ("sync" ::: "memory")
-#define write_barrier() __asm__ volatile ("eieio" ::: "memory")
+#define memory_barrier() asm volatile ("sync" ::: "memory")
+#define read_barrier() asm volatile ("sync" ::: "memory")
+#define write_barrier() asm volatile ("eieio" ::: "memory")
 
 #endif
Index: arch/ppc64/include/boot/boot.h
===================================================================
--- arch/ppc64/include/boot/boot.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/boot/boot.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -35,4 +35,5 @@
 #define TEMP_STACK_SIZE 0x100
 
+#define TASKMAP_MAX_RECORDS 32
 #define MEMMAP_MAX_RECORDS 32
 
@@ -42,10 +43,20 @@
 
 typedef struct {
+	__address addr;
+	__u64 size;
+} utask_t;
+
+typedef struct {
+	__u32 count;
+	utask_t tasks[TASKMAP_MAX_RECORDS];
+} taskmap_t;
+
+typedef struct {
 	__address start;
-	__u32 size;
+	__u64 size;
 } memzone_t;
 
 typedef struct {
-	__u32 total;
+	__u64 total;
 	__u32 count;
 	memzone_t zones[MEMMAP_MAX_RECORDS];
@@ -61,4 +72,5 @@
 
 typedef struct {
+	taskmap_t taskmap;
 	memmap_t memmap;
 	screen_t screen;
Index: arch/ppc64/include/byteorder.h
===================================================================
--- arch/ppc64/include/byteorder.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/byteorder.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -54,7 +54,11 @@
 	__address v;
 	
-	__asm__ volatile ("lwbrx %0, %1, %2\n" : "=r" (v) : "i" (0) , "r" (&n));
-	
+	asm volatile (
+		"lwbrx %0, %1, %2\n"
+		: "=r" (v)
+		: "i" (0), "r" (&n)
+	);
 	return v;
 }
+
 #endif
Index: ch/ppc64/include/console.h
===================================================================
--- arch/ppc64/include/console.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ 	(revision )
@@ -1,34 +1,0 @@
-/*
- * 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.
- */
-
-#ifndef __ppc64_CONSOLE_H__
-#define __ppc64_CONSOLE_H__
-
-extern void ppc64_console_init(void);
-
-#endif
Index: arch/ppc64/include/cpuid.h
===================================================================
--- arch/ppc64/include/cpuid.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/cpuid.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -39,6 +39,6 @@
 static inline void cpu_version(struct cpu_info *info)
 {
-	__asm__ volatile (
-		"mfspr %0, 287\n"
+	asm volatile (
+		"mfpvr %0\n"
 		: "=r" (*info)
 	);
Index: arch/ppc64/include/elf.h
===================================================================
--- arch/ppc64/include/elf.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/elf.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -30,5 +30,5 @@
 #define __ppc64_ELF_H__
 
-#define	ELF_MACHINE		EM_PPC
+#define	ELF_MACHINE		EM_PPC64
 #define ELF_DATA_ENCODING	ELFDATA2MSB
 #define ELF_CLASS		ELFCLASS32
Index: arch/ppc64/include/exception.h
===================================================================
--- arch/ppc64/include/exception.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
+++ arch/ppc64/include/exception.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef __ppc64_EXCEPTION_H__
+#define __ppc64_EXCEPTION_H__
+
+#ifndef __ppc64_TYPES_H__
+#  include <arch/types.h>
+#endif
+
+#include <typedefs.h>
+
+struct istate {
+	__u64 r0;
+	__u64 r2;
+	__u64 r3;
+	__u64 r4;
+	__u64 r5;
+	__u64 r6;
+	__u64 r7;
+	__u64 r8;
+	__u64 r9;
+	__u64 r10;
+	__u64 r11;
+	__u64 r13;
+	__u64 r14;
+	__u64 r15;
+	__u64 r16;
+	__u64 r17;
+	__u64 r18;
+	__u64 r19;
+	__u64 r20;
+	__u64 r21;
+	__u64 r22;
+	__u64 r23;
+	__u64 r24;
+	__u64 r25;
+	__u64 r26;
+	__u64 r27;
+	__u64 r28;
+	__u64 r29;
+	__u64 r30;
+	__u64 r31;
+	__u64 cr;
+	__u64 pc;
+	__u64 srr1;
+	__u64 lr;
+	__u64 ctr;
+	__u64 xer;
+	__u64 r12;
+	__u64 sp;
+};
+
+static inline void istate_set_retaddr(istate_t *istate, __address retaddr)
+{
+	istate->pc = retaddr;
+}
+
+#endif
Index: arch/ppc64/include/mm/asid.h
===================================================================
--- arch/ppc64/include/mm/asid.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/mm/asid.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -32,7 +32,7 @@
 typedef int asid_t;
 
-#define ASID_MAX_ARCH	3
+#define ASID_MAX_ARCH		3
 
-#define asid_get()	(ASID_START+1)
+#define asid_get()		(ASID_START+1)
 
 #endif
Index: arch/ppc64/include/mm/frame.h
===================================================================
--- arch/ppc64/include/mm/frame.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/mm/frame.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -31,8 +31,12 @@
 
 #define FRAME_WIDTH		12	/* 4K */
-#define FRAME_SIZE		(1<<FRAME_WIDTH)
+#define FRAME_SIZE		(1 << FRAME_WIDTH)
 
 #ifdef KERNEL
 #ifndef __ASM__
+
+#include <arch/types.h> 
+
+extern __address last_frame;
 
 extern void frame_arch_init(void);
Index: arch/ppc64/include/mm/page.h
===================================================================
--- arch/ppc64/include/mm/page.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/mm/page.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -45,39 +45,51 @@
 #endif
 
-#define PTL0_ENTRIES_ARCH		0
-#define PTL1_ENTRIES_ARCH		0
-#define PTL2_ENTRIES_ARCH		0
-#define PTL3_ENTRIES_ARCH		0
+/*
+ * Implementation of generic 4-level page table interface,
+ * the hardware Page Hash Table is used as cache.
+ *
+ * Page table layout:
+ * - 32-bit virtual addressess
+ * - Offset is 12 bits => pages are 4K long
+ * - PTL0 has 1024 entries (10 bits)
+ * - PTL1 is not used
+ * - PTL2 is not used
+ * - PLT3 has 1024 entries (10 bits)
+ */
 
-#define PTL0_INDEX_ARCH(vaddr)		0
-#define PTL1_INDEX_ARCH(vaddr)		0
-#define PTL2_INDEX_ARCH(vaddr)		0
-#define PTL3_INDEX_ARCH(vaddr)		0
+#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 *) (ptl0))[(i)].pfn << 12)
+#define GET_PTL2_ADDRESS_ARCH(ptl1, i)		(ptl1)
+#define GET_PTL3_ADDRESS_ARCH(ptl2, i)		(ptl2)
+#define GET_FRAME_ADDRESS_ARCH(ptl3, i)		(((pte_t *) (ptl3))[(i)].pfn << 12)
 
 #define SET_PTL0_ADDRESS_ARCH(ptl0)
-
-#define GET_PTL1_ADDRESS_ARCH(ptl0, i)		((pte_t *) 0)
-#define GET_PTL2_ADDRESS_ARCH(ptl1, i)		((pte_t *) 0)
-#define GET_PTL3_ADDRESS_ARCH(ptl2, i)		((pte_t *) 0)
-#define GET_FRAME_ADDRESS_ARCH(ptl3, i)		((pte_t *) 0)
-
-#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
+#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)	(((pte_t *) (ptl0))[(i)].pfn = (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)
+#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a)	(((pte_t *) (ptl3))[(i)].pfn = (a) >> 12)
 
-#define GET_PTL1_FLAGS_ARCH(ptl0, i)		0
-#define GET_PTL2_FLAGS_ARCH(ptl1, i)		0
-#define GET_PTL3_FLAGS_ARCH(ptl2, i)		0
-#define GET_FRAME_FLAGS_ARCH(ptl3, i)		0
+#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)
+#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)
+#define SET_FRAME_FLAGS_ARCH(ptl3, i, x)	set_pt_flags((pte_t *) (ptl3), (index_t) (i), (x))
 
-#define PTE_VALID_ARCH(p)		1
-#define PTE_PRESENT_ARCH(p)		1
-#define PTE_GET_FRAME_ARCH(p)		0
+#define PTE_VALID_ARCH(pte)			(*((__u32 *) (pte)) != 0)
+#define PTE_PRESENT_ARCH(pte)		((pte)->p != 0)
+#define PTE_GET_FRAME_ARCH(pte)		((pte)->pfn << 12)
 
 #ifndef __ASM__
@@ -87,5 +99,49 @@
 #include <arch/types.h>
 
+static inline int get_pt_flags(pte_t *pt, index_t i)
+{
+	pte_t *p = &pt[i];
+	
+	return (
+		(1 << PAGE_CACHEABLE_SHIFT) |
+		((!p->p) << PAGE_PRESENT_SHIFT) |
+		(1 << PAGE_USER_SHIFT) |
+		(1 << PAGE_READ_SHIFT) |
+		(1 << PAGE_WRITE_SHIFT) |
+		(1 << PAGE_EXEC_SHIFT) |
+		(p->g << PAGE_GLOBAL_SHIFT)
+	);
+}
+
+static inline void set_pt_flags(pte_t *pt, index_t i, int flags)
+{
+	pte_t *p = &pt[i];
+	
+	p->p = !(flags & PAGE_NOT_PRESENT);
+	p->g = (flags & PAGE_GLOBAL) != 0;
+	p->valid = 1;
+}
+
 extern void page_arch_init(void);
+
+#define PHT_BITS	16
+#define PHT_ORDER	4
+
+typedef struct {
+	unsigned v : 1;          /**< Valid */
+	unsigned vsid : 24;      /**< Virtual Segment ID */
+	unsigned h : 1;          /**< Primary/secondary hash */
+	unsigned api : 6;        /**< Abbreviated Page Index */
+	unsigned rpn : 20;       /**< Real Page Number */
+	unsigned reserved0 : 3;
+	unsigned r : 1;          /**< Reference */
+	unsigned c : 1;          /**< Change */
+	unsigned wimg : 4;       /**< Access control */
+	unsigned reserved1 : 1;
+	unsigned pp : 2;         /**< Page protection */
+} phte_t;
+
+extern void pht_refill(bool data, istate_t *istate);
+extern void pht_init(void);
 
 #endif /* __ASM__ */
Index: arch/ppc64/include/mm/tlb.h
===================================================================
--- arch/ppc64/include/mm/tlb.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/mm/tlb.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -30,6 +30,4 @@
 #define __ppc64_TLB_H__
 
-#define tlb_arch_init()
-#define tlb_print()
 
 #endif
Index: arch/ppc64/include/types.h
===================================================================
--- arch/ppc64/include/types.h	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/include/types.h	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -34,6 +34,6 @@
 typedef signed char __s8;
 typedef signed short __s16;
-typedef signed long __s32;
-typedef signed long long __s64;
+typedef signed int __s32;
+typedef signed long __s64;
 
 typedef unsigned char __u8;
@@ -43,11 +43,18 @@
 
 typedef __u64 __address;
-typedef __u32 pfn_t;
+typedef __u64 pfn_t;
 
 typedef __u64 ipl_t;
 
-typedef __u64 __native;
+typedef __u32 __native;
 
-typedef __u32 pte_t;
+/** Page Table Entry. */
+typedef struct {
+	unsigned p : 1;       /**< Present bit. */
+	unsigned a : 1;       /**< Accessed bit. */
+	unsigned g : 1;       /**< Global bit. */
+	unsigned valid : 1;   /**< Valid content even if not present. */
+	unsigned pfn : 20;    /**< Physical frame number. */
+} pte_t;
 
 #endif
Index: arch/ppc64/src/asm.S
===================================================================
--- arch/ppc64/src/asm.S	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/asm.S	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -31,61 +31,170 @@
 .text
 
+.global userspace_asm
 .global iret
+.global iret_syscall
 .global memsetb
 .global memcpy
+.global memcpy_from_uspace
+.global memcpy_to_uspace
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
+
+userspace_asm:
+
+	# r3 = uspace_uarg
+	# r4 = stack
+	# r5 = entry
+	
+	# disable interrupts
+
+	mfmsr r31
+	rlwinm r31, r31, 0, 17, 15
+	mtmsr r31
+	
+	# set entry point
+	
+	mtsrr0 r5
+	
+	# set problem state, enable interrupts
+	
+	ori r31, r31, msr_pr
+	ori r31, r31, msr_ee
+	mtsrr1 r31
+	
+	# set stack
+	
+	mr sp, r4
+	
+	# jump to userspace
+	
+	rfi
 
 iret:
-	lwz r3, 144(sp)
-	mtxer r3
-	
-	lwz r3, 140(sp)
-	mtctr r3
-	
-	lwz r3, 136(sp)
-	mtcr r3
-	
-	lwz r3, 132(sp)
-	mtlr r3
-	
-	lwz r3, 128(sp)
-	mtspr srr1, r3
-	
-	lwz r3, 124(sp)
-	mtspr srr0, r3
-	
-	lwz r0, 0(sp)
-	lwz r2, 4(sp)
-	lwz r3, 8(sp)
-	lwz r4, 12(sp)
-	lwz r5, 16(sp)
-	lwz r6, 20(sp)
-	lwz r7, 24(sp)
-	lwz r8, 28(sp)
-	lwz r9, 32(sp)
-	lwz r10, 36(sp)
-	lwz r11, 40(sp)
-	lwz r12, 44(sp)
-	lwz r13, 48(sp)
-	lwz r14, 52(sp)
-	lwz r15, 56(sp)
-	lwz r16, 60(sp)
-	lwz r17, 64(sp)
-	lwz r18, 68(sp)
-	lwz r19, 72(sp)
-	lwz r20, 76(sp)
-	lwz r21, 80(sp)
-	lwz r22, 84(sp)
-	lwz r23, 88(sp)
-	lwz r24, 92(sp)
-	lwz r25, 96(sp)
-	lwz r26, 100(sp)
-	lwz r27, 104(sp)
-	lwz r28, 108(sp)
-	lwz r29, 112(sp)
-	lwz r30, 116(sp)
-	lwz r31, 120(sp)
-	
-	mfspr sp, sprg1
-	
+	
+	# disable interrupts
+	
+	mfmsr r31
+	rlwinm r31, r31, 0, 17, 15
+	mtmsr r31
+	
+	lwz r0, 8(sp)
+	lwz r2, 12(sp)
+	lwz r3, 16(sp)
+	lwz r4, 20(sp)
+	lwz r5, 24(sp)
+	lwz r6, 28(sp)
+	lwz r7, 32(sp)
+	lwz r8, 36(sp)
+	lwz r9, 40(sp)
+	lwz r10, 44(sp)
+	lwz r11, 48(sp)
+	lwz r13, 52(sp)
+	lwz r14, 56(sp)
+	lwz r15, 60(sp)
+	lwz r16, 64(sp)
+	lwz r17, 68(sp)
+	lwz r18, 72(sp)
+	lwz r19, 76(sp)
+	lwz r20, 80(sp)
+	lwz r21, 84(sp)
+	lwz r22, 88(sp)
+	lwz r23, 92(sp)
+	lwz r24, 96(sp)
+	lwz r25, 100(sp)
+	lwz r26, 104(sp)
+	lwz r27, 108(sp)
+	lwz r28, 112(sp)
+	lwz r29, 116(sp)
+	lwz r30, 120(sp)
+	lwz r31, 124(sp)
+	
+	lwz r12, 128(sp)
+	mtcr r12
+	
+	lwz r12, 132(sp)
+	mtsrr0 r12
+	
+	lwz r12, 136(sp)
+	mtsrr1 r12
+	
+	lwz r12, 140(sp)
+	mtlr r12
+	
+	lwz r12, 144(sp)
+	mtctr r12
+	
+	lwz r12, 148(sp)
+	mtxer r12
+	
+	lwz r12, 152(sp)
+	lwz sp, 156(sp)
+	
+	rfi
+
+iret_syscall:
+	
+	# reset decrementer
+
+	li r31, 1000
+	mtdec r31
+	
+	# disable interrupts
+	
+	mfmsr r31
+	rlwinm r31, r31, 0, 17, 15
+	mtmsr r31
+	
+	lwz r0, 8(sp)
+	lwz r2, 12(sp)
+	lwz r4, 20(sp)
+	lwz r5, 24(sp)
+	lwz r6, 28(sp)
+	lwz r7, 32(sp)
+	lwz r8, 36(sp)
+	lwz r9, 40(sp)
+	lwz r10, 44(sp)
+	lwz r11, 48(sp)
+	lwz r13, 52(sp)
+	lwz r14, 56(sp)
+	lwz r15, 60(sp)
+	lwz r16, 64(sp)
+	lwz r17, 68(sp)
+	lwz r18, 72(sp)
+	lwz r19, 76(sp)
+	lwz r20, 80(sp)
+	lwz r21, 84(sp)
+	lwz r22, 88(sp)
+	lwz r23, 92(sp)
+	lwz r24, 96(sp)
+	lwz r25, 100(sp)
+	lwz r26, 104(sp)
+	lwz r27, 108(sp)
+	lwz r28, 112(sp)
+	lwz r29, 116(sp)
+	lwz r30, 120(sp)
+	lwz r31, 124(sp)
+	
+	lwz r12, 128(sp)
+	mtcr r12
+	
+	lwz r12, 132(sp)
+	mtsrr0 r12
+	
+	lwz r12, 136(sp)
+	mtsrr1 r12
+	
+	lwz r12, 140(sp)
+	mtlr r12
+	
+	lwz r12, 144(sp)
+	mtctr r12
+	
+	lwz r12, 148(sp)
+	mtxer r12
+	
+	lwz r12, 152(sp)
+	lwz sp, 156(sp)
+
 	rfi
 	
@@ -134,4 +243,7 @@
 
 memcpy:
+memcpy_from_uspace:
+memcpy_to_uspace:
+
 	srwi. r7, r5, 3
 	addi r6, r3, -4
@@ -194,2 +306,6 @@
 	mtctr r7
 	b 1b
+
+memcpy_from_uspace_failover_address:
+memcpy_to_uspace_failover_address:
+	b memcpy_from_uspace_failover_address
Index: arch/ppc64/src/boot/boot.S
===================================================================
--- arch/ppc64/src/boot/boot.S	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/boot/boot.S	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -35,16 +35,19 @@
 kernel_image_start:
 
-	# load temporary stack
+	# load temporal kernel stack
 	
-	lis sp, end_stack@ha
-	addi sp, sp, end_stack@l
+	lis sp, kernel_stack@ha
+	addi sp, sp, kernel_stack@l
+	
+	# set kernel stack for interrupt handling
+	
+	mr r31, sp
+	subis r31, r31, 0x8000
+	mtsprg0 r31
 	
 	# r3 contains physical address of bootinfo_t
 	# r4 contains size of bootinfo_t
 	
-	lis r31, 0x80000000@ha
-	addi r31, r31, 0x80000000@l
-	
-	add r3, r3, r31
+	addis r3, r3, 0x8000
 
 	lis r31, bootinfo@ha
@@ -68,8 +71,11 @@
 	bootinfo_end:
 	
+	bl arch_pre_main
 	b main_bsp
 
 .section K_DATA_START, "aw", @progbits
 
+.align 12
+kernel_stack_bottom:
 	.space TEMP_STACK_SIZE
-end_stack:
+kernel_stack:
Index: ch/ppc64/src/console.c
===================================================================
--- arch/ppc64/src/console.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ 	(revision )
@@ -1,41 +1,0 @@
-/*
- * 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.
- */
-
-#include <arch/boot/boot.h>
-#include <arch/console.h>
-#include <console/chardev.h>
-#include <console/console.h>
-#include <genarch/fb/fb.h>
-
-
-/** Initialize console to use frame buffer. */
-void ppc64_console_init(void)
-{
-	/* TODO: Framebuffer mapping */
-	fb_init(0xf0000000 + (bootinfo.screen.addr & ((__address) ~0 >> 15)), bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.bpp, bootinfo.screen.scanline);
-}
Index: arch/ppc64/src/dummy.s
===================================================================
--- arch/ppc64/src/dummy.s	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/dummy.s	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -29,26 +29,6 @@
 .text
 
-.global cpu_halt
 .global asm_delay_loop
-.global userspace
 .global sys_tls_set
-.global tlb_invalidate_all
-.global tlb_invalidate_asid
-.global tlb_invalidate_pages
-
-cpu_halt:
-	b cpu_halt
-
-tlb_invalidate_all:
-	b tlb_invalidate_all
-
-tlb_invalidate_asid:
-	b tlb_invalidate_asid
-
-tlb_invalidate_pages:
-	b tlb_invalidate_pages
-
-userspace:
-	b userspace
 
 sys_tls_set:
Index: arch/ppc64/src/exception.S
===================================================================
--- arch/ppc64/src/exception.S	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/exception.S	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -32,4 +32,121 @@
 .section K_UNMAPPED_TEXT_START, "ax"
 
+.macro CONTEXT_STORE
+	
+	# save R12 in SPRG1, backup CR in R12
+	# save SP in SPRG2
+
+	mtsprg1 r12
+	mfcr r12
+	mtsprg2 sp
+	
+	# check whether SP is in kernel
+	
+	andis. sp, sp, 0x8000
+	bne 1f
+	
+		# stack is in user-space
+		
+		mfsprg0 sp
+	
+	b 2f
+	
+	1:
+	
+		# stack is in kernel
+		
+		mfsprg2 sp
+		subis sp, sp, 0x8000
+	
+	2:
+	
+	subi sp, sp, 160
+	stw r0, 8(sp)
+	stw r2, 12(sp)
+	stw r3, 16(sp)
+	stw r4, 20(sp)
+	stw r5, 24(sp)
+	stw r6, 28(sp)
+	stw r7, 32(sp)
+	stw r8, 36(sp)
+	stw r9, 40(sp)
+	stw r10, 44(sp)
+	stw r11, 48(sp)
+	stw r13, 52(sp)
+	stw r14, 56(sp)
+	stw r15, 60(sp)
+	stw r16, 64(sp)
+	stw r17, 68(sp)
+	stw r18, 72(sp)
+	stw r19, 76(sp)
+	stw r20, 80(sp)
+	stw r21, 84(sp)
+	stw r22, 88(sp)
+	stw r23, 92(sp)
+	stw r24, 96(sp)
+	stw r25, 100(sp)
+	stw r26, 104(sp)
+	stw r27, 108(sp)
+	stw r28, 112(sp)
+	stw r29, 116(sp)
+	stw r30, 120(sp)
+	stw r31, 124(sp)
+	
+	stw r12, 128(sp)
+	
+	mfsrr0 r12
+	stw r12, 132(sp)
+	
+	mfsrr1 r12
+	stw r12, 136(sp)
+	
+	mflr r12
+	stw r12, 140(sp)
+	
+	mfctr r12
+	stw r12, 144(sp)
+	
+	mfxer r12
+	stw r12, 148(sp)
+	
+	mfsprg1 r12
+	stw r12, 152(sp)
+	
+	mfsprg2 r12
+	stw r12, 156(sp)
+.endm
+
+.org 0x060
+jump_to_kernel:
+	lis r12, iret@ha
+	addi r12, r12, iret@l
+	mtlr r12
+
+	mfmsr r12
+	ori r12, r12, (msr_ir | msr_dr)@l
+	mtsrr1 r12
+	
+	addis sp, sp, 0x8000
+	mr r4, sp
+	addi r4, r4, 8
+	
+	rfi
+
+jump_to_kernel_syscall:
+	lis r12, syscall_handler@ha
+	addi r12, r12, syscall_handler@l
+	mtsrr0 r12
+	
+	lis r12, iret_syscall@ha
+	addi r12, r12, iret_syscall@l
+	mtlr r12
+
+	mfmsr r12
+	ori r12, r12, (msr_ir | msr_dr)@l
+	mtsrr1 r12
+	
+	addis sp, sp, 0x8000
+	rfi
+
 .org 0x100
 .global exc_system_reset
@@ -45,20 +162,24 @@
 .global exc_data_storage
 exc_data_storage:
-	b exc_data_storage
-
-.org 0x380
-.global exc_data_segment
-exc_data_segment:
-	b exc_data_segment
+	CONTEXT_STORE
+	
+	lis r12, pht_refill@ha
+	addi r12, r12, pht_refill@l
+	mtsrr0 r12
+	
+	li r3, 1
+	b jump_to_kernel
 
 .org 0x400
 .global exc_instruction_storage
 exc_instruction_storage:
-	b exc_instruction_storage
-
-.org 0x480
-.global exc_instruction_segment
-exc_instruction_segment:
-	b exc_instruction_segment
+	CONTEXT_STORE
+	
+	lis r12, pht_refill@ha
+	addi r12, r12, pht_refill@l
+	mtsrr0 r12
+	
+	li r3, 0
+	b jump_to_kernel
 
 .org 0x500
@@ -85,74 +206,12 @@
 .global exc_decrementer
 exc_decrementer:
-	mtspr sprg1, sp
-	
-	subis sp, sp, 0x8000
-	
-	subi sp, sp, 144
-	stw r0, 0(sp)
-	stw r2, 4(sp)
-	stw r3, 8(sp)
-	stw r4, 12(sp)
-	stw r5, 16(sp)
-	stw r6, 20(sp)
-	stw r7, 24(sp)
-	stw r8, 28(sp)
-	stw r9, 32(sp)
-	stw r10, 36(sp)
-	stw r11, 40(sp)
-	stw r12, 44(sp)
-	stw r13, 48(sp)
-	stw r14, 52(sp)
-	stw r15, 56(sp)
-	stw r16, 60(sp)
-	stw r17, 64(sp)
-	stw r18, 68(sp)
-	stw r19, 72(sp)
-	stw r20, 76(sp)
-	stw r21, 80(sp)
-	stw r22, 84(sp)
-	stw r23, 88(sp)
-	stw r24, 92(sp)
-	stw r25, 96(sp)
-	stw r26, 100(sp)
-	stw r27, 104(sp)
-	stw r28, 108(sp)
-	stw r29, 112(sp)
-	stw r30, 116(sp)
-	stw r31, 120(sp)
-	
-	mfspr r3, srr0
-	stw r3, 124(sp)
-	
-	mfspr r3, srr1
-	stw r3, 128(sp)
-	
-	mflr r3
-	stw r3, 132(sp)
-	
-	mfcr r3
-	stw r3, 136(sp)
-	
-	mfctr r3
-	stw r3, 140(sp)
-	
-	mfxer r3
-	stw r3, 144(sp)
-
-	lis r3, exc_dispatch@ha
-	addi r3, r3, exc_dispatch@l
-	mtspr srr0, r3
-	
-	mfmsr r3
-	ori r3, r3, (msr_ir | msr_dr)@l
-	mtspr srr1, r3
-	
-	lis r3, iret@ha
-	addi r3, r3, iret@l
-	mtlr r3
-	
-	addis sp, sp, 0x8000
+	CONTEXT_STORE
+
+	lis r12, exc_dispatch@ha
+	addi r12, r12, exc_dispatch@l
+	mtsrr0 r12
+	
 	li r3, 10
-	rfid
+	b jump_to_kernel
 
 .org 0xa00
@@ -169,5 +228,7 @@
 .global exc_syscall
 exc_syscall:
-	b exc_syscall
+	CONTEXT_STORE	
+	
+	b jump_to_kernel_syscall
 
 .org 0xd00
Index: arch/ppc64/src/interrupt.c
===================================================================
--- arch/ppc64/src/interrupt.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/interrupt.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -32,5 +32,5 @@
 #include <arch.h>
 #include <time/clock.h>
-#include <print.h>
+#include <ipc/sysipc.h>
 
 
@@ -39,5 +39,6 @@
 	asm volatile (
 		"mtdec %0\n"
-		:: "r" (1000)
+		:
+		: "r" (1000)
 	);
 }
@@ -56,2 +57,10 @@
 	exc_register(VECTOR_DECREMENTER, "timer", exception_decrementer);
 }
+
+
+/* Reregister irq to be IPC-ready */
+void irq_ipc_bind_arch(__native irq)
+{
+	panic("not implemented\n");
+	/* TODO */
+}
Index: arch/ppc64/src/mm/memory_init.c
===================================================================
--- arch/ppc64/src/mm/memory_init.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/mm/memory_init.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -44,4 +44,4 @@
 	
 	for (i = 0; i < bootinfo.memmap.count; i++)
-		printf("base: %p size: %#x\n", bootinfo.memmap.zones[i].start, bootinfo.memmap.zones[i].size);
+		printf("base: %#x size: %#x\n", bootinfo.memmap.zones[i].start, bootinfo.memmap.zones[i].size);
 }
Index: arch/ppc64/src/mm/page.c
===================================================================
--- arch/ppc64/src/mm/page.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/mm/page.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -30,10 +30,267 @@
 #include <genarch/mm/page_pt.h>
 #include <arch/mm/frame.h>
+#include <arch/asm.h>
 #include <mm/frame.h>
 #include <mm/page.h>
+#include <mm/as.h>
+#include <arch.h>
 #include <arch/types.h>
+#include <arch/exception.h>
+#include <align.h>
+#include <config.h>
+#include <print.h>
+#include <symtab.h>
+
+static phte_t *phte;
+
+
+/** Try to find PTE for faulting address
+ *
+ * Try to find PTE for faulting address.
+ * The as->lock must be held on entry to this function
+ * if lock is true.
+ *
+ * @param as       Address space.
+ * @param lock     Lock/unlock the address space.
+ * @param badvaddr Faulting virtual address.
+ * @param istate   Pointer to interrupted state.
+ * @param pfrc     Pointer to variable where as_page_fault() return code will be stored.
+ * @return         PTE on success, NULL otherwise.
+ *
+ */
+static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, istate_t *istate, int *pfcr)
+{
+	/*
+	 * Check if the mapping exists in page tables.
+	 */	
+	pte_t *pte = page_mapping_find(as, badvaddr);
+	if ((pte) && (pte->p)) {
+		/*
+		 * Mapping found in page tables.
+		 * Immediately succeed.
+		 */
+		return pte;
+	} else {
+		int rc;
+	
+		/*
+		 * Mapping not found in page tables.
+		 * Resort to higher-level page fault handler.
+		 */
+		page_table_unlock(as, lock);
+		switch (rc = as_page_fault(badvaddr, istate)) {
+			case AS_PF_OK:
+				/*
+				 * The higher-level page fault handler succeeded,
+				 * The mapping ought to be in place.
+				 */
+				page_table_lock(as, lock);
+				pte = page_mapping_find(as, badvaddr);
+				ASSERT((pte) && (pte->p));
+				return pte;
+			case AS_PF_DEFER:
+				page_table_lock(as, lock);
+				*pfcr = rc;
+				return NULL;
+			case AS_PF_FAULT:
+				page_table_lock(as, lock);
+				printf("Page fault.\n");
+				*pfcr = rc;
+				return NULL;
+			default:
+				panic("unexpected rc (%d)\n", rc);
+		}	
+	}
+}
+
+
+static void pht_refill_fail(__address badvaddr, istate_t *istate)
+{
+	char *symbol = "";
+	char *sym2 = "";
+
+	char *s = get_symtab_entry(istate->pc);
+	if (s)
+		symbol = s;
+	s = get_symtab_entry(istate->lr);
+	if (s)
+		sym2 = s;
+	panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
+}
+
+
+static void pht_insert(const __address vaddr, const pfn_t pfn)
+{
+	__u32 page = (vaddr >> 12) & 0xffff;
+	__u32 api = (vaddr >> 22) & 0x3f;
+	__u32 vsid;
+	
+	asm volatile (
+		"mfsrin %0, %1\n"
+		: "=r" (vsid)
+		: "r" (vaddr)
+	);
+	
+	/* Primary hash (xor) */
+	__u32 h = 0;
+	__u32 hash = vsid ^ page;
+	__u32 base = (hash & 0x3ff) << 3;
+	__u32 i;
+	bool found = false;
+	
+	/* Find unused or colliding
+	   PTE in PTEG */
+	for (i = 0; i < 8; i++) {
+		if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) {
+			found = true;
+			break;
+		}
+	}
+	
+	if (!found) {
+		/* Secondary hash (not) */
+		__u32 base2 = (~hash & 0x3ff) << 3;
+		
+		/* Find unused or colliding
+		   PTE in PTEG */
+		for (i = 0; i < 8; i++) {
+			if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) {
+				found = true;
+				base = base2;
+				h = 1;
+				break;
+			}
+		}
+		
+		if (!found) {
+			// TODO: A/C precedence groups
+			i = page % 8;
+		}
+	}
+	
+	phte[base + i].v = 1;
+	phte[base + i].vsid = vsid;
+	phte[base + i].h = h;
+	phte[base + i].api = api;
+	phte[base + i].rpn = pfn;
+	phte[base + i].r = 0;
+	phte[base + i].c = 0;
+	phte[base + i].pp = 2; // FIXME
+}
+
+
+/** Process Instruction/Data Storage Interrupt
+ *
+ * @param data   True if Data Storage Interrupt.
+ * @param istate Interrupted register context.
+ *
+ */
+void pht_refill(bool data, istate_t *istate)
+{
+	__address badvaddr;
+	pte_t *pte;
+	int pfcr;
+	as_t *as;
+	bool lock;
+	
+	if (AS == NULL) {
+		as = AS_KERNEL;
+		lock = false;
+	} else {
+		as = AS;
+		lock = true;
+	}
+	
+	if (data) {
+		asm volatile (
+			"mfdar %0\n"
+			: "=r" (badvaddr)
+		);
+	} else
+		badvaddr = istate->pc;
+		
+	page_table_lock(as, lock);
+	
+	pte = find_mapping_and_check(as, lock, badvaddr, istate, &pfcr);
+	if (!pte) {
+		switch (pfcr) {
+			case AS_PF_FAULT:
+				goto fail;
+				break;
+			case AS_PF_DEFER:
+				/*
+		 		 * The page fault came during copy_from_uspace()
+				 * or copy_to_uspace().
+				 */
+				page_table_unlock(as, lock);
+				return;
+			default:
+				panic("Unexpected pfrc (%d)\n", pfcr);
+		}
+	}
+	
+	pte->a = 1; /* Record access to PTE */
+	pht_insert(badvaddr, pte->pfn);
+	
+	page_table_unlock(as, lock);
+	return;
+	
+fail:
+	page_table_unlock(as, lock);
+	pht_refill_fail(badvaddr, istate);
+}
+
+
+void pht_init(void)
+{
+	memsetb((__address) phte, 1 << PHT_BITS, 0);
+}
+
 
 void page_arch_init(void)
 {
-	page_mapping_operations = &pt_mapping_operations;
-}
+	if (config.cpu_active == 1) {
+		page_mapping_operations = &pt_mapping_operations;
+		
+		__address cur;
+		int flags;
+		
+		/* Frames below 128 MB are mapped using BAT,
+		   map rest of the physical memory */
+		for (cur = 128 << 20; 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);
+		}
+		
+		/* Allocate page hash table */
+		phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC));
+		phte = (phte_t *) PA2KA((__address) physical_phte);
+		
+		ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0);
+		pht_init();
+		
+		asm volatile (
+			"mtsdr1 %0\n"
+			:
+			: "r" ((__address) physical_phte)
+		);
+	}
+}
+
+
+__address hw_map(__address 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)
+	
+	__address 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: arch/ppc64/src/mm/tlb.c
===================================================================
--- arch/ppc64/src/mm/tlb.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
+++ arch/ppc64/src/mm/tlb.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -0,0 +1,77 @@
+/*
+ * 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 <mm/tlb.h>
+
+
+/** Initialize Page Hash Table.
+ *
+ * Setup the Page Hash Table with no entries.
+ *
+ */
+void tlb_arch_init(void)
+{
+	tlb_invalidate_all();
+}
+
+
+void tlb_invalidate_all(void)
+{
+	asm volatile (
+		"tlbia\n"
+		"tlbsync\n"
+	);
+}
+
+
+/** 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, __address page, count_t cnt)
+{
+	tlb_invalidate_all();
+}
+
+
+
+/** Print contents of Page Hash Table. */
+void tlb_print(void)
+{
+}
Index: arch/ppc64/src/ppc64.c
===================================================================
--- arch/ppc64/src/ppc64.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/ppc64.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -29,10 +29,24 @@
 #include <arch.h>
 #include <arch/boot/boot.h>
-#include <arch/console.h>
 #include <arch/mm/memory_init.h>
 #include <arch/interrupt.h>
-#include <mm/frame.h>
+#include <genarch/fb/fb.h>
+#include <userspace.h>
+#include <proc/uarg.h>
 
 bootinfo_t bootinfo;
+
+void arch_pre_main(void)
+{
+	/* Setup usermode */
+	init.cnt = bootinfo.taskmap.count;
+	
+	__u32 i;
+	
+	for (i = 0; i < bootinfo.taskmap.count; i++) {
+		init.tasks[i].addr = PA2KA(bootinfo.taskmap.tasks[i].addr);
+		init.tasks[i].size = bootinfo.taskmap.tasks[i].size;
+	}
+}
 
 void arch_pre_mm_init(void)
@@ -43,6 +57,4 @@
 	/* Start decrementer */
 	start_decrementer();
-
-	ppc64_console_init();
 }
 
@@ -50,4 +62,6 @@
 {
 	if (config.cpu_active == 1) {
+		fb_init(bootinfo.screen.addr, bootinfo.screen.width, bootinfo.screen.height, bootinfo.screen.bpp, bootinfo.screen.scanline);	
+	
 		/* Merge all zones to 1 big zone */
 		zone_merge_all();
@@ -68,2 +82,10 @@
 }
 
+void userspace(uspace_arg_t *kernel_uarg)
+{
+	userspace_asm((__address) kernel_uarg->uspace_uarg, (__address) kernel_uarg->uspace_stack + THREAD_STACK_SIZE - SP_DELTA, (__address) kernel_uarg->uspace_entry);
+	
+	/* Unreachable */
+	for (;;)
+		;
+}
Index: arch/ppc64/src/proc/scheduler.c
===================================================================
--- arch/ppc64/src/proc/scheduler.c	(revision bd55bbb6b76432980c7a7dec3ca9c347f0985943)
+++ arch/ppc64/src/proc/scheduler.c	(revision 48c1ef99601d3c28d9577147199e8e4f36174b69)
@@ -28,10 +28,8 @@
 
 #include <arch/mm/page.h>
+#include <arch/boot/boot.h>
 #include <proc/scheduler.h>
 #include <proc/thread.h>
 #include <arch.h>
-
-__address supervisor_sp;
-__address supervisor_sp_physical;
 
 /** Perform ppc64 specific tasks needed before the new task is run. */
@@ -43,6 +41,11 @@
 void before_thread_runs_arch(void)
 {
-	supervisor_sp = (__address) &THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA];
-	supervisor_sp_physical = KA2PA(supervisor_sp_physical);
+	pht_init();
+	tlb_invalidate_all();
+	asm volatile (
+		"mtsprg0 %0\n"
+		:
+		: "r" (KA2PA(&THREAD->kstack[THREAD_STACK_SIZE - SP_DELTA]))
+	);
 }
 
