Index: memory.c
===================================================================
--- memory.c.orig
+++ memory.c
@@ -2819,7 +2819,7 @@ void
 cmd_vtop(void)
 {
 	int c;
-	ulong vaddr, context;
+	ulong vaddr, context, mm_struct_addr_new, mm_struct_addr_old;
 	int others;
 	ulong vtop_flags, loop_vtop_flags;
 	struct task_context *tc;
@@ -2827,7 +2827,7 @@ cmd_vtop(void)
 	vtop_flags = loop_vtop_flags = 0;
 	tc = NULL;
 
-        while ((c = getopt(argcnt, args, "ukc:")) != EOF) {
+	while ((c = getopt(argcnt, args, "ukc:M:")) != EOF) {
                 switch(c)
 		{
 		case 'c':
@@ -2853,6 +2853,11 @@ cmd_vtop(void)
 			vtop_flags |= KVADDR;
 			break;
 
+		case 'M':
+			vtop_flags |= MEMSTRUCTADDR;
+			mm_struct_addr_new = htol(optarg, FAULT_ON_ERROR, NULL);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -2893,8 +2898,22 @@ cmd_vtop(void)
 		if (others++)
 			fprintf(fp, "\n");
 
+		if (vtop_flags & MEMSTRUCTADDR) {
+			if (!IS_EXITING(tc->task))
+				error(FATAL, "Provided task is not exiting\n");
+
+			mm_struct_addr_old = task_to_context(tc->task)->mm_struct;
+			task_to_context(tc->task)->mm_struct = mm_struct_addr_new;
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+		}
+
 		do_vtop(vaddr, tc, vtop_flags | loop_vtop_flags);
 
+		if (vtop_flags & MEMSTRUCTADDR) {
+			task_to_context(tc->task)->mm_struct = mm_struct_addr_old;
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
+		}
+
 		optind++;
 	}
 }
@@ -2957,6 +2976,8 @@ do_vtop(ulong vaddr, struct task_context
 			fprintf(fp, "%s  (not accessible)\n\n", 
 				mkstring(buf1, UVADDR_PRLEN, LJUST|LONG_HEX,
 				    MKSTR(vaddr)));
+			if (!(task_to_context(tc->mm_struct)))
+				fprintf(fp, "mm_struct is NULL\n");
 			return;
 		}
 		if (!uvtop(tc, vaddr, &paddr, 0)) {
@@ -2977,7 +2998,7 @@ do_vtop(ulong vaddr, struct task_context
 		}
 		uvtop(tc, vaddr, &paddr, VERBOSE);
 		fprintf(fp, "\n");
-		vma = vm_area_dump(tc->task, UVADDR, vaddr, 0);
+		vma = vm_area_dump(tc->task, UVADDR, vaddr, 0, 0);
 		if (!page_exists) { 
 			if (swap_location(paddr, buf1))
                        		fprintf(fp, "\nSWAP: %s\n", buf1);
@@ -3151,6 +3172,7 @@ cmd_vm(void)
 	ulong flag;
 	ulong value;
 	ulong single_vma;
+	ulong mm_provided;
 	ulonglong llvalue;
 	struct task_context *tc;
 	struct reference reference, *ref;
@@ -3159,11 +3181,12 @@ cmd_vm(void)
 
 	flag = 0;
 	single_vma = 0;
+	mm_provided = 0;
 	radix = 0;
 	ref = NULL;
 	BZERO(&reference, sizeof(struct reference));
 
-        while ((c = getopt(argcnt, args, "f:pmvR:P:xd")) != EOF) {
+	while ((c = getopt(argcnt, args, "f:pmvR:P:xdM:")) != EOF) {
                 switch(c)
 		{
 		case 'f':
@@ -3209,7 +3232,7 @@ cmd_vm(void)
 			break;
 
 		case 'P':
-			if (flag)
+			if (flag & PHYSADDR)
 				argerrs++;
 			else {
 				flag |= PRINT_SINGLE_VMA;
@@ -3231,6 +3254,13 @@ cmd_vm(void)
 			radix = 10;
 			break;
 
+		case 'M':
+			if (flag & PHYSADDR)
+				argerrs++;
+			else
+				mm_provided = htol(optarg, FAULT_ON_ERROR, NULL);
+			break;
+
 		default:
 			argerrs++;
 			break;
@@ -3248,7 +3278,15 @@ cmd_vm(void)
 	if (!args[optind]) {
 		if (!ref)
 			print_task_header(fp, CURRENT_CONTEXT(), 0);
-		vm_area_dump(CURRENT_TASK(), flag, single_vma, ref);
+		if (mm_provided) {
+			if (!IS_EXITING(CURRENT_CONTEXT()->task))
+				error(FATAL, "Provided task is not exiting\n");
+
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+		}
+		vm_area_dump(CURRENT_TASK(), flag, single_vma, mm_provided, ref);
+		if (mm_provided)
+			ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
 		return;
 	}
 
@@ -3259,16 +3297,33 @@ cmd_vm(void)
 		{
 		case STR_PID:
 			for (tc = pid_to_context(value); tc; tc = tc->tc_next) {
-                                if (!ref)
-                                        print_task_header(fp, tc, subsequent++);
-                                vm_area_dump(tc->task, flag, single_vma, ref);
+				if (mm_provided) {
+					if (!IS_EXITING(tc->task))
+						error(FATAL, "Provided task is not exiting\n");
+					ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+				}
+
+				if (!ref)
+					print_task_header(fp, tc, subsequent++);
+
+				vm_area_dump(tc->task, flag, single_vma, mm_provided, ref);
+				if (mm_provided)
+					ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
                         }
 			break;
 
 		case STR_TASK:
 			if (!ref)
                                 print_task_header(fp, tc, subsequent++);
-                        vm_area_dump(tc->task, flag, single_vma, ref);
+			if (mm_provided) {
+				if (!IS_EXITING(tc->task))
+					error(FATAL, "Provided task is not exiting\n");
+				ULONG(tt->task_struct + OFFSET(task_struct_flags)) &= !PF_EXITING;
+			}
+                        vm_area_dump(tc->task, flag, single_vma, mm_provided, ref);
+			if (mm_provided) {
+				ULONG(tt->task_struct + OFFSET(task_struct_flags)) |= PF_EXITING;
+			}
 			break;
 
 		case STR_INVALID:
@@ -3523,13 +3578,14 @@ get_vm_flags(char *vma_buf)
 #define VM_REF_FOUND(X)    ((X) && ((X)->cmdflags & VM_REF_HEADER))
 
 ulong
-vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref)
+vm_area_dump(ulong task, ulong flag, ulong vaddr, ulong mm_addr, struct reference *ref)
 {
         struct task_context *tc;
 	ulong vma;
 	ulong vm_start;
 	ulong vm_end;
 	ulong vm_next, vm_mm;
+	ulong mm_struct_old;
 	char *dentry_buf, *vma_buf, *file_buf;
 	ulonglong vm_flags;
 	ulong vm_file, inode;
@@ -3547,6 +3603,10 @@ vm_area_dump(ulong task, ulong flag, ulo
 	char vma_header[BUFSIZE];
 
         tc = task_to_context(task);
+	if (mm_addr) {
+		mm_struct_old = tc->mm_struct;
+		tc->mm_struct = mm_addr;
+	}
 	tm = &task_mem_usage;
 	get_task_mem_usage(task, tm);
 
@@ -3580,6 +3640,8 @@ vm_area_dump(ulong task, ulong flag, ulo
         	print_task_header(fp, tc, 0);
 		PRINT_VM_DATA();
 		fprintf(fp, "\n");
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
                 return (ulong)NULL;
         }
 
@@ -3587,11 +3649,16 @@ vm_area_dump(ulong task, ulong flag, ulo
 	    !DO_REF_SEARCH(ref)) 
 		PRINT_VM_DATA();
 
-        if (!tm->mm_struct_addr)
-                return (ulong)NULL;
+	if (!tm->mm_struct_addr) {
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
+		return (ulong)NULL;
+	}
 
 	if (flag & PRINT_MM_STRUCT) {
 		dump_struct("mm_struct", tm->mm_struct_addr, radix);
+		if (mm_addr)
+			tc->mm_struct = mm_struct_old;
                 return (ulong)NULL;
 	}
 
@@ -3664,8 +3731,11 @@ vm_area_dump(ulong task, ulong flag, ulo
 		    ((vaddr >= vm_start) && (vaddr < vm_end)))) {
 			found = TRUE;
 
-			if (flag & VERIFY_ADDR)
+			if (flag & VERIFY_ADDR) {
+				if (mm_addr)
+					tc->mm_struct = mm_struct_old;
 				return vma;
+			}
 
 			if (DO_REF_SEARCH(ref)) {
 				if (VM_REF_CHECK_HEXVAL(ref, vma) ||
@@ -3726,11 +3796,17 @@ vm_area_dump(ulong task, ulong flag, ulo
 						vm_start, vm_end, vm_mm, ref);
 			}
 
-			if (flag & UVADDR)
+			if (flag & UVADDR) {
+				if (mm_addr)
+					tc->mm_struct = mm_struct_old;
 				return vma;
+			}
 		} 
 	}
 
+	if (mm_addr)
+		tc->mm_struct = mm_struct_old;
+
 	if (flag & VERIFY_ADDR)
 		return (ulong)NULL;
 
@@ -3940,7 +4016,7 @@ in_user_stack(ulong task, ulong vaddr)
 	ulonglong vm_flags;
 	char *vma_buf;
 
-	if ((vma = vm_area_dump(task, UVADDR|VERIFY_ADDR, vaddr, 0))) {
+	if ((vma = vm_area_dump(task, UVADDR|VERIFY_ADDR, vaddr, 0, 0))) {
 		vma_buf = fill_vma_cache(vma);
 		vm_flags = get_vm_flags(vma_buf);
 
Index: task.c
===================================================================
--- task.c.orig
+++ task.c
@@ -5870,19 +5870,19 @@ foreach(struct foreach_data *fd)
 					cmdflags = PRINT_RADIX_10;
 				if (fd->flags & FOREACH_i_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_INODES, 0, NULL);
+					    PRINT_INODES, 0, 0, NULL);
 				else if (fd->flags & FOREACH_p_FLAG)
 					vm_area_dump(tc->task, 
-					    PHYSADDR, 0, 
+					    PHYSADDR, 0, 0,
 					    fd->reference ? ref : NULL);
 				else if (fd->flags & FOREACH_m_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_MM_STRUCT|cmdflags, 0, NULL);
+					    PRINT_MM_STRUCT|cmdflags, 0, 0, NULL);
 				else if (fd->flags & FOREACH_v_FLAG)
 					vm_area_dump(tc->task, 
-					    PRINT_VMA_STRUCTS|cmdflags, 0, NULL);
+					    PRINT_VMA_STRUCTS|cmdflags, 0, 0, NULL);
 				else
-					vm_area_dump(tc->task, 0, 0, 
+					vm_area_dump(tc->task, 0, 0, 0,
 					    fd->reference ? ref : NULL);
 				break;
 
Index: defs.h
===================================================================
--- defs.h.orig
+++ defs.h
@@ -2501,6 +2501,7 @@ struct load_module {
 #define PHYSADDR           (0x4)
 #define XENMACHADDR        (0x8)
 #define FILEADDR          (0x10)
+#define MEMSTRUCTADDR     (0x20)
 #define AMBIGUOUS          (~0)
 
 #define USE_USER_PGD       (UVADDR << 2)
@@ -4449,8 +4450,8 @@ void do_vtop(ulong, struct task_context
 void raw_stack_dump(ulong, ulong);
 void raw_data_dump(ulong, long, int);
 int accessible(ulong);
-ulong vm_area_dump(ulong, ulong, ulong, struct reference *);
-#define IN_TASK_VMA(TASK,VA) (vm_area_dump((TASK), UVADDR|VERIFY_ADDR, (VA), 0))
+ulong vm_area_dump(ulong, ulong, ulong, ulong, struct reference *);
+#define IN_TASK_VMA(TASK,VA) (vm_area_dump((TASK), UVADDR|VERIFY_ADDR, (VA), 0, 0))
 char *fill_vma_cache(ulong);
 void clear_vma_cache(void);
 void dump_vma_cache(ulong);
Index: help.c
===================================================================
--- help.c.orig
+++ help.c
@@ -3490,7 +3490,7 @@ NULL
 char *help_vtop[] = {
 "vtop",
 "virtual to physical",
-"[-c [pid | taskp]] [-u|-k] address ...",
+"[-c [pid | taskp]] [-u|-k] [-M mm_addr] address ...",
 "  This command translates a user or kernel virtual address to its physical",
 "  address.  Also displayed is the PTE translation, the vm_area_struct data",
 "  for user virtual addresses, the mem_map page data associated with the",
@@ -3514,6 +3514,7 @@ char *help_vtop[] = {
 "                      the pid or taskp argument should NOT be entered; the",
 "                      address will be translated using the page directory of",
 "                      each task specified by \"foreach\".",
+"   -M mm_addr         Use mm_struct located at mm_addr.",
 "   address            A hexadecimal user or kernel virtual address.",
 "\nEXAMPLES",
 "  Translate user virtual address 80b4000:\n",
@@ -3595,7 +3596,7 @@ NULL
 char *help_vm[] = { 
 "vm",
 "virtual memory",
-"[-p | -P vmaddr | -v | -m | -x | -d | [-R reference] | [-f vm_flags]]"
+"[-p | -P vmaddr | -v | -m | [-M mm_addr] | -x | -d | [-R reference] | [-f vm_flags]]"
 "\n     [pid | taskp] ... ",
 "  This command displays basic virtual memory information of a context,",
 "  consisting of a pointer to its mm_struct and page dirctory, its RSS and ",
@@ -3616,6 +3617,7 @@ char *help_vm[] = {
 "                specified VM area of a context.",
 "  -R reference  search for references to this number or filename.",
 "            -m  dump the mm_struct assocated with the task.",
+"    -M mm_addr  use mm_struct located at mm_addr.",
 "            -v  dump all of the vm_area_structs associated with the task.",
 "            -x  override the default output format for the -m or -v options",
 "                with hexadecimal format.",
