bitkeeper revision 1.881 (409285285QhBEC23wsKBevdQUow-YA)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Fri, 30 Apr 2004 16:56:08 +0000 (16:56 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Fri, 30 Apr 2004 16:56:08 +0000 (16:56 +0000)
faster suspend

14 files changed:
tools/Makefile
tools/examples/xc_dom_control.py
tools/xc/lib/Makefile
tools/xc/lib/xc_linux_restore.c
tools/xc/lib/xc_linux_save.c
tools/xc/lib/xc_private.c
tools/xc/lib/xc_private.h
xen/common/kernel.c
xen/common/memory.c
xen/include/xen/sched.h
xen/net/dev.c
xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c
xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c
xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h

index 0d4c43fb241afa0c26cf897bd526972c6de7e86d..9ddf5f25a21208151d98f361ad5558a840df1569 100644 (file)
@@ -17,6 +17,10 @@ install: all
        $(MAKE) -C xenctl install
        $(MAKE) -C xend install
 
+dist: $(TARGET)
+       $(MAKE) prefix=`pwd`/../../install dist=yes install
+
+
 clean:
        $(MAKE) -C balloon clean
        $(MAKE) -C xc clean
index ea97a45f0ec5a7e8dc5d500efad45ade80f4bbfc..080af6f366bb2fb46c89bb9d07c326eff9296c90 100755 (executable)
@@ -137,6 +137,7 @@ elif cmd == 'suspend':
         os.kill(pid, signal.SIGTERM)
 
     xc.domain_stop( dom=dom )
+    time.sleep(0.1);
     rc = xc.linux_save( dom=dom, state_file=file, progress=1)
     if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
 
index 79dce046df80cadc7a4c7b4795f95a0ff5101a6d..f542935167e4331c85da0a0d815158757eb1ad2b 100644 (file)
@@ -4,7 +4,7 @@ MINOR    = 0
 SONAME   = libxc.so.$(MAJOR)
 
 CC       = gcc
-CFLAGS   = -c -Wall -O3 -fno-strict-aliasing
+CFLAGS   = -c -Werror -O3 -fno-strict-aliasing
 CFLAGS  += -I../../../xen/include/hypervisor-ifs
 CFLAGS  += -I../../xend/lib
 CFLAGS  += -I../../../xenolinux-sparse/include
index 239df65984ac963615a71cf03a8ef497d8f19787..893cd0cef45f02d7892259e1f1657e9ea6b7982f 100644 (file)
@@ -246,7 +246,7 @@ int xc_linux_restore(int xc_handle,
                 {
                     if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns )
                     {
-                        ERROR("Frame number in page table is out of range");
+                        ERROR("Frame number in type %d page table is out of range. i=%d j=%d pfn=%d nr_pfns=%d",pfn_type[i],i,j,pfn,nr_pfns);
                         goto out;
                     }
                     if ( (pfn_type[pfn] != NONE) && (ppage[j] & _PAGE_RW) )
index e6e8f8864d6b5007fc19b1ec26f1d31167a23c1d..0a367234de943ec273a609983d14641b7afdcf82 100644 (file)
@@ -24,7 +24,7 @@
  */
 #define MFN_IS_IN_PSEUDOPHYS_MAP(_mfn) \
     (((_mfn) < (1024*1024)) &&          \
-     (pfn_to_mfn_table[mfn_to_pfn_table[_mfn]] == (_mfn)))
+     (live_pfn_to_mfn_table[live_mfn_to_pfn_table[_mfn]] == (_mfn)))
 
 /* Returns TRUE if MFN is successfully converted to a PFN. */
 #define translate_mfn_to_pfn(_pmfn)         \
@@ -34,7 +34,7 @@
     if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )   \
         _res = 0;                           \
     else                                    \
-        *(_pmfn) = mfn_to_pfn_table[mfn];   \
+        *(_pmfn) = live_mfn_to_pfn_table[mfn];   \
     _res;                                   \
 })
 
@@ -80,7 +80,7 @@ int xc_linux_save(int xc_handle,
                   int verbose)
 {
     dom0_op_t op;
-    int rc = 1, i, j;
+    int rc = 1, i, j, k, n;
     unsigned long mfn;
     unsigned int prev_pc, this_pc;
 
@@ -103,25 +103,25 @@ int xc_linux_save(int xc_handle,
     unsigned long *pfn_type = NULL;
 
     /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long *ppage, page[1024];
+    unsigned long page[1024];
 
     /* A copy of the pfn-to-mfn table frame list. */
-    unsigned long *pfn_to_mfn_frame_list;
-    /* A live mapping of the pfn-to-mfn table frame list. */
     unsigned long *live_pfn_to_mfn_frame_list;
+    unsigned long pfn_to_mfn_frame_list[1024];
 
-    /* A table translating each PFN to its current MFN. */
-    unsigned long *pfn_to_mfn_table = NULL;
     /* Live mapping of the table mapping each PFN to its current MFN. */
     unsigned long *live_pfn_to_mfn_table = NULL;
-    /* A table translating each current MFN to its canonical PFN. */
-    unsigned long *mfn_to_pfn_table = NULL;
+    /* Live mapping of system MFN to PFN table. */
+    unsigned long *live_mfn_to_pfn_table = NULL;
     
     /* Live mapping of shared info structure */
     unsigned long *live_shinfo;
 
+    /* base of the region in which domain memory is mapped */
+    unsigned char *region_base;
+
     /* A temporary mapping, and a copy, of the guest's suspend record. */
-    suspend_record_t *srec;
+    suspend_record_t *p_srec, srec;
 
     /* The name and descriptor of the file that we are writing to. */
     int    fd;
@@ -187,118 +187,126 @@ int xc_linux_save(int xc_handle,
     }
 
 
-    /* Map the suspend-record MFN to pin it */
-    srec = mfn_mapper_map_single(xc_handle, PROT_READ, 
-                                ctxt.cpu_ctxt.esi, sizeof(*srec));
+    /* Map the suspend-record MFN to pin it. The page must be owned by 
+       domid for this to succeed. */
+    p_srec = mfn_mapper_map_single(xc_handle, domid,
+                                sizeof(srec), PROT_READ, 
+                                ctxt.cpu_ctxt.esi );
 
-    /* Is the suspend-record MFN actually valid for this domain? */
-    if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) )
+    if (!p_srec)
     {
-        ERROR("Invalid state record pointer");
+        ERROR("Couldn't map state record");
         goto out;
     }
 
+    memcpy( &srec, p_srec, sizeof(srec) );
+
     /* cheesy sanity check */
-    if ( srec->nr_pfns > 1024*1024 )
+    if ( srec.nr_pfns > 1024*1024 )
     {
         ERROR("Invalid state record -- pfn count out of range");
         goto out;
     }
 
-    
     /* the pfn_to_mfn_frame_list fits in a single page */
     live_pfn_to_mfn_frame_list = 
-       mfn_mapper_map_single(xc_handle, PROT_WRITE
-                             srec->pfn_to_mfn_frame_list
-                             PAGE_SIZE);
+       mfn_mapper_map_single(xc_handle, domid
+                             PAGE_SIZE, PROT_READ
+                             srec.pfn_to_mfn_frame_list );
 
-    if ( !check_pfn_ownership(xc_handle, 
-                             srec->pfn_to_mfn_frame_list, domid) )
+    if (!live_pfn_to_mfn_frame_list)
     {
-       ERROR("Invalid pfn-to-mfn frame list pointer");
-       goto out;
+        ERROR("Couldn't map pfn_to_mfn_frame_list");
+        goto out;
     }
+   
 
-    memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
-
-    if ( (mapper_handle1 = mfn_mapper_init(xc_handle, 1024*1024, PROT_READ )) 
+    if ( (mapper_handle1 = mfn_mapper_init(xc_handle, domid,
+                                          1024*1024, PROT_READ )) 
         == NULL )
         goto out;
        
-    for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
+    for ( i = 0; i < (srec.nr_pfns+1023)/1024; i++ )
     {
        /* Grab a copy of the pfn-to-mfn table frame list. 
         This has the effect of preventing the page from being freed and
         given to another domain. (though the domain is stopped anyway...) */
        mfn_mapper_queue_entry( mapper_handle1, i<<PAGE_SHIFT, 
-                               pfn_to_mfn_frame_list[i],
+                               live_pfn_to_mfn_frame_list[i],
                                PAGE_SIZE );
     }
     
-    mfn_mapper_flush_queue(mapper_handle1);
-
-    /* Now they're pined, check they're the right dom. We assume
-       they're not going to change, otherwise the suspend is going to fail, 
-       with only itself to blame. */
-
-    for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
+    if ( mfn_mapper_flush_queue(mapper_handle1) )
     {
-       if ( !check_pfn_ownership(xc_handle, 
-                                 pfn_to_mfn_frame_list[i], domid) )
-       {
-           ERROR("Invalid pfn-to-mfn frame list pointer");
-           goto out;
-       }
+        ERROR("Couldn't map pfn_to_mfn table");
+        goto out;
     }
 
     live_pfn_to_mfn_table = mfn_mapper_base( mapper_handle1 );
 
+
+
     /* We want zeroed memory so use calloc rather than malloc. */
-    mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
-    pfn_to_mfn_table = calloc(1, 4 * srec->nr_pfns);
-    pfn_type         = calloc(1, 4 * srec->nr_pfns);
+    pfn_type         = calloc(1, 4 * srec.nr_pfns);
 
-    if ( (mfn_to_pfn_table == NULL) ||
-         (pfn_to_mfn_table == NULL) ||
-         (pfn_type == NULL) )
+    if ( (pfn_type == NULL) )
     {
         errno = ENOMEM;
         goto out;
     }
 
 
+
+    /* Track the mfn_to_pfn table down from the domains PT */
+    {
+       unsigned long *pgd;
+       unsigned long mfn_to_pfn_table_start_mfn;
+
+    pgd = mfn_mapper_map_single(xc_handle, domid, 
+                               PAGE_SIZE, PROT_READ, 
+                               ctxt.pt_base>>PAGE_SHIFT);
+/*
+    printf("pt mfn=%d pfn=%d type=%08x pte=%08x\n",ctxt.pt_base>>PAGE_SHIFT,
+          mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT],
+          pfn_type[mfn_to_pfn_table[ctxt.pt_base>>PAGE_SHIFT]],
+          pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT] );
+*/
+    mfn_to_pfn_table_start_mfn = pgd[HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT]>>PAGE_SHIFT;
+
+    live_mfn_to_pfn_table = 
+       mfn_mapper_map_single(xc_handle, ~0ULL, 
+                             PAGE_SIZE*1024, PROT_READ, 
+                             mfn_to_pfn_table_start_mfn );
+    }
+
+
     /*
      * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
      * loop we have each MFN mapped at most once. Note that there may be MFNs
      * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
      */
 
-    for ( i = 0; i < srec->nr_pfns; i++ )
+    for ( i = 0; i < srec.nr_pfns; i++ )
     {
         mfn = live_pfn_to_mfn_table[i];
 
-        if ( !check_pfn_ownership(xc_handle, mfn, domid) )
-        {
-            ERROR("Invalid frame specified with pfn-to-mfn table");
-            goto out;
-        }
+#if 1  /* XXX use the master mfn_to_pfn table???? */
 
-        /* Did we map this MFN already? That would be invalid! */
-        if ( mfn_to_pfn_table[mfn] )
-        {
-            ERROR("A machine frame appears twice in pseudophys space");
-            goto out;
-        }
 
-        mfn_to_pfn_table[mfn] = i;
-       pfn_to_mfn_table[i] = live_pfn_to_mfn_table[i];
+       if( live_mfn_to_pfn_table[mfn] != i )
+           printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n",
+                  i,mfn,live_mfn_to_pfn_table[mfn]);
 
         /* Query page type by MFN, but store it by PFN. */
         if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == 
              GETPFN_ERR )
             goto out;
+#endif
+
     }
 
+
+
     /* Canonicalise the suspend-record frame number. */
     if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
     {
@@ -322,9 +330,10 @@ int xc_linux_save(int xc_handle,
         ERROR("PT base is not in range of pseudophys map");
         goto out;
     }
-    ctxt.pt_base = mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
+    ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
 
     /* Canonicalise the pfn-to-mfn table frame-number list. */
+    memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
     for ( i = 0; i < srec.nr_pfns; i += 1024 )
     {
         if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
@@ -335,8 +344,15 @@ int xc_linux_save(int xc_handle,
     }
 
     /* Start writing out the saved-domain record. */
-    live_shinfo = mfn_mapper_map_single(xc_handle, PROT_READ,
-                                 shared_info_frame, PAGE_SIZE);
+    live_shinfo = mfn_mapper_map_single(xc_handle, domid,
+                                       PAGE_SIZE, PROT_READ,
+                                       shared_info_frame);
+
+    if (!live_shinfo)
+    {
+        ERROR("Couldn't map live_shinfo");
+        goto out;
+    }
 
     /* Belts and braces safety check on the shared info record */
     if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
@@ -360,7 +376,9 @@ int xc_linux_save(int xc_handle,
 
     verbose_printf("Saving memory pages:   0%%");
 
-    if ( (mapper_handle2 = mfn_mapper_init(xc_handle, 
+#define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
+
+    if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid,
                                           BATCH_SIZE*4096, PROT_READ )) 
         == NULL )
         goto out;
@@ -383,12 +401,19 @@ int xc_linux_save(int xc_handle,
        {
            /* queue up mappings for all of the pages in this batch */
 
+//printf("region n=%d j=%d i=%d mfn=%d\n",n,j,i,live_pfn_to_mfn_table[i]);
            mfn_mapper_queue_entry( mapper_handle2, j<<PAGE_SHIFT, 
-                                   pfn_to_mfn_frame_list[i],
+                                   live_pfn_to_mfn_table[i],
                                    PAGE_SIZE );
        }
-       mfn_mapper_flush_queue(mapper_handle2);
-          
+
+       if( mfn_mapper_flush_queue(mapper_handle2) )
+       {
+           ERROR("Couldn't map page region");
+           goto out;
+       }
+
+#if 0     
        typer_handle = get_type_init( xc_handle, BATCH_SIZE )
 
        for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
@@ -399,42 +424,51 @@ int xc_linux_save(int xc_handle,
                                  pfn_to_mfn_frame_list[i] );
        }
 
-
        region_type = get_type;
 
+#endif
+
        for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
        {
            /* write out pages in batch */
 
-           mfn = pfn_to_mfn_table[i];
-
-           ppage = map_pfn_readonly(pm_handle, mfn);
-           memcpy(page, ppage, PAGE_SIZE);
-           unmap_pfn(pm_handle, ppage);
-
            if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
            {
-               for ( j = 0; 
-                     j < ((pfn_type[i] == L2TAB) ? 
+               
+               memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
+
+               for ( k = 0; 
+                     k < ((pfn_type[i] == L2TAB) ? 
                           (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
-                     j++ )
+                     k++ )
                {
-                   if ( !(page[j] & _PAGE_PRESENT) ) continue;
-                   mfn = page[j] >> PAGE_SHIFT;
+                   if ( !(page[k] & _PAGE_PRESENT) ) continue;
+                   mfn = page[k] >> PAGE_SHIFT;
                    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
                    {
                        ERROR("Frame number in pagetable page is invalid");
                        goto out;
                    }
-                   page[j] &= PAGE_SIZE - 1;
-                   page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
+                   page[k] &= PAGE_SIZE - 1;
+                   page[k] |= live_mfn_to_pfn_table[mfn] << PAGE_SHIFT;
+
+               }
+
+               if ( !checked_write(gfd, page, PAGE_SIZE) )
+               {
+                   ERROR("Error when writing to state file");
+                   goto out;
                }
-           }
 
-           if ( !checked_write(gfd, page, PAGE_SIZE) )
+
+           }
+           else
            {
-               ERROR("Error when writing to state file");
-               goto out;
+               if ( !checked_write(gfd, region_base + (PAGE_SIZE*j), PAGE_SIZE) )
+               {
+                   ERROR("Error when writing to state file");
+                   goto out;
+               }
            }
        }
        
@@ -450,6 +484,7 @@ out:
     /* Restart the domain if we had to stop it to save its state. */
     if ( we_stopped_it )
     {
+       printf("Restart domain\n");
         op.cmd = DOM0_STARTDOMAIN;
         op.u.startdomain.domain = (domid_t)domid;
         (void)do_dom0_op(xc_handle, &op);
@@ -457,13 +492,6 @@ out:
 
     gzclose(gfd);
 
-    if ( pm_handle >= 0 )
-        (void)close_pfn_mapper(pm_handle);
-
-    if ( pfn_to_mfn_table != NULL )
-        free(pfn_to_mfn_table);
-    if ( mfn_to_pfn_table != NULL )
-        free(mfn_to_pfn_table);
     if ( pfn_type != NULL )
         free(pfn_type);
 
index 796da64ad7f89eddc29f05bf025f9c24a7de2857..0c9092b607f295360c5351e86355fe363bdb7bc0 100644 (file)
@@ -47,8 +47,9 @@ void unmap_pfn(int pm_handle, void *vaddr)
 
 /*******************/
 
-void * mfn_mapper_map_single(int xc_handle, int prot, 
-                            unsigned long mfn, int size)
+void * mfn_mapper_map_single(int xc_handle, domid_t dom,
+                            int size, int prot,
+                            unsigned long mfn )
 {
     privcmd_mmap_t ioctlx; 
     privcmd_mmap_entry_t entry; 
@@ -57,6 +58,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot,
     if (addr)
     {
        ioctlx.num=1;
+       ioctlx.dom=dom;
        ioctlx.entry=&entry;
        entry.va=(unsigned long) addr;
        entry.mfn=mfn;
@@ -67,7 +69,7 @@ void * mfn_mapper_map_single(int xc_handle, int prot,
     return addr;
 }
 
-mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
+mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot)
 {
     mfn_mapper_t * t;
     t = calloc( 1, sizeof(mfn_mapper_t)+
@@ -76,6 +78,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
     t->xc_handle = xc_handle;
     t->size = size;
     t->prot = prot;
+    t->error = 0;
     t->max_queue_size = mfn_mapper_queue_size;
     t->addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
     if (!t->addr)
@@ -84,6 +87,7 @@ mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
        return NULL;
     }
     t->ioctl.num = 0;
+    t->ioctl.dom = dom;
     t->ioctl.entry = (privcmd_mmap_entry_t *) &t[1];
     return t;
 }
@@ -99,14 +103,29 @@ void mfn_mapper_close(mfn_mapper_t *t)
     free(t);    
 }
 
+static int __mfn_mapper_flush_queue(mfn_mapper_t *t)
+{
+    int rc;
+    rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl );
+    t->ioctl.num = 0;    
+    if(rc && !t->error) 
+       t->error = rc;
+    return rc;
+}
+
 int mfn_mapper_flush_queue(mfn_mapper_t *t)
 {
     int rc;
+    
+    rc = __mfn_mapper_flush_queue(t);
 
-    rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl );
-    if (rc<0) return rc;
-    t->ioctl.num = 0;
-    return 0;
+    if ( t->error )
+    {
+       rc = t->error;
+    }
+
+    t->error = 0;
+    return rc;
 }
 
 void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
@@ -123,30 +142,113 @@ void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
     {
        prev = &t->ioctl.entry[t->ioctl.num-1];       
 
-       if ( (prev->va+(prev->npages*PAGE_SIZE)) == (t->addr+offset) &&
+       if ( (prev->va+(prev->npages*PAGE_SIZE)) == 
+            ((unsigned long)t->addr+offset) &&
             (prev->mfn+prev->npages) == mfn )
        {
            prev->npages += pages;
-printf("merge\n");
            return t->addr+offset;
        }
     }
      
-    entry->va = t->addr+offset;
+    entry->va = (unsigned long)t->addr+offset;
     entry->mfn = mfn;
     entry->npages = pages;
     t->ioctl.num++;       
 
     if(t->ioctl.num == t->max_queue_size)
     {
-       if ( mfn_mapper_flush_queue(t) )
-       return 0;
+       if ( __mfn_mapper_flush_queue(t) )
+           return 0;
     }
 
     return t->addr+offset;
 }
 
 
+/*******************/
+
+typedef struct dom0_op_compact_getpageframeinfo {
+    unsigned long cmd;
+    unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
+    dom0_getpageframeinfo_t getpageframeinfo;
+}  dom0_op_compact_getpageframeinfo_t;
+
+
+typedef struct mfn_typer {
+    domid_t dom;
+    int max;
+    int nr_multicall_ents;
+    multicall_entry_t *multicall_list;
+    dom0_op_compact_getpageframeinfo_t *gpf_list;
+} mfn_typer_t;
+
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
+
+int mfn_typer_flush_queue(mfn_typer_t *t);
+
+unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx);
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
+{
+    mfn_typer_t *t;
+    multicall_entry_t *m;
+    dom0_op_compact_getpageframeinfo_t *d;
+
+    t = calloc(1, sizeof(mfn_typer_t) );
+    m = calloc(1, sizeof(multicall_entry_t)*num );
+    d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num );
+
+    if (!t || !m || !d)
+    {
+       if(t) free(t);  
+       if(m) free(m);
+       if(d) free(d);
+       return NULL;
+    }
+
+    t->max = num;
+    t->nr_multicall_ents=0;
+    t->multicall_list=m;
+    t->gpf_list=d;
+    t->dom = dom;
+
+    return t;
+}
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn )
+{
+    int i = t->nr_multicall_ents;
+    multicall_entry_t *m = &t->multicall_list[i];
+    dom0_op_compact_getpageframeinfo_t *d = &t->gpf_list[i];
+
+    d->cmd = DOM0_GETPAGEFRAMEINFO;
+    d->interface_version = DOM0_INTERFACE_VERSION;
+    d->getpageframeinfo.pfn = mfn;
+    d->getpageframeinfo.domain = t->dom;
+    d->getpageframeinfo.type = ~0UL;
+      
+    m->op = __HYPERVISOR_dom0_op;
+    m->args[0] = (unsigned long)d;
+   
+    t->nr_multicall_ents++;
+}
+
+int mfn_typer_flush_queue(mfn_typer_t *t)
+{
+    if (t->nr_multicall_ents == 0) return 0;
+    (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents);
+    t->nr_multicall_ents = 0;
+}
+
+unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx)
+{
+    return t->gpf_list[idx].getpageframeinfo.type;
+}
+
 
 
 /*******************/
index d173e58e465f8f846c2ee1bc9dced4ca109ba826..198c703eaf4c58154ab8afe9cdcefb22bbb06efe 100644 (file)
@@ -16,8 +16,6 @@
 
 #include "xc.h"
 
-#include <asm-xen/proc_cmd.h>
-
 /* from xen/include/hypervisor-ifs */
 #include <hypervisor-if.h>
 #include <dom0_ops.h>
 #include <event_channel.h>
 #include <sched_ctl.h>
 
+#include <asm-xen/proc_cmd.h>
+
+
+
 /* from xend/lib */
 #include <domain_controller.h>
 
@@ -188,6 +190,7 @@ typedef struct privcmd_mmap_entry {
 
 typedef struct privcmd_mmap {
     int num;
+    domid_t dom;
     privcmd_mmap_entry_t *entry;
 } privcmd_mmap_t; 
 */
@@ -198,16 +201,17 @@ typedef struct mfn_mapper {
     int xc_handle;
     int size;
     int prot;
+    int error;
     int max_queue_size;
     void * addr;
     privcmd_mmap_t ioctl; 
     
 } mfn_mapper_t;
 
-void * mfn_mapper_map_single(int xc_handle, int prot, 
-                            unsigned long mfn, int size);
+void * mfn_mapper_map_single(int xc_handle, domid_t dom, int size, int prot, 
+                            unsigned long mfn );
 
-mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot);
+mfn_mapper_t * mfn_mapper_init(int xc_handle, domid_t dom, int size, int prot);
 
 void * mfn_mapper_base(mfn_mapper_t *t);
 
index 3c10cf3ca2f8b68df64583a40e76a56ce582c6cc..d8d5d0325164efd8c790741b5d31886d446b9601 100644 (file)
@@ -255,6 +255,9 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
 
     start_of_day();
 
+    /* Add CPU0 idle task to the task hash list */
+    task_hash[TASK_HASH(IDLE_DOMAIN_ID)] = &idle0_task;
+
     /* Create initial domain 0. */
     dom0_params.memory_kb = opt_dom0_mem;
     new_dom = do_createdomain(0, 0);
index 1ffc207bdfe43af27ff043f72953ba08970ca80a..ed2e5b6e170df202f7ae34f92e4bdfade17d77df 100644 (file)
@@ -194,6 +194,9 @@ static struct {
  */
 void __init init_frametable(unsigned long nr_pages)
 {
+    int i;
+    unsigned long mfn;
+
     memset(percpu_info, 0, sizeof(percpu_info));
 
     max_page = nr_pages;
@@ -206,8 +209,20 @@ void __init init_frametable(unsigned long nr_pages)
     INIT_LIST_HEAD(&free_list);    
     free_pfns = 0;
 
+    /* so that we can map them latter, set the ownership of pages
+       belonging to the machine_to_phys_mapping to CPU0 idle task */
+    
+    mfn = virt_to_phys((void *)RDWR_MPT_VIRT_START)>>PAGE_SHIFT;
+//    for(i=0;i<nr_pages;i+=1024,mfn++)
+    for(i=0;i<1024*1024;i+=1024,mfn++)
+    {
+       frame_table[mfn].count_and_flags = 1 | PGC_allocated;
+       frame_table[mfn].type_and_flags = 1 | PGT_gdt_page; // anything non RW
+       frame_table[mfn].u.domain = &idle0_task;
+    }
 }
 
+
 void add_to_domain_alloc_list(unsigned long ps, unsigned long pe)
 {
     struct pfn_info *pf;
@@ -895,7 +910,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
         break;
 
     case MMUEXT_SET_SUBJECTDOM_H:
-        percpu_info[cpu].subject_id |= (domid_t)((ptr&~0xFFFF)|(val>>16))<<32;
+        percpu_info[cpu].subject_id |= ((domid_t)((ptr&~0xFFFF)|(val>>16)))<<32;
+
         if ( !IS_PRIV(current) )
         {
             MEM_LOG("Dom %llu has no privilege to set subject domain",
index 14f4019ac1a9223a2086b42bedf9dee5f26e4ab7..c9b072aaa03e9cd4191d1a5c335621636d62587d 100644 (file)
@@ -209,7 +209,8 @@ struct task_struct
     mm:          IDLE0_MM,       \
     addr_limit:  KERNEL_DS,      \
     thread:      INIT_THREAD,    \
-    flags:       1<<PF_IDLETASK  \
+    flags:       1<<PF_IDLETASK, \
+    refcnt:      ATOMIC_INIT(1)  \
 }
 
 extern struct task_struct idle0_task;
index e4e10928407dd5d60cbeb99d2a3fdd07e62a9381..5ab01092f0e726218a8eb33ea8a07286f98f6fd1 100644 (file)
@@ -2156,8 +2156,9 @@ static void get_rx_bufs(net_vif_t *vif)
                               0) != 
                       (PGC_allocated | PGC_tlb_flush_on_type_change | 2)) )
         {
-            DPRINTK("Page held more than once %08x\n", 
-                    buf_page->count_and_flags);
+            DPRINTK("Page held more than once %08x %s\n", 
+                    buf_page->count_and_flags,
+                   (buf_page->u.domain)?buf_page->u.domain->name:"None");
             if ( !get_page_type(buf_page, PGT_writeable_page) )
                 put_page(buf_page);
             else if ( cmpxchg(ptep, pte & ~_PAGE_PRESENT, pte) !=
index a94b016fb7b0eaae10b7e993335051e258487ec8..4e507081beac8e5ed25bc4882b901dcbe8396aae 100644 (file)
@@ -67,7 +67,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
 #define PRIVCMD_MMAP_SZ 32
        privcmd_mmap_t mmapcmd;
        privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
-       int i;
+       int i, rc;
 
         if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
             return -EFAULT;
@@ -95,12 +95,13 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
                if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end)
                    return -EINVAL;
 
-               if (direct_remap_area_pages(vma->vm_mm, 
+               if (rc = direct_remap_area_pages(vma->vm_mm, 
                                            msg[j].va&PAGE_MASK, 
                                            msg[j].mfn<<PAGE_SHIFT, 
                                            msg[j].npages<<PAGE_SHIFT, 
-                                           vma->vm_page_prot))
-                   return -EINVAL;
+                                           vma->vm_page_prot,
+                                           mmapcmd.dom))
+                   return rc;
            }
        }
        ret = 0;
index 6474d4c6ed3de7ed480776a32d5512028149f9cb..7b4d1ff0a94284f178889466afc0da24bddfad06 100644 (file)
@@ -27,7 +27,7 @@
 #define direct_mk_pte_phys(physpage, pgprot) \
   __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
 
-static inline void direct_remap_area_pte(pte_t *pte, 
+static inline int direct_remap_area_pte(pte_t *pte, 
                                          unsigned long address, 
                                          unsigned long size,
                                          unsigned long machine_addr, 
@@ -39,6 +39,9 @@ static inline void direct_remap_area_pte(pte_t *pte,
     mmu_update_t *u, *v;
     u = v = vmalloc(3*PAGE_SIZE); /* plenty */
 
+    if (!u) 
+       return -ENOMEM;
+
     /* If not I/O mapping then specify General-Purpose Subject Domain (GPS). */
     if ( domid != 0 )
     {
@@ -74,10 +77,15 @@ static inline void direct_remap_area_pte(pte_t *pte,
         pte++;
     } while (address && (address < end));
 
-    if ( ((v-u) != 0) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
+    if ( ((v-u) > 2) && (HYPERVISOR_mmu_update(u, v-u) < 0) )
+    {
         printk(KERN_WARNING "Failed to ioremap %08lx->%08lx (%08lx)\n",
                end-size, end, machine_addr-size);
+       return -EINVAL;
+    }
+
     vfree(u);
+    return 0;
 }
 
 static inline int direct_remap_area_pmd(struct mm_struct *mm,
@@ -89,6 +97,7 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm,
                                         domid_t  domid)
 {
     unsigned long end;
+    int rc;
 
     address &= ~PGDIR_MASK;
     end = address + size;
@@ -101,8 +110,11 @@ static inline int direct_remap_area_pmd(struct mm_struct *mm,
         pte_t * pte = pte_alloc(mm, pmd, address);
         if (!pte)
             return -ENOMEM;
-        direct_remap_area_pte(pte, address, end - address, 
-                              address + machine_addr, prot, domid);
+
+        if ( rc = direct_remap_area_pte(pte, address, end - address, 
+                              address + machine_addr, prot, domid) )
+           return rc;
+
         address = (address + PMD_SIZE) & PMD_MASK;
         pmd++;
     } while (address && (address < end));
@@ -120,8 +132,8 @@ int direct_remap_area_pages(struct mm_struct *mm,
     pgd_t * dir;
     unsigned long end = address + size;
 
-printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
-       address, machine_addr, size);
+/*printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
+       address, machine_addr, size);*/
 
     machine_addr -= address;
     dir = pgd_offset(mm, address);
index 205355fa9c40749ae581363e90a6cace6bef4d84..30cec9aff539c69d72047a84043afa85ca1dcb52 100644 (file)
@@ -21,6 +21,7 @@ typedef struct privcmd_mmap_entry {
 
 typedef struct privcmd_mmap {
     int num;
+    domid_t dom; /* target domain */
     privcmd_mmap_entry_t *entry;
 } privcmd_mmap_t;