Index: arch/ia32/include/mm/page.h
===================================================================
--- arch/ia32/include/mm/page.h	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/ia32/include/mm/page.h	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -30,6 +30,8 @@
 #define __ia32_PAGE_H__
 
+#include <mm/page.h>
 #include <arch/types.h>
 #include <arch/mm/frame.h>
+#include <typedefs.h>
 
 #define PAGE_SIZE	FRAME_SIZE
@@ -47,4 +49,5 @@
 #define PTL3_INDEX_ARCH(vaddr)	(((vaddr)>>12)&0x3ff)
 
+#define GET_PTL0_ADDRESS_ARCH()			((pte_t *) read_cr3())
 #define GET_PTL1_ADDRESS_ARCH(ptl0, i)		((pte_t *)((((pte_t *)(ptl0))[(i)].frame_address)<<12))
 #define GET_PTL2_ADDRESS_ARCH(ptl1, i)		(ptl1)
@@ -52,4 +55,19 @@
 #define GET_FRAME_ADDRESS_ARCH(ptl3, i)		((__address)((((pte_t *)(ptl3))[(i)].frame_address)<<12))
 
+#define SET_PTL0_ADDRESS_ARCH(ptl0)		(write_cr3((__address) (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))
 
 struct page_specifier {
@@ -66,5 +84,29 @@
 } __attribute__ ((packed));
 
-typedef struct page_specifier	pte_t;
+typedef struct page_specifier pte_t;
+
+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
+	);
+}
+
+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;
+	p->writeable = flags & PAGE_WRITE;
+}
 
 extern void page_arch_init(void);
Index: arch/ia32/src/mm/page.c
===================================================================
--- arch/ia32/src/mm/page.c	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/ia32/src/mm/page.c	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -87,50 +87,2 @@
 	paging_on();
 }
-
-/*
- * Besides mapping pages to frames, this function also sets the present bit of
- * the page's specifier in both page directory and respective page table. If
- * the page table for this page has not been allocated so far, it will take
- * care of it and allocate the necessary frame.
- *
- * PAGE_CACHEABLE flag: when set, it turns caches for that page on
- * PAGE_NOT_PRESENT flag: when set, it marks the page not present
- * PAGE_USER flag: when set, the page is accessible from userspace
- *
- * When the root parameter is non-zero, it is used as the page directory address.
- * Otherwise, the page directory address is read from CPU.
- */
-void map_page_to_frame(__address page, __address frame, int flags, __address root)
-{
-	struct page_specifier *pd, *pt;
-	__address dba, newpt;
-	int pde, pte;
-
-	if (root) dba = root;
-	else dba = read_cr3();
-
-	pde = page >> 22;		/* page directory entry */
-	pte = (page >> 12) & 0x3ff;	/* page table entry */
-	
-	pd = (struct page_specifier *) PA2KA(dba);
-	
-	if (!pd[pde].present) {
-		/*
-		 * There is currently no page table for this address. Allocate
-		 * frame for the page table and clean it.
-		 */
-		newpt = frame_alloc(FRAME_KA);
-		pd[pde].frame_address = KA2PA(newpt) >> 12;
-		memsetb(newpt, PAGE_SIZE, 0);
-		pd[pde].present = 1;
-		pd[pde].uaccessible = 1;
-	}
-	
-	pt = (struct page_specifier *) PA2KA((pd[pde].frame_address << 12));
-
-	pt[pte].frame_address = frame >> 12;
-	pt[pte].present = !(flags & PAGE_NOT_PRESENT);
-	pt[pte].page_cache_disable = !(flags & PAGE_CACHEABLE);
-	pt[pte].uaccessible = (flags & PAGE_USER) != 0;
-	pt[pte].writeable = (flags & PAGE_WRITE) != 0;	
-}
Index: arch/ia64/include/mm/page.h
===================================================================
--- arch/ia64/include/mm/page.h	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/ia64/include/mm/page.h	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -39,3 +39,36 @@
 #define page_arch_init()	;
 
+/*
+ * Implementation of generic 4-level page table interface.
+ * TODO: this is a fake implementation provided to satisfy the compiler
+ */
+#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 GET_PTL0_ADDRESS_ARCH()                 ((pte_t *) 0)
+#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_PTL0_ADDRESS_ARCH(ptl0)
+#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
+#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 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 SET_PTL1_FLAGS_ARCH(ptl0, 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)
+
+typedef __u64 pte_t;
+
 #endif
Index: arch/ia64/src/fake.s
===================================================================
--- arch/ia64/src/fake.s	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/ia64/src/fake.s	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -43,5 +43,4 @@
 .global cpu_sleep
 .global frame_arch_init
-.global map_page_to_frame
 
 before_thread_runs_arch:
@@ -59,5 +58,4 @@
 cpu_sleep:
 frame_arch_init:
-map_page_to_frame:
 	br.ret.sptk.many b0
 
Index: arch/mips/include/mm/page.h
===================================================================
--- arch/mips/include/mm/page.h	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/mips/include/mm/page.h	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -31,4 +31,5 @@
 
 #include <arch/mm/frame.h>
+#include <arch/types.h>
 
 #define PAGE_SIZE	FRAME_SIZE
@@ -39,3 +40,36 @@
 #define page_arch_init()	;
 
+/*
+ * Implementation of generic 4-level page table interface.
+ * TODO: this is a fake implementation provided to satisfy the compiler
+ */
+#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 GET_PTL0_ADDRESS_ARCH()                 ((pte_t *) 0)
+#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_PTL0_ADDRESS_ARCH(ptl0)
+#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
+#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 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 SET_PTL1_FLAGS_ARCH(ptl0, 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)
+
+typedef __u32 pte_t;
+
 #endif
Index: arch/mips/src/mm/page.c
===================================================================
--- arch/mips/src/mm/page.c	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ arch/mips/src/mm/page.c	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -29,7 +29,2 @@
 #include <arch/types.h>
 #include <mm/page.h>
-
-void map_page_to_frame(__address page, __address frame, int flags, __address root)
-{
-	/* TODO !!! */
-}
Index: include/mm/page.h
===================================================================
--- include/mm/page.h	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ include/mm/page.h	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -31,19 +31,28 @@
 
 #include <arch/types.h>
-#include <arch/mm/page.h>
 #include <typedefs.h>
 
-#define PAGE_NOT_CACHEABLE      (0<<0)
-#define PAGE_CACHEABLE          (1<<0)
+#define PAGE_CACHEABLE_SHIFT		0
+#define PAGE_NOT_CACHEABLE_SHIFT	PAGE_CACHEABLE_SHIFT
+#define PAGE_PRESENT_SHIFT		1
+#define PAGE_NOT_PRESENT_SHIFT		PAGE_PRESENT_SHIFT
+#define PAGE_USER_SHIFT			2
+#define PAGE_KERNEL_SHIFT		PAGE_USER_SHIFT
+#define PAGE_READ_SHIFT			3
+#define PAGE_WRITE_SHIFT		4
+#define PAGE_EXEC_SHIFT			5
 
-#define PAGE_PRESENT            (0<<1)
-#define PAGE_NOT_PRESENT        (1<<1)
+#define PAGE_NOT_CACHEABLE      (0<<PAGE_CACHEABLE_SHIFT)
+#define PAGE_CACHEABLE          (1<<PAGE_CACHEABLE_SHIFT)
 
-#define PAGE_USER               (1<<2)
-#define PAGE_KERNEL             (0<<2)
+#define PAGE_PRESENT            (0<<PAGE_PRESENT_SHIFT)
+#define PAGE_NOT_PRESENT        (1<<PAGE_PRESENT_SHIFT)
 
-#define PAGE_READ		(1<<3)
-#define PAGE_WRITE		(1<<4)
-#define PAGE_EXEC		(1<<5)
+#define PAGE_USER               (1<<PAGE_USER_SHIFT)
+#define PAGE_KERNEL             (0<<PAGE_USER_SHIFT)
+
+#define PAGE_READ		(1<<PAGE_READ_SHIFT)
+#define PAGE_WRITE		(1<<PAGE_WRITE_SHIFT)
+#define PAGE_EXEC		(1<<PAGE_EXEC_SHIFT)
 
 /*
@@ -61,8 +70,12 @@
 #define PTL3_INDEX(vaddr)		PTL3_INDEX_ARCH(vaddr)
 
+#define GET_PTL0_ADDRESS()		GET_PTL0_ADDRESS_ARCH()
+#define SET_PTL0_ADDRESS(ptl0)		SET_PTL0_ADDRESS_ARCH(ptl0)
+
 /*
  * These macros traverse the 4-level tree of page tables,
  * each descending by one level.
  */
+#define GET_PTL0_ADDRESS()		GET_PTL0_ADDRESS_ARCH()
 #define GET_PTL1_ADDRESS(ptl0, i)	GET_PTL1_ADDRESS_ARCH(ptl0, i)
 #define GET_PTL2_ADDRESS(ptl1, i)	GET_PTL2_ADDRESS_ARCH(ptl1, i)
@@ -74,8 +87,17 @@
  * tree of page tables on respective level.
  */
+#define SET_PTL0_ADDRESS(ptl0)		SET_PTL0_ADDRESS_ARCH(ptl0)
 #define SET_PTL1_ADDRESS(ptl0, i, a)	SET_PTL1_ADDRESS_ARCH(ptl0, i, a)
 #define SET_PTL2_ADDRESS(ptl1, i, a)	SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
 #define SET_PTL3_ADDRESS(ptl2, i, a)	SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
 #define SET_FRAME_ADDRESS(ptl3, i, a)	SET_FRAME_ADDRESS_ARCH(ptl3, i, a)
+
+/*
+ * These macros are provided to query various flags within the page tables.
+ */
+#define GET_PTL1_FLAGS(ptl0, i)		GET_PTL1_FLAGS_ARCH(ptl0, i)
+#define GET_PTL2_FLAGS(ptl1, i)		GET_PTL2_FLAGS_ARCH(ptl1, i)
+#define GET_PTL3_FLAGS(ptl2, i)		GET_PTL3_FLAGS_ARCH(ptl2, i)
+#define GET_FRAME_FLAGS(ptl3, i)	GET_FRAME_FLAGS_ARCH(ptl3, i)
 
 /*
@@ -87,4 +109,5 @@
 #define SET_FRAME_FLAGS(ptl3, i, x)	SET_FRAME_FLAGS_ARCH(ptl3, i, x)
 
+#include <arch/mm/page.h>
 
 extern void page_init(void);
Index: include/typedefs.h
===================================================================
--- include/typedefs.h	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ include/typedefs.h	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -37,4 +37,5 @@
 typedef unsigned int size_t;
 typedef unsigned int count_t;
+typedef unsigned int index_t;
 
 typedef struct config config_t;
Index: src/mm/page.c
===================================================================
--- src/mm/page.c	(revision 992bbb973fb33c1a5240dfc3591c3fa04a139966)
+++ src/mm/page.c	(revision ff9f858e06ba17699b8a6270f956c6f6bb1efe94)
@@ -28,7 +28,9 @@
 
 #include <mm/page.h>
+#include <mm/frame.h>
 #include <arch/mm/page.h>
 #include <arch/types.h>
 #include <typedefs.h>
+#include <arch/asm.h>
 
 void page_init(void)
@@ -59,2 +61,50 @@
 
 }
+
+/** Map page to frame
+ *
+ * Map virtual address 'page' to physical address 'frame'
+ * using 'flags'. Allocate and setup any missing page tables.
+ *
+ * @param page Virtual address of the page to be mapped.
+ * @param frame Physical address of memory frame to which the mapping is done.
+ * @param flags Flags to be used for mapping.
+ * @param root Explicit PTL0 address.
+ */
+void map_page_to_frame(__address page, __address frame, int flags, __address root)
+{
+        pte_t *ptl0, *ptl1, *ptl2, *ptl3;
+        __address newpt;
+
+        ptl0 = (pte_t *) PA2KA(root ? root : (__address) GET_PTL0_ADDRESS());
+
+        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
+                newpt = frame_alloc(FRAME_KA);
+                memsetb(newpt, PAGE_SIZE, 0);
+                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
+                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER);
+        }
+
+        ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
+
+        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
+                newpt = frame_alloc(FRAME_KA);
+                memsetb(newpt, PAGE_SIZE, 0);
+                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
+                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER);
+        }
+
+        ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
+
+        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
+                newpt = frame_alloc(FRAME_KA);
+                memsetb(newpt, PAGE_SIZE, 0);
+                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
+                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER);
+        }
+
+        ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
+
+        SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame);
+        SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags);
+}
