Subject: IOCTL_PRIVCMD_MMAPBATCH (save/restore, part 3)
To: None <port-xen@NetBSD.org>
From: Jed Davis <jdev@panix.com>
List: port-xen
Date: 09/07/2005 22:53:59
--=-=-=


This ioctl is pretty straightforward to do a basic implementation of;
it takes a virtual address range and a corresponding number of machine
frame numbers and, ideally, sends the MMU operations to the hypervisor
in an efficient manner.

The attached patch is not ideal in that sense; it just iterates over
the array and calls pmap_remap_pages for each page.  (The Linux
implementation, to the extent that I can make sense of it, queues up
the work for efficient dispatch to the hypervisor.)


--=-=-=
Content-Type: text/x-patch
Content-Disposition: inline; filename=xen-privcmd-mmapbatch.patch
Content-Description: Implement IOCTL_PRIVCMD_MMAPBATCH

Index: sys/arch/xen/xen/privcmd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/xen/xen/privcmd.c,v
retrieving revision 1.2.2.2
diff -u -p -r1.2.2.2 privcmd.c
--- sys/arch/xen/xen/privcmd.c	18 Jun 2005 10:43:37 -0000	1.2.2.2
+++ sys/arch/xen/xen/privcmd.c	8 Sep 2005 01:50:15 -0000
@@ -137,10 +168,46 @@ privcmd_ioctl(void *v)
 		break;
 	}
 	case IOCTL_PRIVCMD_MMAPBATCH:
-		/* XXX */
-		printf("IOCTL_PRIVCMD_MMAPBATCH\n");
-		error = EOPNOTSUPP;
+	{
+		int i;
+		privcmd_mmapbatch_t* pmb = ap->a_data;
+		vaddr_t va0, va;
+		u_long mfn, ma;
+		struct vm_map *vmm;
+		pmap_t pmap;
+
+		vmm = &ap->a_p->p_vmspace->vm_map;
+		pmap = vm_map_pmap(vmm);
+		va0 = pmb->addr & ~PAGE_MASK;
+
+		if (va0 > VM_MAXUSER_ADDRESS)
+			return EINVAL;
+		if (((VM_MAXUSER_ADDRESS - va0) >> PGSHIFT) < pmb->num)
+			return EINVAL;
+		
+		//printf("mmapbatch: va0=%lx num=%d dom=%d\n", va0, pmb->num, pmb->dom);
+		for(i = 0; i < pmb->num; ++i) {
+			va = va0 + (i * PAGE_SIZE);
+			error = copyin(&pmb->arr[i], &mfn, sizeof(mfn));
+			if (error != 0)
+				return error;
+			ma = mfn << PGSHIFT;
+			
+			/*
+			 * XXXjld@panix.com: figure out how to stuff
+			 * these into fewer hypercalls.
+			 */
+			//printf("mmapbatch: va=%lx ma=%lx dom=%d\n", va, ma, pmb->dom);
+			error = pmap_remap_pages(pmap, va, ma, 1,
+			    PMAP_WIRED | PMAP_CANFAIL, pmb->dom);
+			if (error != 0) {
+				printf("mmapbatch: remap error %d!\n", error);
+				mfn |= 0xF0000000;
+				copyout(&mfn, &pmb->arr[i], sizeof(mfn));
+			}
+		}
 		break;
+	}
 	case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
 		{
 		unsigned long *mfn_start = ap->a_data;

--=-=-=

-- 
(let ((C call-with-current-continuation)) (apply (lambda (x y) (x y)) (map
((lambda (r) ((C C) (lambda (s) (r (lambda l (apply (s s) l))))))  (lambda
(f) (lambda (l) (if (null? l) C (lambda (k) (display (car l)) ((f (cdr l))
(C k)))))))    '((#\J #\d #\D #\v #\s) (#\e #\space #\a #\i #\newline)))))

--=-=-=--