diff -uprN linux-2.6.8.1/fs/proc/Makefile linux-2.6.8.1-patched/fs/proc/Makefile
--- linux-2.6.8.1/fs/proc/Makefile	2004-08-14 12:54:48.000000000 +0200
+++ linux-2.6.8.1-patched/fs/proc/Makefile	2004-10-23 19:59:36.845709776 +0200
@@ -8,7 +8,7 @@ proc-y			:= task_nommu.o
 proc-$(CONFIG_MMU)	:= task_mmu.o
 
 proc-y       += inode.o root.o base.o generic.o array.o \
-		kmsg.o proc_tty.o proc_misc.o
+		kmsg.o proc_tty.o proc_misc.o pagemap.o
 
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
diff -uprN linux-2.6.8.1/fs/proc/base.c linux-2.6.8.1-patched/fs/proc/base.c
--- linux-2.6.8.1/fs/proc/base.c	2004-08-14 12:55:35.000000000 +0200
+++ linux-2.6.8.1-patched/fs/proc/base.c	2004-10-23 19:59:36.851708864 +0200
@@ -48,6 +48,9 @@ enum pid_directory_inos {
 	PROC_TGID_TASK,
 	PROC_TGID_STATUS,
 	PROC_TGID_MEM,
+#ifdef CONFIG_NUMA
+	PROC_TGID_PAGEMAP,
+#endif
 	PROC_TGID_CWD,
 	PROC_TGID_ROOT,
 	PROC_TGID_EXE,
@@ -71,6 +74,9 @@ enum pid_directory_inos {
 	PROC_TID_INO,
 	PROC_TID_STATUS,
 	PROC_TID_MEM,
+#ifdef CONFIG_NUMA
+	PROC_TID_PAGEMAP,
+#endif
 	PROC_TID_CWD,
 	PROC_TID_ROOT,
 	PROC_TID_EXE,
@@ -113,6 +119,9 @@ static struct pid_entry tgid_base_stuff[
 	E(PROC_TGID_STATM,     "statm",   S_IFREG|S_IRUGO),
 	E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUGO),
 	E(PROC_TGID_MEM,       "mem",     S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_NUMA
+	E(PROC_TGID_PAGEMAP,   "pagemap", S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TGID_CWD,       "cwd",     S_IFLNK|S_IRWXUGO),
 	E(PROC_TGID_ROOT,      "root",    S_IFLNK|S_IRWXUGO),
 	E(PROC_TGID_EXE,       "exe",     S_IFLNK|S_IRWXUGO),
@@ -135,6 +144,9 @@ static struct pid_entry tid_base_stuff[]
 	E(PROC_TID_STATM,      "statm",   S_IFREG|S_IRUGO),
 	E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUGO),
 	E(PROC_TID_MEM,        "mem",     S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_NUMA
+	E(PROC_TID_PAGEMAP,    "pagemap", S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TID_CWD,        "cwd",     S_IFLNK|S_IRWXUGO),
 	E(PROC_TID_ROOT,       "root",    S_IFLNK|S_IRWXUGO),
 	E(PROC_TID_EXE,        "exe",     S_IFLNK|S_IRWXUGO),
@@ -689,6 +701,31 @@ static struct inode_operations proc_mem_
 	.permission	= proc_permission,
 };
 
+
+#ifdef CONFIG_NUMA
+
+
+extern int pagemap_show(struct seq_file *s, void *v);
+
+static int pagemap_open(struct inode *inode, struct file *file) {
+	struct task_struct *task = proc_task(inode);
+        int ret = single_open(file, pagemap_show, NULL);
+        if (!ret) {
+                struct seq_file *m = file->private_data;
+                m->private = task;
+        }
+        return ret;
+}
+
+static struct file_operations proc_pagemap_operations = {
+        .open           = pagemap_open,
+        .read           = seq_read,
+        .llseek         = seq_lseek,
+        .release        = single_release,
+};
+
+#endif /* CONFIG_NUMA */
+
 static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1342,6 +1379,12 @@ static struct dentry *proc_pident_lookup
 			inode->i_op = &proc_mem_inode_operations;
 			inode->i_fop = &proc_mem_operations;
 			break;
+#ifdef CONFIG_NUMA
+		case PROC_TID_PAGEMAP:
+		case PROC_TGID_PAGEMAP:
+			inode->i_fop = &proc_pagemap_operations;
+			break;
+#endif
 		case PROC_TID_MOUNTS:
 		case PROC_TGID_MOUNTS:
 			inode->i_fop = &proc_mounts_operations;
diff -uprN linux-2.6.8.1/fs/proc/pagemap.c linux-2.6.8.1-patched/fs/proc/pagemap.c
--- linux-2.6.8.1/fs/proc/pagemap.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8.1-patched/fs/proc/pagemap.c	2004-10-23 19:59:36.853708560 +0200
@@ -0,0 +1,76 @@
+#ifdef AS_MODULE
+#include <linux/module.h>
+#endif
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/sched.h>
+#include <linux/threads.h>
+
+/* Offsets into the range list array */
+#define COW_PAGE NR_CPUS
+#define NOT_PRESENT (NR_CPUS + 1)
+
+static inline int page2node(struct page *page) {
+        struct zone *zone = page_zone(page);
+        return zone->zone_pgdat->node_id;
+}
+
+int pagemap_show(struct seq_file *s, void *v) {
+        struct task_struct *task = s->private;
+	struct vm_area_struct *vma;
+        pgd_t *pgd;
+        pmd_t *pmd;
+        pte_t *ptep, pte;
+        unsigned long pga;
+        int n, i, vmac;
+
+	long node_pgc[NOT_PRESENT + 1];
+
+	down_read(&task->active_mm->mmap_sem);
+	vmac = 0;
+	/* For each VMA, translate each page it spans to a node number */
+	for (vma = task->active_mm->mmap; vma; vma = vma->vm_next) {
+		seq_printf(s, "VMA %d start %lx end %lx\n", vmac, vma->vm_start,
+		       vma->vm_end);
+                for (pga = PAGE_ALIGN(vma->vm_start); pga < vma->vm_end; 
+		     pga += PAGE_SIZE) {
+			n = NOT_PRESENT;
+			pgd = pgd_offset(task->active_mm, pga);
+			if (pgd_none(*pgd) || pgd_bad(*pgd))
+				goto out;
+			pmd = pmd_offset(pgd, pga);
+			if (pmd_none(*pmd) || pmd_bad(*pmd))
+				goto out;
+			ptep = pte_offset_map(pmd, pga);
+			if (!ptep)
+				goto out;
+			pte = *ptep;
+			pte_unmap(ptep);
+			n = page2node(pte_page(pte));
+			/* COW-page? Check if mapped to the zero page */
+			if (!pte_write(pte) && (vma->vm_flags & VM_SHARED) 
+			    && (vma->vm_flags & VM_WRITE)) {
+			    seq_printf(s, "%08lx-%08lx node %d COW\n", 
+				       pga, pga + PAGE_SIZE - 1, n); 
+			}
+
+			else {
+			    if (n == NOT_PRESENT)
+				seq_printf(s, "%08lx-%08lx node %d not present\n", 
+					   pga, pga + PAGE_SIZE - 1, n); 
+			    else
+				seq_printf(s, "%08lx-%08lx node %d \n", pga, 
+					   pga + PAGE_SIZE - 1, n); 
+			}
+		out:
+                }
+		vmac++;
+        }
+	up_read(&task->active_mm->mmap_sem);
+	
+	return 0;
+}
