diff --git a/fs/proc/page.c b/fs/proc/page.c
index 6d8e6a9..b328b57 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -203,10 +203,113 @@ static const struct file_operations proc_kpageflags_operations = {
 	.read = kpageflags_read,
 };
 
+/* vaddr_to_paddr
+ * 
+ * Converts any virtual address to a physical address without using any
+ * assumptions but by walking the page table associated with the passed
+ * mm_struct. 
+ * Note that compared to the Popcorn Linux equivalent of this function
+ * we are not using pte/pmd/pud/pgd_bad because as written in "Understanding
+ * the Linux Kernel" p 61 from Bovet, "The pmd_bad macro is used by functions
+ * to check PMD entries passed as input parameters. It yelds the value 1 if the
+ * entry points to a bad Page Table - that is, (1) if the page is not in main
+ * memory; (2) the page allows only read access; and (3) either Accessed or
+ * Dirty is cleared (Linux always forces these flags to be set for every 
+ * existing Page Table."
+ */
+#define PGDIR_PAGE_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_PAGE_MASK 	(~(PGDIR_PAGE_SIZE-1))
+static unsigned long vaddr_to_paddr(struct mm_struct* mm, unsigned long vaddr)
+{
+    pte_t* pte = NULL;
+    pmd_t* pmd = NULL;                                                             
+    pud_t* pud = NULL;                                                             
+    pgd_t* pgd = NULL; 
+
+    pgd = pgd_offset(mm, vaddr);
+    if (pgd && !pgd_none(*pgd) && pgd_present(*pgd)) {
+      if (pgd_large(*pgd))
+        return (pgd_val(*pgd) & PTE_PFN_MASK) | (vaddr & ~PGDIR_PAGE_MASK);
+
+        pud = pud_offset(pgd,vaddr);                                               
+        if (pud && !pud_none(*pud) && pud_present(*pud)) {
+	  if (pud_large(*pud))
+	    return (pud_val(*pud) & PTE_PFN_MASK) | (vaddr & ~PUD_PAGE_MASK);
+	  
+            pmd = pmd_offset(pud,vaddr);
+            if(pmd && !pmd_none(*pmd) && pmd_present(*pmd)) {             
+	      if (pmd_large(*pmd))
+	        return (pmd_val(*pmd) & PTE_PFN_MASK) | (vaddr & ~PMD_PAGE_MASK);
+	      
+                pte = pte_offset_map(pmd,vaddr);                                   
+                if(pte && !pte_none(*pte) && pte_present(*pte)) { 
+                    return (pte_val(*pte) & PTE_PFN_MASK) | (vaddr & ~PAGE_MASK);
+                }
+		else
+		    return 0xa5a5a5a5a5a5a5a2;
+            }
+	    else
+	        return 0xa5a5a5a5a5a5a5a3;
+        }
+	else
+	    return 0xa5a5a5a5a5a5a5a4;	
+    }
+    else
+	return 0xa5a5a5a5a5a5a5a5;
+}
+
+static ssize_t kpagepaddr_read(struct file *file, char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	u64 __user *out = (u64 __user *)buf;
+	struct page *ppage;
+	unsigned long src = *ppos;
+	unsigned long pfn;
+	ssize_t ret = 0;
+
+/*printk(KERN_ALERT"%s: PTE_PFN_MASK %lx pte_mask %lx ~PTE %lx ~PMD %lx ~PUD %lx ~PGDIR %lx\n", 
+__func__, (unsigned long) PTE_PFN_MASK, (unsigned long)__supported_pte_mask,
+(unsigned long)(~PAGE_MASK), (unsigned long)(~PMD_PAGE_MASK), (unsigned long)(~PUD_PAGE_MASK), (unsigned long)(~PGDIR_PAGE_MASK));
+*/
+
+	pfn = src / KPMSIZE;
+	count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
+	if (src & KPMMASK || count & KPMMASK)
+		return -EINVAL;
+
+	while (count > 0) {
+		if (pfn_valid(pfn))
+			ppage = (struct page *)vaddr_to_paddr(&init_mm, (unsigned long)pfn_to_page(pfn));
+		else
+			ppage = NULL;
+
+		//if (put_user((u64)virt_to_phys(ppage), out)) { // NOTE this is from the original version without vaddr_to_paddr
+		if (put_user((u64)ppage, out)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		pfn++;
+		out++;
+		count -= KPMSIZE;
+	}
+
+	*ppos += (char __user *)out - buf;
+	if (!ret)
+		ret = (char __user *)out - buf;
+	return ret;
+}
+
+static const struct file_operations proc_kpagepaddr_operations = {
+	.llseek = mem_lseek,
+	.read = kpagepaddr_read,
+};
+
 static int __init proc_page_init(void)
 {
 	proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
 	proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
+	proc_create("kpagepaddr", S_IRUSR, NULL, &proc_kpagepaddr_operations);
 	return 0;
 }
 module_init(proc_page_init);