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)))))
--=-=-=--