Port-xen archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

IOCTL_PRIVCMD_MMAPBATCH (save/restore, part 3)



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

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@localhost: 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)))))


Home | Main Index | Thread Index | Old Index