bitkeeper revision 1.883 (4094212dXJnedPkykZkVt9oqyUah3w)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 1 May 2004 22:14:05 +0000 (22:14 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 1 May 2004 22:14:05 +0000 (22:14 +0000)
move full execution context out-of-line from dom0_op_t.
further changes to save/restore.

tools/xc/lib/xc_domain.c
tools/xc/lib/xc_linux_build.c
tools/xc/lib/xc_linux_restore.c
tools/xc/lib/xc_linux_save.c
tools/xc/lib/xc_netbsd_build.c
xen/common/dom0_ops.c
xen/common/domain.c
xen/include/hypervisor-ifs/dom0_ops.h

index ec28f2686b44c5288eec8d07b93278c2fd9d1d75..1d77bfc0166bb127fd8274a7ae838321a6dc553b 100644 (file)
@@ -84,6 +84,7 @@ int xc_domain_getinfo(int xc_handle,
     {
         op.cmd = DOM0_GETDOMAININFO;
         op.u.getdomaininfo.domain = (domid_t)next_domid;
+        op.u.getdomaininfo.ctxt = NULL; // no exec context info, thanks.
         if ( do_dom0_op(xc_handle, &op) < 0 )
             break;
         info->domid   = (u64)op.u.getdomaininfo.domain;
index 7f81c924ad3b80de2db73c309f137b28fe293faf..42696666a8c3c021fe9a9cd550a71ab91d68d2ea 100644 (file)
@@ -26,6 +26,7 @@ static long get_tot_pages(int xc_handle, u64 domid)
     dom0_op_t op;
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = NULL;
     return (do_dom0_op(xc_handle, &op) < 0) ? 
         -1 : op.u.getdomaininfo.tot_pages;
 }
@@ -70,7 +71,7 @@ static int setup_guestos(int xc_handle,
                          gzFile initrd_gfd, unsigned long initrd_len,
                          unsigned long nr_pages,
                          unsigned long *pvsi, unsigned long *pvke,
-                         dom0_builddomain_t *builddomain, 
+                        full_execution_context_t *ctxt,
                          const char *cmdline,
                          unsigned long shared_info_frame,
                          unsigned int control_evtchn)
@@ -163,8 +164,6 @@ static int setup_guestos(int xc_handle,
            v_start, v_end);
     printf(" ENTRY ADDRESS: %08lx\n", vkern_entry);
 
-    memset(builddomain, 0, sizeof(*builddomain));
-
     if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
         goto error_out;
 
@@ -205,7 +204,7 @@ static int setup_guestos(int xc_handle,
     /* First allocate page for page dir. */
     ppt_alloc = (vpt_start - v_start) >> PAGE_SHIFT;
     l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
-    builddomain->ctxt.pt_base = l2tab;
+    ctxt->pt_base = l2tab;
 
     /* Initialise the page tables. */
     if ( (vl2tab = map_pfn_writeable(pm_handle, l2tab >> PAGE_SHIFT)) == NULL )
@@ -388,7 +387,7 @@ int xc_linux_build(int xc_handle,
     int initrd_fd = -1;
     gzFile initrd_gfd = NULL;
     int rc, i;
-    full_execution_context_t *ctxt;
+    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
     unsigned long nr_pages;
     char         *image = NULL;
     unsigned long image_size, initrd_size=0;
@@ -420,8 +419,15 @@ int xc_linux_build(int xc_handle,
         }
     }
 
+    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
+    {   
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = ctxt;
     if ( (do_dom0_op(xc_handle, &op) < 0) || 
          ((u64)op.u.getdomaininfo.domain != domid) )
     {
@@ -429,7 +435,7 @@ int xc_linux_build(int xc_handle,
         goto error_out;
     }
     if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
-         (op.u.getdomaininfo.ctxt.pt_base != 0) )
+         (ctxt->pt_base != 0) )
     {
         ERROR("Domain is already constructed");
         goto error_out;
@@ -438,7 +444,7 @@ int xc_linux_build(int xc_handle,
     if ( setup_guestos(xc_handle, domid, image, image_size, 
                        initrd_gfd, initrd_size, nr_pages, 
                        &vstartinfo_start, &vkern_entry,
-                       &launch_op.u.builddomain, cmdline,
+                       ctxt, cmdline,
                        op.u.getdomaininfo.shared_info_frame,
                        control_evtchn) < 0 )
     {
@@ -453,8 +459,6 @@ int xc_linux_build(int xc_handle,
     if ( image != NULL )
         free(image);
 
-    ctxt = &launch_op.u.builddomain.ctxt;
-
     ctxt->flags = 0;
 
     /*
@@ -507,8 +511,11 @@ int xc_linux_build(int xc_handle,
     ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
     ctxt->failsafe_callback_eip = 0;
 
+    memset( &launch_op, 0, sizeof(launch_op) );
+
     launch_op.u.builddomain.domain   = (domid_t)domid;
     launch_op.u.builddomain.num_vifs = 1;
+    launch_op.u.builddomain.ctxt = ctxt;
 
     launch_op.cmd = DOM0_BUILDDOMAIN;
     rc = do_dom0_op(xc_handle, &launch_op);
index 893cd0cef45f02d7892259e1f1657e9ea6b7982f..00acc5a687b6e99a7c7ca29c3d69e47baaf71407 100644 (file)
@@ -58,8 +58,8 @@ int xc_linux_restore(int xc_handle,
                      u64 *pdomid)
 {
     dom0_op_t op;
-    int rc = 1, i, j;
-    unsigned long mfn, pfn;
+    int rc = 1, i, j, n, k;
+    unsigned long mfn, pfn, xpfn;
     unsigned int prev_pc, this_pc;
     
     /* Number of page frames in use by this Linux session. */
@@ -114,6 +114,14 @@ int xc_linux_restore(int xc_handle,
         return 1;
     }
 
+    if ( mlock(&ctxt, sizeof(ctxt) ) )
+    {   
+        /* needed for when we do the build dom0 op, 
+          but might as well do early */
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
     /* Start writing out the saved-domain record. */
     if ( !checked_read(gfd, signature, 16) ||
          (memcmp(signature, "LinuxGuestRecord", 16) != 0) )
@@ -159,12 +167,6 @@ int xc_linux_restore(int xc_handle,
         goto out;
     }
 
-    if ( !checked_read(gfd, pfn_type, 4 * nr_pfns) )
-    {
-        ERROR("Error when reading from state file");
-        goto out;
-    }
-
     /* Set the domain's name to that from the restore file */
     if ( xc_domain_setname( xc_handle, dom, name ) )
     {
@@ -184,6 +186,7 @@ int xc_linux_restore(int xc_handle,
     /* Get the domain's shared-info frame. */
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)dom;
+    op.u.getdomaininfo.ctxt = NULL;
     if ( do_dom0_op(xc_handle, &op) < 0 )
     {
         ERROR("Could not get information on new domain");
@@ -219,73 +222,119 @@ int xc_linux_restore(int xc_handle,
      * We uncanonicalise page tables as we go.
      */
     prev_pc = 0;
-    for ( i = 0; i < nr_pfns; i++ )
+
+    n=0;
+    while(1)
     {
-        this_pc = (i * 100) / nr_pfns;
+       int j;
+       unsigned long region_pfn_type[1024];
+
+        this_pc = (n * 100) / nr_pfns;
         if ( (this_pc - prev_pc) >= 5 )
         {
             verbose_printf("\b\b\b\b%3d%%", this_pc);
             prev_pc = this_pc;
         }
 
-        mfn = pfn_to_mfn_table[i];
-
-        ppage = map_pfn_writeable(pm_handle, mfn);
-
-        if ( !checked_read(gfd, ppage, PAGE_SIZE) )
+        if ( !checked_read(gfd, &j, sizeof(int)) )
         {
             ERROR("Error when reading from state file");
             goto out;
         }
 
-        if ( pfn_type[i] == L1TAB )
-        {
-            for ( j = 0; j < 1024; j++ )
-            {
-                if ( ppage[j] & _PAGE_PRESENT )
-                {
-                    if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns )
-                    {
-                        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) )
-                    {
-                        ERROR("Write access requested for a restricted frame");
-                        goto out;
-                    }
-                    ppage[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
-                    ppage[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-                }
-            }
-        }
-        else if ( pfn_type[i] == L2TAB )
+       printf("batch=%d\n",j);
+       
+       if(j==0) break;  // our work here is done
+       
+        if ( !checked_read(gfd, region_pfn_type, j*sizeof(unsigned long)) )
         {
-            for ( j = 0; j < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); j++ )
-            {
-                if ( ppage[j] & _PAGE_PRESENT )
-                {
-                    if ( (pfn = ppage[j] >> PAGE_SHIFT) >= nr_pfns )
-                    {
-                        ERROR("Frame number in page table is out of range");
-                        goto out;
-                    }
-                    if ( pfn_type[pfn] != L1TAB )
-                    {
-                        ERROR("Page table mistyping");
-                        goto out;
-                    }
-                    ppage[j] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
-                    ppage[j] |= pfn_to_mfn_table[pfn] << PAGE_SHIFT;
-                }
-            }
+            ERROR("Error when reading from state file");
+            goto out;
         }
 
-        unmap_pfn(pm_handle, ppage);
+       for(i=0;i<j;i++)
+       {
+           pfn = region_pfn_type[i] & ~PGT_type_mask;
+                           
+//if(pfn_type[i])printf("^pfn=%d %08lx\n",pfn,pfn_type[i]);
+
+            if (pfn>nr_pfns)
+           {
+               ERROR("pfn out of range");
+               goto out;
+           }
+
+           region_pfn_type[i] &= PGT_type_mask;
+
+           pfn_type[pfn] = region_pfn_type[i];
+
+           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 = map_pfn_writeable(pm_handle, mfn);
+
+           if ( !checked_read(gfd, ppage, PAGE_SIZE) )
+           {
+               ERROR("Error when reading from state file");
+               goto out;
+           }
+
+           if ( region_pfn_type[i] == L1TAB )
+           {
+               for ( k = 0; k < 1024; k++ )
+               {
+                   if ( ppage[k] & _PAGE_PRESENT )
+                   {
+                       if ( (xpfn = ppage[k] >> PAGE_SHIFT) >= 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],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;
+                   }
+               }
+           }
+           else if ( region_pfn_type[i] == L2TAB )
+           {
+               for ( k = 0; k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); k++ )
+               {
+                   if ( ppage[k] & _PAGE_PRESENT )
+                   {
+                       if ( (xpfn = ppage[k] >> PAGE_SHIFT) >= nr_pfns )
+                       {
+                           ERROR("Frame number in page table is out of range");
+                           goto out;
+                       }
+#if 0
+                       if ( region_pfn_type[pfn] != L1TAB )
+                       {
+                           ERROR("Page table mistyping");
+                           goto out;
+                       }
+#endif
+                       ppage[k] &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
+                       ppage[k] |= pfn_to_mfn_table[xpfn] << PAGE_SHIFT;
+                   }
+               }
+           }
+
+           unmap_pfn(pm_handle, ppage);
+
+           if ( add_mmu_update(xc_handle, mmu,
+                               (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) )
+               goto out;
+
+       }
 
-        if ( add_mmu_update(xc_handle, mmu,
-                            (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i) )
-            goto out;
     }
 
     /*
@@ -352,7 +401,9 @@ int xc_linux_restore(int xc_handle,
     pfn = ctxt.pt_base >> PAGE_SHIFT;
     if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
     {
-        ERROR("PT base is bad");
+        printf("PT base is bad. pfn=%d nr=%d type=%08lx %08lx\n",
+              pfn, nr_pfns, pfn_type[pfn], L2TAB);
+        ERROR("PT base is bad.");
         goto out;
     }
     ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
@@ -406,11 +457,11 @@ int xc_linux_restore(int xc_handle,
         ERROR("Bad LDT base or size");
         goto out;
     }
-
+   
     op.cmd = DOM0_BUILDDOMAIN;
     op.u.builddomain.domain   = (domid_t)dom;
     op.u.builddomain.num_vifs = 1;
-    memcpy(&op.u.builddomain.ctxt, &ctxt, sizeof(ctxt));
+    op.u.builddomain.ctxt = &ctxt;
     rc = do_dom0_op(xc_handle, &op);
 
  out:
index fb6fbd6f575d3c4497b3574c4167292740903459..88ed9e15d79641e34354372f842a8b0de9b8ec7a 100644 (file)
@@ -10,7 +10,7 @@
 #include <asm-xen/suspend.h>
 #include <zlib.h>
 
-#define BATCH_SIZE 512   /* 1024 pages (4MB) at a time */
+#define BATCH_SIZE 1024   /* 1024 pages (4MB) at a time */
 
 /* This may allow us to create a 'quiet' command-line option, if necessary. */
 #define verbose_printf(_f, _a...) \
@@ -122,11 +122,18 @@ int xc_linux_save(int xc_handle,
         return 1;
     }
 
+    if ( mlock(&ctxt, sizeof(ctxt) ) )
+    {
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
     /* Ensure that the domain exists, and that it is stopped. */
     for ( ; ; )
     {
         op.cmd = DOM0_GETDOMAININFO;
         op.u.getdomaininfo.domain = (domid_t)domid;
+        op.u.getdomaininfo.ctxt = &ctxt;
         if ( (do_dom0_op(xc_handle, &op) < 0) || 
              ((u64)op.u.getdomaininfo.domain != domid) )
         {
@@ -134,7 +141,6 @@ int xc_linux_save(int xc_handle,
             goto out;
         }
 
-        memcpy(&ctxt, &op.u.getdomaininfo.ctxt, sizeof(ctxt));
         memcpy(name, op.u.getdomaininfo.name, sizeof(name));
         shared_info_frame = op.u.getdomaininfo.shared_info_frame;
 
@@ -223,7 +229,7 @@ int xc_linux_save(int xc_handle,
 
 
     /* We want zeroed memory so use calloc rather than malloc. */
-    pfn_type         = calloc(1, 4 * srec.nr_pfns);
+    pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
 
     if ( (pfn_type == NULL) )
     {
@@ -231,6 +237,11 @@ int xc_linux_save(int xc_handle,
         goto out;
     }
 
+    if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) )
+    {
+       ERROR("Unable to mlock");
+       goto out;
+    }
 
 
     /* Track the mfn_to_pfn table down from the domains PT */
@@ -238,26 +249,22 @@ int xc_linux_save(int xc_handle,
        unsigned long *pgd;
        unsigned long mfn_to_pfn_table_start_mfn;
 
-    pgd = mfn_mapper_map_single(xc_handle, domid, 
+       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 );
+
+       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 );
     }
 
 
     /*
-     * Quick sanity check.
+     * Quick belt and braces sanity check.
      */
 
     for ( i = 0; i < srec.nr_pfns; i++ )
@@ -270,50 +277,6 @@ int xc_linux_save(int xc_handle,
     }
 
 
-/* test new pfn_type stuff */
-    {
-       int n, i, j;
-
-       if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) )
-       {
-           ERROR("Unable to mlock");
-           goto out;
-       }
-       for ( n = 0; n < srec.nr_pfns; )
-       {
-
-           for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
-           {           
-               pfn_type[i] = live_pfn_to_mfn_table[i];
-           }
-
-           if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) )
-           {
-               ERROR("get_pfn_type_batch failed");
-               goto out;
-           }
-
-           for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
-           {
-               
-               pfn_type[i] >>= 29;
-
-               if(pfn_type[i] == 7)
-               {
-                   ERROR("bogus page");
-                   goto out;
-               }
-
-/*             if(pfn_type[i])
-                   printf("i=%d type=%d\n",i,pfn_type[i]);    */
-           }
-
-           n+=j;
-       }
-    }
-
-
-
     /* Canonicalise the suspend-record frame number. */
     if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
     {
@@ -366,8 +329,7 @@ int xc_linux_save(int xc_handle,
          !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
          !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
          !checked_write(gfd, live_shinfo,           PAGE_SIZE) ||
-         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
-         !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
+         !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) )
     {
         ERROR("Error when writing to state file");
         goto out;
@@ -394,6 +356,11 @@ int xc_linux_save(int xc_handle,
             prev_pc = this_pc;
         }
 
+       for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+       {               
+           pfn_type[j] = live_pfn_to_mfn_table[i];
+       }
+
 
        for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
        {
@@ -411,32 +378,54 @@ int xc_linux_save(int xc_handle,
            goto out;
        }
 
-#if 0     
-       typer_handle = get_type_init( xc_handle, BATCH_SIZE )
-
+       if ( get_pfn_type_batch(xc_handle, domid, j, pfn_type) )
+       {
+           ERROR("get_pfn_type_batch failed");
+           goto out;
+       }
+       
        for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
        {
-           /* queue up ownership and type checks for all pages in batch */
+           if((pfn_type[j]>>29) == 7)
+           {
+               ERROR("bogus page");
+               goto out;
+           }
 
-           get_type_queue_entry( typer_handle, domain, 
-                                 pfn_to_mfn_frame_list[i] );
+           /* canonicalise mfn->pfn */
+           pfn_type[j] = (pfn_type[j] & PGT_type_mask) |
+               live_mfn_to_pfn_table[pfn_type[j]&~PGT_type_mask];
+           
+/*         if(pfn_type[j]>>29)
+                   printf("i=%d type=%d\n",i,pfn_type[i]);    */
        }
 
-       region_type = get_type;
 
-#endif
+       if ( !checked_write(gfd, &j, sizeof(int) ) )
+       {
+           ERROR("Error when writing to state file");
+           goto out;
+       }
+
+       if ( !checked_write(gfd, pfn_type, sizeof(unsigned long)*j ) )
+       {
+           ERROR("Error when writing to state file");
+           goto out;
+       }
+
 
        for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
        {
            /* write out pages in batch */
 
-           if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
+           if ( ((pfn_type[j] & PGT_type_mask) == L1TAB) || 
+                ((pfn_type[j] & PGT_type_mask) == L2TAB) )
            {
                
                memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
 
                for ( k = 0; 
-                     k < ((pfn_type[i] == L2TAB) ? 
+                     k < (((pfn_type[j] & PGT_type_mask) == L2TAB) ? 
                           (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
                      k++ )
                {
@@ -478,6 +467,14 @@ int xc_linux_save(int xc_handle,
     /* Success! */
     rc = 0;
 
+    /* Zero terminate */
+    if ( !checked_write(gfd, &rc, sizeof(int)) )
+    {
+       ERROR("Error when writing to state file");
+       goto out;
+    }
+    
+
 out:
     /* Restart the domain if we had to stop it to save its state. */
     if ( we_stopped_it )
index 8793a512f296905584fe342b08e7ac1fc0eb5d8d..7c67d57d71e94dd0ce0097f5256b1ae5025cef5d 100644 (file)
@@ -27,6 +27,7 @@ static long get_tot_pages(int xc_handle, u64 domid)
     dom0_op_t op;
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = NULL;
     return (do_dom0_op(xc_handle, &op) < 0) ? 
         -1 : op.u.getdomaininfo.tot_pages;
 }
@@ -59,7 +60,7 @@ static int setup_guestos(int xc_handle,
                          unsigned long tot_pages,
                          unsigned long *virt_startinfo_addr, 
                          unsigned long *virt_load_addr, 
-                         dom0_builddomain_t *builddomain, 
+                        full_execution_context_t *ctxt,
                          const char *cmdline,
                          unsigned long shared_info_frame,
                          unsigned int control_evtchn)
@@ -78,8 +79,6 @@ static int setup_guestos(int xc_handle,
     mmu_t *mmu = NULL;
     int pm_handle, i;
 
-    memset(builddomain, 0, sizeof(*builddomain));
-
     if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 )
         goto error_out;
 
@@ -119,7 +118,7 @@ static int setup_guestos(int xc_handle,
      */
     l2tab = page_array[alloc_index] << PAGE_SHIFT;
     alloc_index--;
-    builddomain->ctxt.pt_base = l2tab;
+    ctxt->pt_base = l2tab;
     
     if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
         goto error_out;
@@ -221,7 +220,7 @@ int xc_netbsd_build(int xc_handle,
     int kernel_fd = -1;
     gzFile kernel_gfd = NULL;
     int rc, i;
-    full_execution_context_t *ctxt;
+    full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
     unsigned long virt_startinfo_addr;
 
     if ( (tot_pages = get_tot_pages(xc_handle, domid)) < 0 )
@@ -244,8 +243,15 @@ int xc_netbsd_build(int xc_handle,
         return 1;
     }
 
+    if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
+    {   
+        PERROR("Unable to mlock ctxt");
+        return 1;
+    }
+
     op.cmd = DOM0_GETDOMAININFO;
     op.u.getdomaininfo.domain = (domid_t)domid;
+    op.u.getdomaininfo.ctxt = ctxt;
     if ( (do_dom0_op(xc_handle, &op) < 0) || 
          ((u64)op.u.getdomaininfo.domain != domid) )
     {
@@ -253,7 +259,7 @@ int xc_netbsd_build(int xc_handle,
         goto error_out;
     }
     if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
-         (op.u.getdomaininfo.ctxt.pt_base != 0) )
+         (op.u.getdomaininfo.ctxt->pt_base != 0) )
     {
         ERROR("Domain is already constructed");
         goto error_out;
@@ -261,7 +267,7 @@ int xc_netbsd_build(int xc_handle,
 
     if ( setup_guestos(xc_handle, domid, kernel_gfd, tot_pages,
                        &virt_startinfo_addr,
-                       &load_addr, &launch_op.u.builddomain, cmdline,
+                       &load_addr, &st_ctxt, cmdline,
                        op.u.getdomaininfo.shared_info_frame,
                        control_evtchn) < 0 )
     {
@@ -274,8 +280,6 @@ int xc_netbsd_build(int xc_handle,
     if( kernel_gfd )
         gzclose(kernel_gfd);
 
-    ctxt = &launch_op.u.builddomain.ctxt;
-
     ctxt->flags = 0;
 
     /*
@@ -328,9 +332,11 @@ int xc_netbsd_build(int xc_handle,
     ctxt->failsafe_callback_cs  = FLAT_GUESTOS_CS;
     ctxt->failsafe_callback_eip = 0;
 
+    memset( &launch_op, 0, sizeof(launch_op) );
+
     launch_op.u.builddomain.domain   = (domid_t)domid;
     launch_op.u.builddomain.num_vifs = 1;
-
+    launch_op.u.builddomain.ctxt = ctxt;
     launch_op.cmd = DOM0_BUILDDOMAIN;
     rc = do_dom0_op(xc_handle, &launch_op);
     
index ef0ab2e81bbb913594deaef811e5a6be05b83f57..67c26e303a94e5d412c08cd69da8efb51525b616 100644 (file)
@@ -53,24 +53,19 @@ static void read_msr_for(void *unused)
 long do_dom0_op(dom0_op_t *u_dom0_op)
 {
     long ret = 0;
-    dom0_op_t *op;
+    dom0_op_t curop,*op=&curop;
 
     if ( !IS_PRIV(current) )
         return -EPERM;
 
-    if ( (op = kmalloc(sizeof(*op), GFP_KERNEL)) == NULL )
-        return -ENOMEM;
-
     if ( copy_from_user(op, u_dom0_op, sizeof(*op)) )
     {
-        ret = -EFAULT;
-        goto out;
+        return -EFAULT;
     }
 
     if ( op->interface_version != DOM0_INTERFACE_VERSION )
     {
-        ret = -EACCES;
-        goto out;
+        return -EACCES;
     }
 
     switch ( op->cmd )
@@ -269,15 +264,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
         for_each_domain ( p )
         {
             if ( p->domain >= op->u.getdomaininfo.domain )
-                break;
+               break;
         }
 
         if ( p == NULL )
         {
             ret = -ESRCH;
+           goto gdi_out;
         }
         else
         {
+printk("AAAA %p\n",op->u.getdomaininfo.ctxt);
             op->u.getdomaininfo.domain      = p->domain;
             strcpy (op->u.getdomaininfo.name, p->name);
             op->u.getdomaininfo.processor   = p->processor;
@@ -291,59 +288,81 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
             op->u.getdomaininfo.cpu_time    = p->cpu_time;
             op->u.getdomaininfo.shared_info_frame = 
                 __pa(p->shared_info) >> PAGE_SHIFT;
-            if ( p->state == TASK_STOPPED )
+
+            if ( p->state == TASK_STOPPED && op->u.getdomaininfo.ctxt )
             {
+               full_execution_context_t *c=NULL;
+
+               if ( (c = kmalloc(sizeof(*c), GFP_KERNEL)) == NULL )
+               {
+                   ret= -ENOMEM;
+                   goto gdi_out;
+               }
+
                 rmb(); /* Ensure that we see saved register state. */
-                op->u.getdomaininfo.ctxt.flags = 0;
-                memcpy(&op->u.getdomaininfo.ctxt.cpu_ctxt, 
+                c->flags = 0;
+                memcpy(&c->cpu_ctxt, 
                        &p->shared_info->execution_context,
                        sizeof(p->shared_info->execution_context));
                 if ( test_bit(PF_DONEFPUINIT, &p->flags) )
-                    op->u.getdomaininfo.ctxt.flags |= ECF_I387_VALID;
-                memcpy(&op->u.getdomaininfo.ctxt.fpu_ctxt,
+                    c->flags |= ECF_I387_VALID;
+                memcpy(&c->fpu_ctxt,
                        &p->thread.i387,
                        sizeof(p->thread.i387));
-                memcpy(&op->u.getdomaininfo.ctxt.trap_ctxt,
+                memcpy(&c->trap_ctxt,
                        p->thread.traps,
                        sizeof(p->thread.traps));
 #ifdef ARCH_HAS_FAST_TRAP
                 if ( (p->thread.fast_trap_desc.a == 0) &&
                      (p->thread.fast_trap_desc.b == 0) )
-                    op->u.getdomaininfo.ctxt.fast_trap_idx = 0;
+                    c->fast_trap_idx = 0;
                 else
-                    op->u.getdomaininfo.ctxt.fast_trap_idx = 
+                    c->fast_trap_idx = 
                         p->thread.fast_trap_idx;
 #endif
-                op->u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
-                op->u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
-                op->u.getdomaininfo.ctxt.gdt_ents = 0;
+                c->ldt_base = p->mm.ldt_base;
+                c->ldt_ents = p->mm.ldt_ents;
+                c->gdt_ents = 0;
                 if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START )
                 {
                     for ( i = 0; i < 16; i++ )
-                        op->u.getdomaininfo.ctxt.gdt_frames[i] = 
+                        c->gdt_frames[i] = 
                             l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
-                    op->u.getdomaininfo.ctxt.gdt_ents = 
+                    c->gdt_ents = 
                         (GET_GDT_ENTRIES(p) + 1) >> 3;
                 }
-                op->u.getdomaininfo.ctxt.guestos_ss  = p->thread.guestos_ss;
-                op->u.getdomaininfo.ctxt.guestos_esp = p->thread.guestos_sp;
-                op->u.getdomaininfo.ctxt.pt_base   = 
+                c->guestos_ss  = p->thread.guestos_ss;
+                c->guestos_esp = p->thread.guestos_sp;
+                c->pt_base   = 
                     pagetable_val(p->mm.pagetable);
-                memcpy(op->u.getdomaininfo.ctxt.debugreg, 
+                memcpy(c->debugreg, 
                        p->thread.debugreg, 
                        sizeof(p->thread.debugreg));
-                op->u.getdomaininfo.ctxt.event_callback_cs  =
+                c->event_callback_cs  =
                     p->event_selector;
-                op->u.getdomaininfo.ctxt.event_callback_eip =
+                c->event_callback_eip =
                     p->event_address;
-                op->u.getdomaininfo.ctxt.failsafe_callback_cs  = 
+                c->failsafe_callback_cs  = 
                     p->failsafe_selector;
-                op->u.getdomaininfo.ctxt.failsafe_callback_eip = 
+                c->failsafe_callback_eip = 
                     p->failsafe_address;
+
+               if( copy_to_user(op->u.getdomaininfo.ctxt, c, sizeof(*c)) )
+               {
+printk("URGHT %p\n",op->u.getdomaininfo.ctxt);
+                   ret = -EINVAL;
+               }
+
+               if (c) kfree(c);
             }
         }
+
+        if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )            
+           ret = -EINVAL;
+
+    gdi_out:
         read_unlock_irqrestore(&tasklist_lock, flags);
-        copy_to_user(u_dom0_op, op, sizeof(*op));
+
     }
     break;
 
@@ -647,7 +666,5 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
 
     }
 
- out:
-    kfree(op);
     return ret;
 }
index 2b1372a6af13af92900ef62b5a395dd8da6eb1d5..24f15e886ba19bffa001384f7b70499c09dee44c 100644 (file)
@@ -535,45 +535,58 @@ void release_task(struct task_struct *p)
 int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
 {
     unsigned long phys_basetab;
-    int i;
+    int i, rc = 0;
+    full_execution_context_t *c;
+
+    if ( (c = kmalloc(sizeof(*c), GFP_KERNEL)) == NULL )
+       return -ENOMEM;
 
     if ( test_bit(PF_CONSTRUCTED, &p->flags) )
-        return -EINVAL;
+    {
+        rc = -EINVAL;
+       goto out;
+    }
+
+    if ( copy_from_user(c, builddomain->ctxt, sizeof(*c)) )
+    {
+        rc = -EFAULT;
+        goto out;
+    }
     
     clear_bit(PF_DONEFPUINIT, &p->flags);
-    if ( builddomain->ctxt.flags & ECF_I387_VALID )
+    if ( c->flags & ECF_I387_VALID )
         set_bit(PF_DONEFPUINIT, &p->flags);
     memcpy(&p->shared_info->execution_context,
-           &builddomain->ctxt.cpu_ctxt,
+           &c->cpu_ctxt,
            sizeof(p->shared_info->execution_context));
     memcpy(&p->thread.i387,
-           &builddomain->ctxt.fpu_ctxt,
+           &c->fpu_ctxt,
            sizeof(p->thread.i387));
     memcpy(p->thread.traps,
-           &builddomain->ctxt.trap_ctxt,
+           &c->trap_ctxt,
            sizeof(p->thread.traps));
 #ifdef ARCH_HAS_FAST_TRAP
     SET_DEFAULT_FAST_TRAP(&p->thread);
-    (void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx);
+    (void)set_fast_trap(p, c->fast_trap_idx);
 #endif
-    p->mm.ldt_base = builddomain->ctxt.ldt_base;
-    p->mm.ldt_ents = builddomain->ctxt.ldt_ents;
+    p->mm.ldt_base = c->ldt_base;
+    p->mm.ldt_ents = c->ldt_ents;
     SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
     SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
-    if ( builddomain->ctxt.gdt_ents != 0 )
+    if ( c->gdt_ents != 0 )
         (void)set_gdt(p,
-                      builddomain->ctxt.gdt_frames,
-                      builddomain->ctxt.gdt_ents);
-    p->thread.guestos_ss = builddomain->ctxt.guestos_ss;
-    p->thread.guestos_sp = builddomain->ctxt.guestos_esp;
+                      c->gdt_frames,
+                      c->gdt_ents);
+    p->thread.guestos_ss = c->guestos_ss;
+    p->thread.guestos_sp = c->guestos_esp;
     for ( i = 0; i < 8; i++ )
-        (void)set_debugreg(p, i, builddomain->ctxt.debugreg[i]);
-    p->event_selector    = builddomain->ctxt.event_callback_cs;
-    p->event_address     = builddomain->ctxt.event_callback_eip;
-    p->failsafe_selector = builddomain->ctxt.failsafe_callback_cs;
-    p->failsafe_address  = builddomain->ctxt.failsafe_callback_eip;
+        (void)set_debugreg(p, i, c->debugreg[i]);
+    p->event_selector    = c->event_callback_cs;
+    p->event_address     = c->event_callback_eip;
+    p->failsafe_selector = c->failsafe_callback_cs;
+    p->failsafe_address  = c->failsafe_callback_eip;
     
-    phys_basetab = builddomain->ctxt.pt_base;
+    phys_basetab = c->pt_base;
     p->mm.pagetable = mk_pagetable(phys_basetab);
     get_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT], p, 
                       PGT_base_page_table);
@@ -586,8 +599,11 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
         (void)create_net_vif(p->domain);
 
     set_bit(PF_CONSTRUCTED, &p->flags);
+
+out:    
+    if (c) kfree(c);
     
-    return 0;
+    return rc;
 }
 
 static inline int is_loadable_phdr(Elf_Phdr *phdr)
index 3bc18476afe756e11d310e4dbb4624a6a833dfa8..997c5156fb1dae5b79022439006aa89b198f621f 100644 (file)
@@ -80,6 +80,7 @@ typedef struct dom0_getdomaininfo_st
 {
     /* IN variables. */
     domid_t domain;
+    full_execution_context_t *ctxt;
     /* OUT variables. */
     char name[MAX_DOMAIN_NAME];
     int processor;
@@ -91,7 +92,6 @@ typedef struct dom0_getdomaininfo_st
     unsigned int tot_pages, max_pages;
     long long cpu_time;
     unsigned long shared_info_frame;  /* MFN of shared_info struct */
-    full_execution_context_t ctxt;
 } dom0_getdomaininfo_t;
 
 #define DOM0_BUILDDOMAIN      13
@@ -100,7 +100,8 @@ typedef struct dom0_builddomain_st
     /* IN variables. */
     domid_t                  domain;
     unsigned int             num_vifs;
-    full_execution_context_t ctxt;
+    /* IN/OUT parameters */
+    full_execution_context_t *ctxt;
 } dom0_builddomain_t;
 
 #define DOM0_IOPL             14
@@ -152,7 +153,8 @@ typedef struct dom0_getpageframeinfo_st
     domid_t domain;        /* To which domain does the frame belong?    */
     /* OUT variables. */
     /* Is the page PINNED to a type? */
-    enum { NONE, L1TAB, L2TAB, L3TAB, L4TAB } type;
+    enum { NONE, L1TAB=(1<<29), L2TAB=(2<<29), L3TAB=(3<<29), L4TAB=(4<<29) } type;
+#define PGT_type_mask (7<<29)
 } dom0_getpageframeinfo_t;