bitkeeper revision 1.899 (40a1ea3a_7ZmXmUq-RTnUSd3QZ_X1Q)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Wed, 12 May 2004 09:11:22 +0000 (09:11 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Wed, 12 May 2004 09:11:22 +0000 (09:11 +0000)
live migration cleanups

tools/xc/lib/xc_linux_restore.c
tools/xc/lib/xc_linux_save.c
tools/xc/lib/xc_private.c
tools/xc/py/Xc.c
xen/Rules.mk
xen/common/dom0_ops.c
xen/common/kernel.c
xen/common/shadow.c
xen/include/hypervisor-ifs/dom0_ops.h
xen/include/xen/shadow.h

index 9b1532159f546e7bb6d17d6eb0134e319a9f6c3a..1bbc575889f17b7b9a1c93aeff7ec56aef8944b2 100644 (file)
 
 #define MAX_BATCH_SIZE 1024
 
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
+
 /* This may allow us to create a 'quiet' command-line option, if necessary. */
 #define verbose_printf(_f, _a...) \
     do {                          \
@@ -230,7 +239,7 @@ int xc_linux_restore(int xc_handle,
             goto out;
         }
 
-       printf("batch %d\n",j);
+       DPRINTF("batch %d\n",j);
        
        if (j == 0) 
            break;  // our work here is done
@@ -272,11 +281,6 @@ int xc_linux_restore(int xc_handle,
 
            pfn = region_pfn_type[i] & ~PGT_type_mask;
 
-//if(n>=nr_pfns || ((region_pfn_type[i] & PGT_type_mask) == L2TAB) ) printf("pfn=%08lx mfn=%x\n",region_pfn_type[i],pfn_to_mfn_table[pfn]);
-
-                           
-//if(pfn_type[i])printf("^pfn=%d %08lx\n",pfn,pfn_type[i]);
-
             if ((region_pfn_type[i]>>29) == 7)
                continue;
 
@@ -292,8 +296,6 @@ int xc_linux_restore(int xc_handle,
 
            mfn = pfn_to_mfn_table[pfn];
 
-//if(region_pfn_type[i])printf("i=%d pfn=%d mfn=%d type=%lx\n",i,pfn,mfn,region_pfn_type[i]);
-
             ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
 
            if ( (*readerfn)(readerst, ppage, PAGE_SIZE) )
@@ -315,21 +317,12 @@ int xc_linux_restore(int xc_handle,
                    {
                        xpfn = ppage[k] >> PAGE_SHIFT;
 
-/*printf("L1 i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
-       i,pfn,mfn,k,ppage[k],xpfn);*/
-
                        if ( xpfn >= nr_pfns )
                        {
                            ERROR("Frame number in type %d page table is out of range. i=%d k=%d pfn=0x%x nr_pfns=%d",region_pfn_type[i]>>29,i,k,xpfn,nr_pfns);
                            goto out;
                        }
-#if 0
-                       if ( (region_pfn_type[xpfn] != NONE) && (ppage[k] & _PAGE_RW) )
-                       {
-                           ERROR("Write access requested for a restricted frame");
-                           goto out;
-                       }
-#endif
+
                        ppage[k] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
                        ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
                    }
@@ -345,9 +338,6 @@ int xc_linux_restore(int xc_handle,
                    {
                        xpfn = ppage[k] >> PAGE_SHIFT;
 
-/*printf("L2 i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
-       i,pfn,mfn,k,ppage[k],xpfn);*/
-
                        if ( xpfn >= nr_pfns )
                        {
                            ERROR("Frame number in type %d page table is out of range. i=%d k=%d pfn=%d nr_pfns=%d",region_pfn_type[i]>>29,i,k,xpfn,nr_pfns);
@@ -383,7 +373,8 @@ int xc_linux_restore(int xc_handle,
        n+=j; // crude stats
 
     }
-printf("RECEIVED ALL PAGES\n");
+
+    DPRINTF("Received all pages\n");
 
     mfn_mapper_close( region_mapper );
 
@@ -445,8 +436,6 @@ printf("RECEIVED ALL PAGES\n");
     p_srec->resume_info.flags       = 0;
     unmap_pfn(pm_handle, p_srec);
 
-printf("new shared info is %lx\n", shared_info_frame);
-
     /* Uncanonicalise each GDT frame number. */
     if ( ctxt.gdt_ents > 8192 )
     {
@@ -554,9 +543,9 @@ printf("new shared info is %lx\n", shared_info_frame);
     op.u.builddomain.ctxt = &ctxt;
     rc = do_dom0_op(xc_handle, &op);
 
-printf("NORMAL EXIT RESTORE\n");
+    DPRINTF("Everything OK!\n");
+
  out:
-printf("EXIT RESTORE\n");
     if ( mmu != NULL )
         free(mmu);
 
index cbb1d66fd1a7b031ce358e489cdb0a023c07a9ae..37dd7c6fce089eb78618857ec8cde6eb8478ac62 100644 (file)
 
 #define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
 
+#define DEBUG 0
+
+#if DEBUG
+#define DPRINTF(_f, _a...) printf ( _f , ## _a )
+#else
+#define DPRINTF(_f, _a...) ((void)0)
+#endif
+
 /* This may allow us to create a 'quiet' command-line option, if necessary. */
 #define verbose_printf(_f, _a...) \
     do {                          \
@@ -64,7 +72,7 @@ int xc_linux_save(int xc_handle,
     int rc = 1, i, j, k, n, last_iter, iter = 0;
     unsigned long mfn;
     int verbose = flags & XCFLAGS_VERBOSE;
-    int live = 1; //flags & XCFLAGS_LIVE;     // XXXXXXXXXXXXXXXXXXX
+    int live = flags & XCFLAGS_LIVE;
     int sent_last_iter, sent_this_iter, max_iters;
 
     /* Remember if we stopped the guest, so we can restart it on exit. */
@@ -149,15 +157,12 @@ int xc_linux_save(int xc_handle,
        printf("Sleep for 1ms\n");
     }
 
-#if 1
     /* A cheesy test to see whether the domain contains valid state. */
     if ( ctxt.pt_base == 0 )
     {
         ERROR("Domain is not in a valid Linux guest OS state");
         goto out;
     }
-#endif
-
 
     /* Map the suspend-record MFN to pin it. The page must be owned by 
        domid for this to succeed. */
@@ -225,16 +230,23 @@ int xc_linux_save(int xc_handle,
         goto out;
     }
 
-    for(i=0;i<(nr_pfns+1023)/1024 ;i++)
-       printf("LF: %d %x\n",i,live_pfn_to_mfn_frame_list[i]);
 
+    /* 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 < nr_pfns; i += 1024 )
+    {
+        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
+        {
+            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
+            goto out;
+        }
+    }
 
-    /* At this point, we can start the domain again if we're doign a
+    /* At this point, we can start the domain again if we're doing a
        live suspend */
 
     if( live )
     { 
-#if 1
        if ( xc_shadow_control( xc_handle, domid, 
                           DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
                           NULL, 0 ) < 0 )
@@ -242,16 +254,16 @@ int xc_linux_save(int xc_handle,
            ERROR("Couldn't enable shadow mode");
            goto out;
        }
-#endif 
+
        if ( xc_domain_start( xc_handle, domid ) < 0 )
        {
            ERROR("Couldn't restart domain");
            goto out;
        }
-//exit(-1);
+
        last_iter = 0;
        sent_last_iter = 1<<20; // 4GB's worth of pages
-       max_iters = 8; // limit us to 9 time round loop
+       max_iters = 9; // limit us to 10 time round loop
     }
     else
        last_iter = 1;
@@ -297,7 +309,7 @@ int xc_linux_save(int xc_handle,
     /*
      * Quick belt and braces sanity check.
      */
-
+#if DEBUG
     for ( i = 0; i < nr_pfns; i++ )
     {
         mfn = live_pfn_to_mfn_table[i];
@@ -306,17 +318,7 @@ int xc_linux_save(int xc_handle,
            printf("i=0x%x mfn=%x live_mfn_to_pfn_table=%x\n",
                   i,mfn,live_mfn_to_pfn_table[mfn]);
     }
-
-    /* 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 < nr_pfns; i += 1024 )
-    {
-        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
-        {
-            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
-            goto out;
-        }
-    }
+#endif
 
     /* Map the shared info frame */
     live_shinfo = mfn_mapper_map_single(xc_handle, domid,
@@ -374,28 +376,16 @@ int xc_linux_save(int xc_handle,
 
                if( pfn_type[batch] == 0x80000004 )
                {
-                   //printf("Skip netbuf pfn %lx. mfn %lx\n",n,pfn_type[batch]);
+                   DPRINTF("Skip netbuf pfn %lx. mfn %lx\n",n,pfn_type[batch]);
                    continue;
                }
 
-//if(iter>1) printf("pfn=%x mfn=%x\n",n,pfn_type[batch]);
+               if(iter>1) { DPRINTF("pfn=%x mfn=%x\n",n,pfn_type[batch]); }
                
                batch++;
            }
-
-           for( j = 0; j < batch; j++ )
-           {
-
-               if( (pfn_type[j] &0xfffff) == 0x0000004 )
-               {
-                   printf("XXXXXXXXSkip netbuf entry %d mfn %lx\n",j,pfn_type[j]);
-               }
-
-               
-           }
-
            
-           printf("batch %d:%d (n=%d)\n",iter,batch,n);
+           DPRINTF("batch %d:%d (n=%d)\n",iter,batch,n);
 
            if(batch == 0) goto skip; // vanishingly unlikely...
            
@@ -418,10 +408,9 @@ int xc_linux_save(int xc_handle,
            {
                if((pfn_type[j]>>29) == 7)
                {
-                   //printf("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
+                   DPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
                    continue;
                }
-//if((pfn_type[j] & PGT_type_mask) == L2TAB) printf("L2 pfn=%08lx mfn=%lx\n",pfn_type[j],live_mfn_to_pfn_table[pfn_type[j]&~PGT_type_mask]);
                
                /* canonicalise mfn->pfn */
                pfn_type[j] = (pfn_type[j] & PGT_type_mask) |
@@ -448,7 +437,7 @@ int xc_linux_save(int xc_handle,
                
                if((pfn_type[j]>>29) == 7)
                {
-                   //printf("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
+                   DPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
                    continue;
                }
                
@@ -471,26 +460,28 @@ int xc_linux_save(int xc_handle,
 
                        if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
                        {
+                           // I don't think this should ever happen
+
                            printf("FNI %d : [%08lx,%d] pte=%08lx, mfn=%08lx, pfn=%08lx [mfn]=%08lx\n",
                                   j, pfn_type[j], k,
                                   page[k], mfn, live_mfn_to_pfn_table[mfn],
                                   (live_mfn_to_pfn_table[mfn]<nr_pfns)? 
-                               live_pfn_to_mfn_table[live_mfn_to_pfn_table[mfn]]: 0xdeadbeef);
-                           pfn = 0; // be suspicious
+                                  live_pfn_to_mfn_table[live_mfn_to_pfn_table[mfn]]: 0xdeadbeef);
+
+                           pfn = 0; // be suspicious, very suspicious
                            
-//                         ERROR("Frame number in pagetable page is invalid");
-//                         goto out;
+                           //goto out;  // let's try our luck
 
 
                        }
                        page[k] &= PAGE_SIZE - 1;
                        page[k] |= pfn << PAGE_SHIFT;
                        
-                       /*
-                         printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
-                         pfn_type[j]>>29,
-                         j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
-                         */
+#if DEBUG
+                       printf("L%d i=%d pfn=%d mfn=%d k=%d pte=%08lx xpfn=%d\n",
+                              pfn_type[j]>>29,
+                              j,i,mfn,k,page[k],page[k]>>PAGE_SHIFT);
+#endif                   
                        
                    } /* end of page table rewrite for loop */
                    
@@ -526,11 +517,8 @@ int xc_linux_save(int xc_handle,
 
        if ( live )
        {
-           if ( sent_this_iter < (sent_last_iter * 0.95) && iter < max_iters )
-           {
-               // we seem to be doing OK, keep going
-           }
-           else
+           if ( ( sent_this_iter > (sent_last_iter * 0.95) ) ||
+                (iter >= max_iters) || (sent_this_iter < 10) )
            {
                printf("Start last iteration\n");
                last_iter = 1;
@@ -547,17 +535,13 @@ int xc_linux_save(int xc_handle,
                goto out;
            }
 
-#if 0
-           if(last_iter) memset(to_send, 0xff, (nr_pfns+7)/8 );
-#endif
-
            sent_last_iter = sent_this_iter;
        }
 
 
     } /* end of while 1 */
 
-printf("All memory is saved\n");
+    DPRINTF("All memory is saved\n");
 
     /* Success! */
     rc = 0;
@@ -579,14 +563,14 @@ printf("All memory is saved\n");
        PERROR("Could not get info on domain");
        goto out;
     }
-printf("A\n");    
+
     /* Canonicalise the suspend-record frame number. */
     if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
     {
         ERROR("State record is not in range of pseudophys map");
         goto out;
     }
-printf("B\n");    
+
     /* Canonicalise each GDT frame number. */
     for ( i = 0; i < ctxt.gdt_ents; i += 512 )
     {
@@ -596,7 +580,7 @@ printf("B\n");
             goto out;
         }
     }
-printf("C\n");    
+
     /* Canonicalise the page table base pointer. */
     if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
     {
@@ -604,7 +588,7 @@ printf("C\n");
         goto out;
     }
     ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] << PAGE_SHIFT;
-printf("D\n");    
+
     if ( (*writerfn)(writerst, &ctxt,                 sizeof(ctxt)) ||
          (*writerfn)(writerst, live_shinfo,           PAGE_SIZE) )
     {
@@ -612,7 +596,7 @@ printf("D\n");
         goto out;
     }
     munmap(live_shinfo, PAGE_SIZE);
-printf("E\n");        
+
 out:
     /* Restart the domain if we had to stop it to save its state. */
     if ( we_stopped_it )
index 47931f28ec311613792fec4159c4d7050860747a..41eb2e744a1ad03ce4a0882c9f8305bdc0e0d860 100644 (file)
@@ -379,19 +379,24 @@ int finish_mmu_updates(int xc_handle, mmu_t *mmu)
 int xc_domain_stop_sync( int xc_handle, domid_t domid )
 {
     dom0_op_t op;
+    int i;
+    
 
-    while (1)
+    op.cmd = DOM0_STOPDOMAIN;
+    op.u.stopdomain.domain = (domid_t)domid;
+    if ( do_dom0_op(xc_handle, &op) != 0 )
     {
-        op.cmd = DOM0_STOPDOMAIN;
-        op.u.stopdomain.domain = (domid_t)domid;
-        if ( do_dom0_op(xc_handle, &op) != 0 )
-        {
-            PERROR("Stopping target domain failed");
-            goto out;
-        }
+       PERROR("Stopping target domain failed");
+       goto out;
+    }
+
+    usleep(100); // 100us
 
-        usleep(1000); // 1ms
-       printf("Sleep for 1ms\n");
+    for(i=0;;i++)
+    {
+       if (i>0)
+           if (i==1) printf("Sleep.");
+           else printf(".");
 
         op.cmd = DOM0_GETDOMAININFO;
         op.u.getdomaininfo.domain = (domid_t)domid;
@@ -405,10 +410,11 @@ int xc_domain_stop_sync( int xc_handle, domid_t domid )
 
         if ( op.u.getdomaininfo.state == DOMSTATE_STOPPED )
        {
-           printf("Domain %lld stopped\n",domid);
+           printf("\nDomain %lld stopped\n",domid);
             return 0;
        }
-
+       
+       usleep(1000);
     }
 
 out:
index 3b3081e2622e9e52c14f1df8ddd7b554cabdd658..b2ae143edafd7dd95662e4aea03ef83efec90e72 100644 (file)
@@ -191,7 +191,7 @@ static PyObject *pyxc_linux_save(PyObject *self,
 
     u64   dom;
     char *state_file;
-    int   progress = 1, live = 0;
+    int   progress = 1, live = -1;
     unsigned int flags = 0;
 
     static char *kwd_list[] = { "dom", "state_file", "progress", "live", NULL };
@@ -200,8 +200,8 @@ static PyObject *pyxc_linux_save(PyObject *self,
                                       &dom, &state_file, &progress, &live) )
         return NULL;
 
-    if (progress) flags |= XCFLAGS_VERBOSE;
-    if (live)     flags |= XCFLAGS_LIVE;
+    if (progress)  flags |= XCFLAGS_VERBOSE;
+    if (live == 1) flags |= XCFLAGS_LIVE;
 
     if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
     {
@@ -226,6 +226,8 @@ static PyObject *pyxc_linux_save(PyObject *self,
            return 0;
        }
 
+       if (live == -1) flags |= XCFLAGS_LIVE; // default to live for tcp
+
        strncpy( server, state_file+strlen("tcp://"), max_namelen);
        server[max_namelen-1]='\0';
        if ( (port_s = strchr(server,':')) != NULL )
index a9db6358a44aeafcb2523a085e0f8e5a33b6bdf7..e75a79cbe233dc9b4f52817244c94caa37a1bb5c 100644 (file)
@@ -3,6 +3,7 @@ TARGET_ARCH  ?= $(COMPILE_ARCH)
 
 nodev ?= n
 debug ?= n
+trace ?= n
 
 TARGET  := $(BASEDIR)/xen
 HDRS    := $(wildcard $(BASEDIR)/include/xen/*.h)
@@ -50,6 +51,10 @@ ifeq ($(nodev),y)
 CFLAGS += -DNO_DEVICES_IN_XEN
 endif
 
+ifeq ($(trace),y)
+CFLAGS += -DTRACE_BUFFER
+endif
+
 %.o: %.c $(HDRS) Makefile
        $(CC) $(CFLAGS) -c $< -o $@
 
index dee7552bdd1d5a2445f4907e304516cfe34ebe37..f768edd5ffc87a0f9f3ac7742c2607bf7457f063 100644 (file)
 #include <xen/shadow.h>
 #include <hypervisor-ifs/sched_ctl.h>
 
+
+#define TRC_DOM0OP_START_BASE   0x00020000
+#define TRC_DOM0OP_FINISH_BASE  0x00030000
+
+
 extern unsigned int alloc_new_dom_mem(struct task_struct *, unsigned int);
 
 /* Basically used to protect the domain-id space. */
@@ -68,6 +73,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
         return -EACCES;
     }
 
+    TRACE_5D( TRC_DOM0OP_START_BASE + op->cmd, 
+        0, op->u.dummy[0], op->u.dummy[1], op->u.dummy[2], op->u.dummy[3] );
+
     switch ( op->cmd )
     {
 
@@ -671,5 +679,9 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
 
     }
 
+    TRACE_5D( TRC_DOM0OP_FINISH_BASE + op->cmd, ret,
+        op->u.dummy[0], op->u.dummy[1], op->u.dummy[2], op->u.dummy[3]  );
+
+
     return ret;
 }
index 0d5fa023a14d5910ab8d2b6001f1ccd99ac4db98..b33524928d5f15d2f86e1fd1777186e59466dfc4 100644 (file)
@@ -31,6 +31,7 @@
 #include <xen/console.h>
 #include <xen/net_headers.h>
 #include <xen/serial.h>
+#include <xen/shadow.h>
 
 kmem_cache_t *task_struct_cachep;
 
@@ -268,6 +269,8 @@ void cmain(unsigned long magic, multiboot_info_t *mbi)
 
     set_bit(PF_PRIVILEGED, &new_dom->flags);
 
+    shadow_mode_init();
+
     /*
      * We're going to setup domain0 using the module(s) that we stashed safely
      * above our MAX_DIRECTMAP_ADDRESS in boot/boot.S. The second module, if
index fe142e3ee9fbc87f0a7ff7bf9dbf72495f3b9d7e..ec5ce29d5a0db47efeb9c41602ae61d09805b41d 100644 (file)
@@ -6,6 +6,8 @@
 #include <xen/shadow.h>
 #include <asm/domain_page.h>
 #include <asm/page.h>
+#include <xen/event.h>
+#include <xen/trace.h>
 
 
 /********
@@ -26,6 +28,8 @@ hypercall lock anyhow (at least initially).
 
 ********/
 
+static spinlock_t cpu_stall_lock; 
+
 static inline void free_shadow_page( struct mm_struct *m, 
                                      struct pfn_info *pfn_info )
 {
@@ -155,6 +159,11 @@ static void __scan_shadow_table( struct mm_struct *m, unsigned int op )
 }
 
 
+void shadow_mode_init(void)
+{
+    spin_lock_init( &cpu_stall_lock ); 
+}
+
 int shadow_mode_enable( struct task_struct *p, unsigned int mode )
 {
     struct mm_struct *m = &p->mm;
@@ -260,11 +269,11 @@ void shadow_mode_disable( struct task_struct *p )
 }
 
 static int shadow_mode_table_op( struct task_struct *p, 
-                                                                 dom0_shadow_control_t *sc )
+                                dom0_shadow_control_t *sc )
 {
-       unsigned int op = sc->op;
+    unsigned int op = sc->op;
     struct mm_struct *m = &p->mm;
-       int rc = 0;
+    int rc = 0;
 
     // since Dom0 did the hypercall, we should be running with it's page
     // tables right now. Calling flush on yourself would be really
@@ -290,37 +299,50 @@ static int shadow_mode_table_op( struct task_struct *p,
         break;
    
     case DOM0_SHADOW_CONTROL_OP_CLEAN:
+    {
+       int i,j,zero=1;
+               
+       __scan_shadow_table( m, op );
+       
+       if( p->tot_pages > sc->pages || 
+           !sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap )
        {
-               int i;
-
-           __scan_shadow_table( m, op );
-
-           if( p->tot_pages > sc->pages || 
-                       !sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap )
-           {
-                       rc = -EINVAL;
-                       goto out;
-           }
-           
-           sc->pages = p->tot_pages;
-          
+           rc = -EINVAL;
+           goto out;
+       }
+       
+       sc->pages = p->tot_pages;
+       
 #define chunk (8*1024) // do this in 1KB chunks for L1 cache
-
-           for(i=0;i<p->tot_pages;i+=chunk)
+       
+       for(i=0;i<p->tot_pages;i+=chunk)
+       {
+           int bytes = ((  ((p->tot_pages-i) > (chunk))?
+                           (chunk):(p->tot_pages-i) ) + 7) / 8;
+           
+           copy_to_user( sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
+                         p->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
+                         bytes );
+           
+           for(j=0; zero && j<bytes/sizeof(unsigned long);j++)
            {
-                       int bytes = ((  ((p->tot_pages-i) > (chunk))?
-                               (chunk):(p->tot_pages-i) ) + 7) / 8;
-
-                       copy_to_user( sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
-                                                 p->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
-                                                 bytes );
+               if( p->mm.shadow_dirty_bitmap[j] != 0 )
+                   zero = 0;
+           }
 
-                       memset( p->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
-                                  0, bytes);
-               }
+           memset( p->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
+                   0, bytes);
+       }
 
-        break;
+       if (zero)
+       {
+           /* might as well stop the domain as an optimization. */
+           if ( p->state != TASK_STOPPED )
+               send_guest_virq(p, VIRQ_STOP);
        }
+       
+       break;
+    }
     }
 
 
@@ -338,22 +360,45 @@ out:
        return rc;
 }
 
-
 int shadow_mode_control( struct task_struct *p, dom0_shadow_control_t *sc )
 {
-    int  we_paused = 0;
-       unsigned int cmd = sc->op;
-       int rc = 0;
+    unsigned int cmd = sc->op;
+    int rc = 0, cpu;
+
     // don't call if already shadowed...
 
-    // sychronously stop domain
-    if( 0 && !(p->state & TASK_STOPPED) && !(p->state & TASK_PAUSED))
-    {
-        printk("about to pause domain\n");
-        sched_pause_sync(p);
-        printk("paused domain\n");
-        we_paused = 1;
+    /* The following is pretty hideous because we don't have a way of
+       synchronously pausing a domain. If it's assigned to the curernt CPU,
+       we don't have to worry -- it can't possibly actually be running.
+       If its on another CPU, for the moment, we do something really gross:
+       we cause the other CPU to spin regardless of what domain it is running. 
+
+       I know this is really grim, but it only lasts a few 10's of
+       microseconds. It needs fixing as soon as the last of the Linux-isms
+       get removed from the task structure...
+
+       Oh, and let's hope someone doesn't repin the CPU while we're here.
+       Also, prey someone else doesn't do this in another domain.
+       At least there's only one dom0 at the moment...
+     */
+printk("SMC\n");
+    spin_lock( &cpu_stall_lock );              
+    cpu = p->processor;
+printk("got %d %d\n",cpu, current->processor );
+    if ( cpu != current->processor )
+    {
+printk("CPU %d %d\n",cpu, current->processor );
+       static void cpu_stall(void * data)
+       {
+           if ( current->processor == (int) data )
+           {
+               printk("Stall %d\n",(int)data);
+               spin_lock( &cpu_stall_lock );
+               spin_unlock( &cpu_stall_lock );
+           }
+       }
+
+       smp_call_function(cpu_stall, (void*)cpu, 1, 0); // don't wait!
     }
 
     if ( p->mm.shadow_mode && cmd == DOM0_SHADOW_CONTROL_OP_OFF )
@@ -376,11 +421,11 @@ int shadow_mode_control( struct task_struct *p, dom0_shadow_control_t *sc )
     }
     else
     {
-        if ( we_paused ) wake_up(p);
-        return -EINVAL;
+        rc = -EINVAL;
     }
 
-    if ( we_paused ) wake_up(p);
+    spin_unlock( &cpu_stall_lock );
+printk("SMC-\n");
     return rc;
 }
 
index 0027e9df29deba92cd40cdec75514947a0912aa1..879a728bd4a0d7c03f196650f48105eb9ab845c3 100644 (file)
@@ -289,6 +289,7 @@ typedef struct dom0_op_st
     unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
     union
     {
+       unsigned long           dummy[4];
         dom0_createdomain_t     createdomain;
         dom0_startdomain_t      startdomain;
         dom0_stopdomain_t       stopdomain;
index 01b46301aa49b23ee20fde59ac6cf56fcad66265..bfb2a042565f9781d783469cfed7aefe8859bcc7 100644 (file)
@@ -23,6 +23,7 @@
 #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
 #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
 
+extern void shadow_mode_init(void);
 extern int shadow_mode_control( struct task_struct *p, dom0_shadow_control_t *sc );
 extern int shadow_fault( unsigned long va, long error_code );
 extern void shadow_l1_normal_pt_update( unsigned long pa, unsigned long gpte,