diff --git a/arch/arm/balloon.c b/arch/arm/balloon.c
index 7f35328..958ecba 100644
--- a/arch/arm/balloon.c
+++ b/arch/arm/balloon.c
@@ -27,11 +27,6 @@
 
 unsigned long virt_kernel_area_end;   /* TODO: find a virtual area */
 
-int arch_expand_p2m(unsigned long max_pfn)
-{
-    return 0;
-}
-
 void arch_pfn_add(unsigned long pfn, unsigned long mfn)
 {
 }
diff --git a/arch/arm/mm.c b/arch/arm/mm.c
index fc8d4bc..4f58fc7 100644
--- a/arch/arm/mm.c
+++ b/arch/arm/mm.c
@@ -72,10 +72,6 @@ void arch_init_mm(unsigned long *start_pfn_p, unsigned long *max_pfn_p)
     *max_pfn_p = to_phys(new_device_tree) >> PAGE_SHIFT;
 }
 
-void arch_init_p2m(unsigned long max_pfn)
-{
-}
-
 void arch_init_demand_mapping_area(void)
 {
 }
diff --git a/arch/x86/balloon.c b/arch/x86/balloon.c
index 42389e4..16aaae4 100644
--- a/arch/x86/balloon.c
+++ b/arch/x86/balloon.c
@@ -26,11 +26,13 @@
 #include <mini-os/errno.h>
 #include <mini-os/lib.h>
 #include <mini-os/mm.h>
+#include <mini-os/paravirt.h>
 
 #ifdef CONFIG_BALLOON
 
 unsigned long virt_kernel_area_end = VIRT_KERNEL_AREA;
 
+#ifdef CONFIG_PARAVIRT
 static void p2m_invalidate(unsigned long *list, unsigned long start_idx)
 {
     unsigned long idx;
@@ -143,5 +145,16 @@ void arch_pfn_add(unsigned long pfn, unsigned long mfn)
         do_exit();
     }
 }
+#else
+void arch_pfn_add(unsigned long pfn, unsigned long mfn)
+{
+    pgentry_t *pgt;
+
+    pgt = need_pgt((unsigned long)pfn_to_virt(pfn));
+    ASSERT(pgt);
+    if ( !(*pgt & _PAGE_PSE) )
+        *pgt = (pgentry_t)(mfn << PAGE_SHIFT) | _PAGE_PRESENT | _PAGE_RW;
+}
+#endif
 
 #endif
diff --git a/arch/x86/mm.c b/arch/x86/mm.c
index fe18f53..0543017 100644
--- a/arch/x86/mm.c
+++ b/arch/x86/mm.c
@@ -39,6 +39,7 @@
 #include <mini-os/hypervisor.h>
 #include <mini-os/balloon.h>
 #include <mini-os/mm.h>
+#include <mini-os/paravirt.h>
 #include <mini-os/types.h>
 #include <mini-os/lib.h>
 #include <mini-os/xmalloc.h>
@@ -53,10 +54,24 @@
 
 unsigned long *phys_to_machine_mapping;
 unsigned long mfn_zero;
+pgentry_t *pt_base;
+static unsigned long first_free_pfn;
+static unsigned long last_free_pfn;
+
 extern char stack[];
 extern void page_walk(unsigned long va);
 
-#ifndef CONFIG_PARAVIRT
+#ifdef CONFIG_PARAVIRT
+void arch_mm_preinit(void *p)
+{
+    start_info_t *si = p;
+
+    phys_to_machine_mapping = (unsigned long *)si->mfn_list;
+    pt_base = (pgentry_t *)si->pt_base;
+    first_free_pfn = PFN_UP(to_phys(pt_base)) + si->nr_pt_frames;
+    last_free_pfn = si->nr_pages;
+}
+#else
 #include <mini-os/desc.h>
 user_desc gdt[NR_GDT_ENTRIES] =
 {
@@ -85,6 +100,22 @@ desc_ptr idt_ptr =
     .limit = sizeof(idt) - 1,
     .base = (unsigned long)&idt,
 };
+
+void arch_mm_preinit(void *p)
+{
+    long ret;
+    domid_t domid = DOMID_SELF;
+
+    pt_base = page_table_base;
+    first_free_pfn = PFN_UP(to_phys(&_end));
+    ret = HYPERVISOR_memory_op(XENMEM_current_reservation, &domid);
+    if ( ret < 0 )
+    {
+        xprintk("could not get memory size\n");
+        do_exit();
+    }
+    last_free_pfn = ret;
+}
 #endif
 
 /*
@@ -95,7 +126,7 @@ desc_ptr idt_ptr =
 static void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, 
                          unsigned long offset, unsigned long level)
 {   
-    pgentry_t *tab = (pgentry_t *)start_info.pt_base;
+    pgentry_t *tab = pt_base;
     unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn); 
     pgentry_t prot_e, prot_t;
     mmu_update_t mmu_updates[1];
@@ -172,8 +203,8 @@ static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
     unsigned long start_address, end_address;
     unsigned long pfn_to_map, pt_pfn = *start_pfn;
     static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
-    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
-    unsigned long pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+    pgentry_t *tab = pt_base, page;
+    unsigned long pt_mfn = pfn_to_mfn(virt_to_pfn(pt_base));
     unsigned long offset;
     int count = 0;
     int rc;
@@ -182,6 +213,7 @@ static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
        mapped, start the loop at the very beginning. */
     pfn_to_map = *start_pfn;
 
+#ifdef CONFIG_PARAVIRT
     if ( *max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START) )
     {
         printk("WARNING: Mini-OS trying to use Xen virtual space. "
@@ -193,6 +225,7 @@ static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
                ((unsigned long)pfn_to_virt(*max_pfn) - 
                 (unsigned long)&_text)>>20);
     }
+#endif
 
     start_address = (unsigned long)pfn_to_virt(pfn_to_map);
     end_address = (unsigned long)pfn_to_virt(*max_pfn);
@@ -202,8 +235,8 @@ static void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
 
     while ( start_address < end_address )
     {
-        tab = (pgentry_t *)start_info.pt_base;
-        pt_mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+        tab = pt_base;
+        pt_mfn = pfn_to_mfn(virt_to_pfn(pt_base));
 
 #if defined(__x86_64__)
         offset = l4_table_offset(start_address);
@@ -270,8 +303,8 @@ static void set_readonly(void *text, void *etext)
         ((unsigned long) text + PAGE_SIZE - 1) & PAGE_MASK;
     unsigned long end_address = (unsigned long) etext;
     static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
-    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
-    unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+    pgentry_t *tab = pt_base, page;
+    unsigned long mfn = pfn_to_mfn(virt_to_pfn(pt_base));
     unsigned long offset;
     int count = 0;
     int rc;
@@ -280,8 +313,8 @@ static void set_readonly(void *text, void *etext)
 
     while ( start_address + PAGE_SIZE <= end_address )
     {
-        tab = (pgentry_t *)start_info.pt_base;
-        mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
+        tab = pt_base;
+        mfn = pfn_to_mfn(virt_to_pfn(pt_base));
 
 #if defined(__x86_64__)
         offset = l4_table_offset(start_address);
@@ -343,8 +376,8 @@ static pgentry_t *get_pgt(unsigned long va)
     pgentry_t *tab;
     unsigned offset;
 
-    tab = (pgentry_t *)start_info.pt_base;
-    mfn = virt_to_mfn(start_info.pt_base);
+    tab = pt_base;
+    mfn = virt_to_mfn(pt_base);
 
 #if defined(__x86_64__)
     offset = l4_table_offset(va);
@@ -379,8 +412,8 @@ pgentry_t *need_pgt(unsigned long va)
     unsigned long pt_pfn;
     unsigned offset;
 
-    tab = (pgentry_t *)start_info.pt_base;
-    pt_mfn = virt_to_mfn(start_info.pt_base);
+    tab = pt_base;
+    pt_mfn = virt_to_mfn(pt_base);
 
 #if defined(__x86_64__)
     offset = l4_table_offset(va);
@@ -639,6 +672,7 @@ static void clear_bootstrap(void)
         printk("Unable to unmap NULL page. rc=%d\n", rc);
 }
 
+#ifdef CONFIG_PARAVIRT
 void p2m_chk_pfn(unsigned long pfn)
 {
     if ( (pfn >> L3_P2M_SHIFT) > 0 )
@@ -670,6 +704,7 @@ void arch_init_p2m(unsigned long max_pfn)
 
     arch_remap_p2m(max_pfn);
 }
+#endif
 
 void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
 {
@@ -683,8 +718,8 @@ void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
     printk("       _end: %p(VA)\n", &_end);
 
     /* First page follows page table pages. */
-    start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames;
-    max_pfn = start_info.nr_pages;
+    start_pfn = first_free_pfn;
+    max_pfn = last_free_pfn;
 
     if ( max_pfn >= MAX_MEM_SIZE / PAGE_SIZE )
         max_pfn = MAX_MEM_SIZE / PAGE_SIZE - 1;
diff --git a/arch/x86/setup.c b/arch/x86/setup.c
index efecefb..8b6bb6e 100644
--- a/arch/x86/setup.c
+++ b/arch/x86/setup.c
@@ -131,6 +131,9 @@ arch_init(void *par)
 	/* Initialize SSE */
 	sse_init();
 
+	/* Setup memory management info from start_info. */
+	arch_mm_preinit(par);
+
 	/* Copy the start_info struct to a globally-accessible area. */
 	/* WARN: don't do printk before here, it uses information from
 	   shared_info. Use xprintk instead. */
@@ -152,9 +155,6 @@ arch_init(void *par)
 			si->cmd_line ? (const char *)si->cmd_line : "NULL");
 	printk("       stack: %p-%p\n", stack, stack + sizeof(stack));
 
-	/* set up minimal memory infos */
-	phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
-
 	/* Grab the shared_info pointer and put it in a safe place. */
 	HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
 
diff --git a/arch/x86/traps.c b/arch/x86/traps.c
index 0b3d85b..2d3222d 100644
--- a/arch/x86/traps.c
+++ b/arch/x86/traps.c
@@ -97,9 +97,9 @@ DO_ERROR(18, "machine check", machine_check)
 
 void page_walk(unsigned long virt_address)
 {
-        pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+        pgentry_t *tab = pt_base, page;
         unsigned long addr = virt_address;
-        printk("Pagetable walk from virt %lx, base %lx:\n", virt_address, start_info.pt_base);
+        printk("Pagetable walk from virt %lx, base %p:\n", virt_address, pt_base);
     
 #if defined(__x86_64__)
         page = tab[l4_table_offset(addr)];
@@ -119,7 +119,7 @@ void page_walk(unsigned long virt_address)
 }
 
 static int handle_cow(unsigned long addr) {
-        pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
+        pgentry_t *tab = pt_base, page;
 	unsigned long new_page;
 	int rc;
 
diff --git a/balloon.c b/balloon.c
index 608492a..8d2f151 100644
--- a/balloon.c
+++ b/balloon.c
@@ -25,6 +25,7 @@
 #include <mini-os/balloon.h>
 #include <mini-os/errno.h>
 #include <mini-os/lib.h>
+#include <mini-os/paravirt.h>
 #include <xen/xen.h>
 #include <xen/memory.h>
 
diff --git a/include/arm/arch_mm.h b/include/arm/arch_mm.h
index f4685d8..79d9e05 100644
--- a/include/arm/arch_mm.h
+++ b/include/arm/arch_mm.h
@@ -29,9 +29,6 @@ extern uint32_t physical_address_offset;	/* Add this to a virtual address to get
 #define mfn_to_virt(_mfn)          (to_virt(PFN_PHYS(_mfn)))
 #define pfn_to_virt(_pfn)          (to_virt(PFN_PHYS(_pfn)))
 
-#define mfn_to_pfn(x) (x)
-#define pfn_to_mfn(x) (x)
-
 #define virtual_to_mfn(_virt)	   virt_to_mfn(_virt)
 
 // FIXME
diff --git a/include/balloon.h b/include/balloon.h
index d8710ad..8cd41af 100644
--- a/include/balloon.h
+++ b/include/balloon.h
@@ -39,16 +39,13 @@ extern unsigned long nr_mem_pages;
 void get_max_pages(void);
 int balloon_up(unsigned long n_pages);
 
-void arch_remap_p2m(unsigned long max_pfn);
 void mm_alloc_bitmap_remap(void);
-int arch_expand_p2m(unsigned long max_pfn);
 void arch_pfn_add(unsigned long pfn, unsigned long mfn);
 int chk_free_pages(unsigned long needed);
 
 #else /* CONFIG_BALLOON */
 
 static inline void get_max_pages(void) { }
-static inline void arch_remap_p2m(unsigned long max_pfn) { }
 static inline void mm_alloc_bitmap_remap(void) { }
 static inline int chk_free_pages(unsigned long needed)
 {
diff --git a/include/mm.h b/include/mm.h
index fc3128b..953570c 100644
--- a/include/mm.h
+++ b/include/mm.h
@@ -36,6 +36,7 @@
 #endif
 #include <xen/xen.h>
 
+#include <mini-os/paravirt.h>
 #include <mini-os/arch_limits.h>
 #include <mini-os/arch_mm.h>
 
@@ -67,7 +68,6 @@ static __inline__ int get_order(unsigned long size)
 
 void arch_init_demand_mapping_area(void);
 void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
-void arch_init_p2m(unsigned long max_pfn_p);
 
 unsigned long allocate_ondemand(unsigned long n, unsigned long alignment);
 /* map f[i*stride]+i*increment for i in 0..n-1, aligned on alignment pages */
diff --git a/include/paravirt.h b/include/paravirt.h
index 7852e16..15076be 100644
--- a/include/paravirt.h
+++ b/include/paravirt.h
@@ -26,7 +26,55 @@
 
 #if defined(CONFIG_PARAVIRT)
 
+#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
+#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
+
+/* for P2M */
+#ifdef __x86_64__
+#define P2M_SHIFT       9
 #else
+#define P2M_SHIFT       10
+#endif
+#define P2M_ENTRIES     (1UL << P2M_SHIFT)
+#define P2M_MASK        (P2M_ENTRIES - 1)
+#define L1_P2M_SHIFT    P2M_SHIFT
+#define L2_P2M_SHIFT    (2 * P2M_SHIFT)
+#define L3_P2M_SHIFT    (3 * P2M_SHIFT)
+#define L1_P2M_IDX(pfn) ((pfn) & P2M_MASK)
+#define L2_P2M_IDX(pfn) (((pfn) >> L1_P2M_SHIFT) & P2M_MASK)
+#define L3_P2M_IDX(pfn) (((pfn) >> L2_P2M_SHIFT) & P2M_MASK)
+#define INVALID_P2M_ENTRY (~0UL)
+
+void p2m_chk_pfn(unsigned long pfn);
+
+static inline unsigned long p2m_pages(unsigned long pages)
+{
+    return (pages + P2M_ENTRIES - 1) >> L1_P2M_SHIFT;
+}
+
+void arch_init_p2m(unsigned long max_pfn_p);
+
+#else
+
+#define mfn_to_pfn(_mfn) ((unsigned long)(_mfn))
+#define pfn_to_mfn(_pfn) ((unsigned long)(_pfn))
+
+static inline void arch_init_p2m(unsigned long max_pfn_p) { }
+
+#endif
+
+#if defined(CONFIG_PARAVIRT) && defined(CONFIG_BALLOON)
+
+void arch_remap_p2m(unsigned long max_pfn);
+int arch_expand_p2m(unsigned long max_pfn);
+
+#else
+
+static inline void arch_remap_p2m(unsigned long max_pfn) { }
+static inline int arch_expand_p2m(unsigned long max_pfn)
+{
+    return 0;
+}
 
 #endif
 
diff --git a/include/x86/arch_mm.h b/include/x86/arch_mm.h
index 2b18b34..28ab406 100644
--- a/include/x86/arch_mm.h
+++ b/include/x86/arch_mm.h
@@ -184,31 +184,6 @@ typedef unsigned long pgentry_t;
 #define IO_PROT (L1_PROT)
 #define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
 
-/* for P2M */
-#ifdef __x86_64__
-#define P2M_SHIFT       9
-#else
-#define P2M_SHIFT       10
-#endif
-#define P2M_ENTRIES     (1UL << P2M_SHIFT)
-#define P2M_MASK        (P2M_ENTRIES - 1)
-#define L1_P2M_SHIFT    P2M_SHIFT
-#define L2_P2M_SHIFT    (2 * P2M_SHIFT)
-#define L3_P2M_SHIFT    (3 * P2M_SHIFT)
-#define L1_P2M_IDX(pfn) ((pfn) & P2M_MASK)
-#define L2_P2M_IDX(pfn) (((pfn) >> L1_P2M_SHIFT) & P2M_MASK)
-#define L3_P2M_IDX(pfn) (((pfn) >> L2_P2M_SHIFT) & P2M_MASK)
-#define INVALID_P2M_ENTRY (~0UL)
-
-#ifndef __ASSEMBLY__
-void p2m_chk_pfn(unsigned long pfn);
-
-static inline unsigned long p2m_pages(unsigned long pages)
-{
-    return (pages + P2M_ENTRIES - 1) >> L1_P2M_SHIFT;
-}
-#endif
-
 #include "arch_limits.h"
 #define PAGE_SIZE       __PAGE_SIZE
 #define PAGE_SHIFT      __PAGE_SHIFT
@@ -232,10 +207,14 @@ typedef unsigned long paddr_t;
 typedef unsigned long maddr_t;
 #endif
 
+extern pgentry_t *pt_base;
+#ifdef CONFIG_PARAVIRT
 extern unsigned long *phys_to_machine_mapping;
+#else
+extern pgentry_t page_table_base[];
+#endif
 extern char _text, _etext, _erodata, _edata, _end;
 extern unsigned long mfn_zero;
-#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
 static __inline__ maddr_t phys_to_machine(paddr_t phys)
 {
 	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
@@ -243,7 +222,6 @@ static __inline__ maddr_t phys_to_machine(paddr_t phys)
 	return machine;
 }
 
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
 static __inline__ paddr_t machine_to_phys(maddr_t machine)
 {
 	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
@@ -267,13 +245,10 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
 #define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
 #define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
 
-
-#define PT_BASE			   ((pgentry_t *)start_info.pt_base)
-
 #ifdef __x86_64__
-#define virtual_to_l3(_virt)	   ((pgentry_t *)pte_to_virt(PT_BASE[l4_table_offset(_virt)]))
+#define virtual_to_l3(_virt)	   ((pgentry_t *)pte_to_virt(pt_base[l4_table_offset(_virt)]))
 #else
-#define virtual_to_l3(_virt)	   PT_BASE
+#define virtual_to_l3(_virt)	   pt_base
 #endif
 
 #define virtual_to_l2(_virt)	   ({ \
@@ -297,6 +272,7 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
 #define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, NULL, L1_PROT_RO)
 
 pgentry_t *need_pgt(unsigned long addr);
+void arch_mm_preinit(void *p);
 
 #endif
 
diff --git a/include/xen/arch-x86/xen-x86_32.h b/include/xen/arch-x86/xen-x86_32.h
index 1504191..6339727 100644
--- a/include/xen/arch-x86/xen-x86_32.h
+++ b/include/xen/arch-x86/xen-x86_32.h
@@ -55,6 +55,7 @@
 #define FLAT_USER_DS    FLAT_RING3_DS
 #define FLAT_USER_SS    FLAT_RING3_SS
 
+#ifdef CONFIG_PARAVIRT
 #define __HYPERVISOR_VIRT_START_PAE    0xF5800000
 #define __MACH2PHYS_VIRT_START_PAE     0xF5800000
 #define __MACH2PHYS_VIRT_END_PAE       0xF6800000
@@ -90,6 +91,7 @@
 #ifndef machine_to_phys_mapping
 #define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
 #endif
+#endif
 
 /* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
 #if defined(__XEN__) || defined(__XEN_TOOLS__)
diff --git a/include/xen/arch-x86/xen-x86_64.h b/include/xen/arch-x86/xen-x86_64.h
index 1c4e159..2c00111 100644
--- a/include/xen/arch-x86/xen-x86_64.h
+++ b/include/xen/arch-x86/xen-x86_64.h
@@ -70,6 +70,7 @@
 #define FLAT_USER_SS32 FLAT_RING3_SS32
 #define FLAT_USER_SS   FLAT_USER_SS64
 
+#ifdef CONFIG_PARAVIRT
 #define __HYPERVISOR_VIRT_START 0xFFFF800000000000
 #define __HYPERVISOR_VIRT_END   0xFFFF880000000000
 #define __MACH2PHYS_VIRT_START  0xFFFF800000000000
@@ -86,6 +87,7 @@
 #ifndef machine_to_phys_mapping
 #define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
 #endif
+#endif
 
 /*
  * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
diff --git a/mm.c b/mm.c
index ca0b9be..c76be7f 100644
--- a/mm.c
+++ b/mm.c
@@ -39,6 +39,7 @@
 #include <xen/memory.h>
 #include <mini-os/mm.h>
 #include <mini-os/balloon.h>
+#include <mini-os/paravirt.h>
 #include <mini-os/types.h>
 #include <mini-os/lib.h>
 #include <mini-os/xmalloc.h>
