diff --git a/arch/x64/arch-setup.cc b/arch/x64/arch-setup.cc
index 4b24ec4aeaa6280aa5aa343d9e7b25ea63543d5a..5e1d9709d9066dca4f08e6d619169875f19b1ff1 100644
--- a/arch/x64/arch-setup.cc
+++ b/arch/x64/arch-setup.cc
@@ -7,6 +7,8 @@
 #include <alloca.h>
 #include <string.h>
 
+using namespace mmu;
+
 struct multiboot_info_type {
     u32 flags;
     u32 mem_lower;
@@ -63,8 +65,7 @@ void setup_temporary_phys_map()
     // duplicate 1:1 mapping into phys_mem
     u64 cr3 = processor::read_cr3();
     auto pt = reinterpret_cast<u64*>(cr3);
-    // assumes phys_mem = 0xffffc00000000000
-    pt[256+128] = pt[0];
+    pt[pt_index(phys_mem, 3)] = pt[0];
 }
 
 void for_each_e820_entry(void* e820_buffer, unsigned size, void (*f)(e820ent e))
diff --git a/core/mmu.cc b/core/mmu.cc
index 444067ad5bc76875351466bb0c9129fcff2cf897..1a1757545d0741636f3d9c53d073b0406fd2819a 100644
--- a/core/mmu.cc
+++ b/core/mmu.cc
@@ -176,12 +176,6 @@ phys virt_to_phys(void *virt)
     return static_cast<char*>(virt) - phys_mem;
 }
 
-unsigned pt_index(void *virt, unsigned level)
-{
-    auto v = reinterpret_cast<ulong>(virt);
-    return (v >> (12 + level * 9)) & 511;
-}
-
 void allocate_intermediate_level(hw_ptep ptep)
 {
     phys pt_page = virt_to_phys(memory::alloc_page());
diff --git a/include/mmu.hh b/include/mmu.hh
index b3acd9de3afc0c44b1e7b0c0a0bb9fa0c2f5c3c1..9b5ede71d1d9c96bce3e8d7f9472ab828849432c 100644
--- a/include/mmu.hh
+++ b/include/mmu.hh
@@ -15,6 +15,12 @@ typedef uint64_t f_offset;
 
 static constexpr char* phys_mem = reinterpret_cast<char*>(0xffffc00000000000);
 
+inline unsigned pt_index(void *virt, unsigned level)
+{
+    auto v = reinterpret_cast<ulong>(virt);
+    return (v >> (12 + level * 9)) & 511;
+}
+
 enum {
     perm_read = 1,
     perm_write = 2,