ia64/xen-unstable

changeset 1323:d41f26deb150

bitkeeper revision 1.880 (408e873bJZUD6CJ5wPeA5HUnW78lhQ)

Merge
author iap10@labyrinth.cl.cam.ac.uk
date Tue Apr 27 16:15:55 2004 +0000 (2004-04-27)
parents 112eec3395e6 1983d16b31c5
children 80919e3d24af
files tools/xc/lib/xc_linux_save.c tools/xc/lib/xc_private.c tools/xc/lib/xc_private.h xen/common/memory.c 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
line diff
     1.1 --- a/tools/xc/lib/xc_linux_save.c	Tue Apr 27 13:13:06 2004 +0000
     1.2 +++ b/tools/xc/lib/xc_linux_save.c	Tue Apr 27 16:15:55 2004 +0000
     1.3 @@ -84,6 +84,9 @@ int xc_linux_save(int xc_handle,
     1.4      unsigned long mfn;
     1.5      unsigned int prev_pc, this_pc;
     1.6  
     1.7 +    /* state of the new MFN mapper */
     1.8 +    mfn_mapper_t *mapper_handle1, *mapper_handle2;
     1.9 +
    1.10      /* Remember if we stopped the guest, so we can restart it on exit. */
    1.11      int we_stopped_it = 0;
    1.12  
    1.13 @@ -102,18 +105,23 @@ int xc_linux_save(int xc_handle,
    1.14      /* A temporary mapping, and a copy, of one frame of guest memory. */
    1.15      unsigned long *ppage, page[1024];
    1.16  
    1.17 -    /* A temporary mapping, and a copy, of the pfn-to-mfn table frame list. */
    1.18 -    unsigned long *p_pfn_to_mfn_frame_list, pfn_to_mfn_frame_list[1024];
    1.19 -    /* A temporary mapping of one frame in the above list. */
    1.20 -    unsigned long *pfn_to_mfn_frame;
    1.21 +    /* A copy of the pfn-to-mfn table frame list. */
    1.22 +    unsigned long *pfn_to_mfn_frame_list;
    1.23 +    /* A live mapping of the pfn-to-mfn table frame list. */
    1.24 +    unsigned long *live_pfn_to_mfn_frame_list;
    1.25  
    1.26 -    /* A table mapping each PFN to its current MFN. */
    1.27 +    /* A table translating each PFN to its current MFN. */
    1.28      unsigned long *pfn_to_mfn_table = NULL;
    1.29 -    /* A table mapping each current MFN to its canonical PFN. */
    1.30 +    /* Live mapping of the table mapping each PFN to its current MFN. */
    1.31 +    unsigned long *live_pfn_to_mfn_table = NULL;
    1.32 +    /* A table translating each current MFN to its canonical PFN. */
    1.33      unsigned long *mfn_to_pfn_table = NULL;
    1.34      
    1.35 +    /* Live mapping of shared info structure */
    1.36 +    unsigned long *live_shinfo;
    1.37 +
    1.38      /* A temporary mapping, and a copy, of the guest's suspend record. */
    1.39 -    suspend_record_t *p_srec, srec;
    1.40 +    suspend_record_t *srec;
    1.41  
    1.42      /* The name and descriptor of the file that we are writing to. */
    1.43      int    fd;
    1.44 @@ -178,8 +186,10 @@ int xc_linux_save(int xc_handle,
    1.45          goto out;
    1.46      }
    1.47  
    1.48 -    if ( (pm_handle = init_pfn_mapper((domid_t)domid)) < 0 )
    1.49 -        goto out;
    1.50 +
    1.51 +    /* Map the suspend-record MFN to pin it */
    1.52 +    srec = mfn_mapper_map_single(xc_handle, PROT_READ, 
    1.53 +				 ctxt.cpu_ctxt.esi, sizeof(*srec));
    1.54  
    1.55      /* Is the suspend-record MFN actually valid for this domain? */
    1.56      if ( !check_pfn_ownership(xc_handle, ctxt.cpu_ctxt.esi, domid) )
    1.57 @@ -188,33 +198,65 @@ int xc_linux_save(int xc_handle,
    1.58          goto out;
    1.59      }
    1.60  
    1.61 -    /* If the suspend-record MFN is okay then grab a copy of it to @srec. */
    1.62 -    p_srec = map_pfn_readonly(pm_handle, ctxt.cpu_ctxt.esi);
    1.63 -    memcpy(&srec, p_srec, sizeof(srec));
    1.64 -    unmap_pfn(pm_handle, p_srec);
    1.65 -
    1.66 -    if ( srec.nr_pfns > 1024*1024 )
    1.67 +    /* cheesy sanity check */
    1.68 +    if ( srec->nr_pfns > 1024*1024 )
    1.69      {
    1.70          ERROR("Invalid state record -- pfn count out of range");
    1.71          goto out;
    1.72      }
    1.73  
    1.74 -    if ( !check_pfn_ownership(xc_handle, srec.pfn_to_mfn_frame_list, domid) )
    1.75 +    
    1.76 +    /* the pfn_to_mfn_frame_list fits in a single page */
    1.77 +    live_pfn_to_mfn_frame_list = 
    1.78 +	mfn_mapper_map_single(xc_handle, PROT_WRITE, 
    1.79 +			      srec->pfn_to_mfn_frame_list, 
    1.80 +			      PAGE_SIZE);
    1.81 +
    1.82 +    if ( !check_pfn_ownership(xc_handle, 
    1.83 +			      srec->pfn_to_mfn_frame_list, domid) )
    1.84      {
    1.85 -        ERROR("Invalid pfn-to-mfn frame list pointer");
    1.86 -        goto out;
    1.87 +	ERROR("Invalid pfn-to-mfn frame list pointer");
    1.88 +	goto out;
    1.89      }
    1.90  
    1.91 -    /* Grab a copy of the pfn-to-mfn table frame list. */
    1.92 -    p_pfn_to_mfn_frame_list = map_pfn_readonly(
    1.93 -        pm_handle, srec.pfn_to_mfn_frame_list);
    1.94 -    memcpy(pfn_to_mfn_frame_list, p_pfn_to_mfn_frame_list, PAGE_SIZE);
    1.95 -    unmap_pfn(pm_handle, p_pfn_to_mfn_frame_list);
    1.96 +    memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
    1.97 +
    1.98 +    if ( (mapper_handle1 = mfn_mapper_init(xc_handle, 1024*1024, PROT_READ )) 
    1.99 +	 == NULL )
   1.100 +        goto out;
   1.101 +	
   1.102 +    for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
   1.103 +    {
   1.104 +	/* Grab a copy of the pfn-to-mfn table frame list. 
   1.105 +	 This has the effect of preventing the page from being freed and
   1.106 +	 given to another domain. (though the domain is stopped anyway...) */
   1.107 +	mfn_mapper_queue_entry( mapper_handle1, i<<PAGE_SHIFT, 
   1.108 +				pfn_to_mfn_frame_list[i],
   1.109 +				PAGE_SIZE );
   1.110 +    }
   1.111 +    
   1.112 +    mfn_mapper_flush_queue(mapper_handle1);
   1.113 +
   1.114 +    /* Now they're pined, check they're the right dom. We assume
   1.115 +       they're not going to change, otherwise the suspend is going to fail, 
   1.116 +       with only itself to blame. */
   1.117 +
   1.118 +    for ( i = 0; i < (srec->nr_pfns+1023)/1024; i++ )
   1.119 +    {
   1.120 +	if ( !check_pfn_ownership(xc_handle, 
   1.121 +				  pfn_to_mfn_frame_list[i], domid) )
   1.122 +	{
   1.123 +	    ERROR("Invalid pfn-to-mfn frame list pointer");
   1.124 +	    goto out;
   1.125 +	}
   1.126 +    }
   1.127 +
   1.128 +    live_pfn_to_mfn_table = mfn_mapper_base( mapper_handle1 );
   1.129  
   1.130      /* We want zeroed memory so use calloc rather than malloc. */
   1.131      mfn_to_pfn_table = calloc(1, 4 * 1024 * 1024);
   1.132 -    pfn_to_mfn_table = calloc(1, 4 * srec.nr_pfns);
   1.133 -    pfn_type         = calloc(1, 4 * srec.nr_pfns);
   1.134 +    pfn_to_mfn_table = calloc(1, 4 * srec->nr_pfns);
   1.135 +    pfn_type         = calloc(1, 4 * srec->nr_pfns);
   1.136  
   1.137      if ( (mfn_to_pfn_table == NULL) ||
   1.138           (pfn_to_mfn_table == NULL) ||
   1.139 @@ -230,24 +272,10 @@ int xc_linux_save(int xc_handle,
   1.140       * loop we have each MFN mapped at most once. Note that there may be MFNs
   1.141       * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
   1.142       */
   1.143 -    pfn_to_mfn_frame = NULL;
   1.144 -    for ( i = 0; i < srec.nr_pfns; i++ )
   1.145 +
   1.146 +    for ( i = 0; i < srec->nr_pfns; i++ )
   1.147      {
   1.148 -        /* Each frameful of table frames must be checked & mapped on demand. */
   1.149 -        if ( (i & 1023) == 0 )
   1.150 -        {
   1.151 -            mfn = pfn_to_mfn_frame_list[i/1024];
   1.152 -            if ( !check_pfn_ownership(xc_handle, mfn, domid) )
   1.153 -            {
   1.154 -                ERROR("Invalid frame number if pfn-to-mfn frame list");
   1.155 -                goto out;
   1.156 -            }
   1.157 -            if ( pfn_to_mfn_frame != NULL )
   1.158 -                unmap_pfn(pm_handle, pfn_to_mfn_frame);
   1.159 -            pfn_to_mfn_frame = map_pfn_readonly(pm_handle, mfn);
   1.160 -        }
   1.161 -        
   1.162 -        mfn = pfn_to_mfn_frame[i & 1023];
   1.163 +        mfn = live_pfn_to_mfn_table[i];
   1.164  
   1.165          if ( !check_pfn_ownership(xc_handle, mfn, domid) )
   1.166          {
   1.167 @@ -256,14 +284,14 @@ int xc_linux_save(int xc_handle,
   1.168          }
   1.169  
   1.170          /* Did we map this MFN already? That would be invalid! */
   1.171 -        if ( MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   1.172 +        if ( mfn_to_pfn_table[mfn] )
   1.173          {
   1.174              ERROR("A machine frame appears twice in pseudophys space");
   1.175              goto out;
   1.176          }
   1.177  
   1.178 -        pfn_to_mfn_table[i] = mfn;
   1.179          mfn_to_pfn_table[mfn] = i;
   1.180 +	pfn_to_mfn_table[i] = live_pfn_to_mfn_table[i];
   1.181  
   1.182          /* Query page type by MFN, but store it by PFN. */
   1.183          if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) == 
   1.184 @@ -307,63 +335,110 @@ int xc_linux_save(int xc_handle,
   1.185      }
   1.186  
   1.187      /* Start writing out the saved-domain record. */
   1.188 -    ppage = map_pfn_readonly(pm_handle, shared_info_frame);
   1.189 +    live_shinfo = mfn_mapper_map_single(xc_handle, PROT_READ,
   1.190 +				  shared_info_frame, PAGE_SIZE);
   1.191 +
   1.192 +    /* Belts and braces safety check on the shared info record */
   1.193 +    if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
   1.194 +    {
   1.195 +        ERROR("Invalid shared_info_frame");
   1.196 +        goto out;
   1.197 +    }
   1.198 +
   1.199      if ( !checked_write(gfd, "LinuxGuestRecord",    16) ||
   1.200           !checked_write(gfd, name,                  sizeof(name)) ||
   1.201           !checked_write(gfd, &srec.nr_pfns,         sizeof(unsigned long)) ||
   1.202           !checked_write(gfd, &ctxt,                 sizeof(ctxt)) ||
   1.203 -         !checked_write(gfd, ppage,                 PAGE_SIZE) ||
   1.204 +         !checked_write(gfd, live_shinfo,           PAGE_SIZE) ||
   1.205           !checked_write(gfd, pfn_to_mfn_frame_list, PAGE_SIZE) ||
   1.206           !checked_write(gfd, pfn_type,              4 * srec.nr_pfns) )
   1.207      {
   1.208          ERROR("Error when writing to state file");
   1.209          goto out;
   1.210      }
   1.211 -    unmap_pfn(pm_handle, ppage);
   1.212 +    munmap(live_shinfo, PAGE_SIZE);
   1.213  
   1.214      verbose_printf("Saving memory pages:   0%%");
   1.215  
   1.216 +    if ( (mapper_handle2 = mfn_mapper_init(xc_handle, 
   1.217 +					   BATCH_SIZE*4096, PROT_READ )) 
   1.218 +	 == NULL )
   1.219 +        goto out;
   1.220 +
   1.221 +    region_base = mfn_mapper_base( mapper_handle2 );
   1.222 +
   1.223      /* Now write out each data page, canonicalising page tables as we go... */
   1.224      prev_pc = 0;
   1.225 -    for ( i = 0; i < srec.nr_pfns; i++ )
   1.226 +    for ( n = 0; n < srec.nr_pfns; )
   1.227      {
   1.228 -        this_pc = (i * 100) / srec.nr_pfns;
   1.229 +        this_pc = (n * 100) / srec.nr_pfns;
   1.230          if ( (this_pc - prev_pc) >= 5 )
   1.231          {
   1.232              verbose_printf("\b\b\b\b%3d%%", this_pc);
   1.233              prev_pc = this_pc;
   1.234          }
   1.235  
   1.236 -        mfn = pfn_to_mfn_table[i];
   1.237 +
   1.238 +	for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
   1.239 +	{
   1.240 +	    /* queue up mappings for all of the pages in this batch */
   1.241 +
   1.242 +	    mfn_mapper_queue_entry( mapper_handle2, j<<PAGE_SHIFT, 
   1.243 +				    pfn_to_mfn_frame_list[i],
   1.244 +				    PAGE_SIZE );
   1.245 +	}
   1.246 +	mfn_mapper_flush_queue(mapper_handle2);
   1.247 +	   
   1.248 +	typer_handle = get_type_init( xc_handle, BATCH_SIZE )
   1.249  
   1.250 -        ppage = map_pfn_readonly(pm_handle, mfn);
   1.251 -        memcpy(page, ppage, PAGE_SIZE);
   1.252 -        unmap_pfn(pm_handle, ppage);
   1.253 +	for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
   1.254 +	{
   1.255 +	    /* queue up ownership and type checks for all pages in batch */
   1.256 +
   1.257 +	    get_type_queue_entry( typer_handle, domain, 
   1.258 +				  pfn_to_mfn_frame_list[i] );
   1.259 +	}
   1.260 +
   1.261 +
   1.262 +	region_type = get_type;
   1.263 +
   1.264 +	for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
   1.265 +	{
   1.266 +	    /* write out pages in batch */
   1.267 +
   1.268 +	    mfn = pfn_to_mfn_table[i];
   1.269  
   1.270 -        if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
   1.271 -        {
   1.272 -            for ( j = 0; 
   1.273 -                  j < ((pfn_type[i] == L2TAB) ? 
   1.274 -                       (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
   1.275 -                  j++ )
   1.276 -            {
   1.277 -                if ( !(page[j] & _PAGE_PRESENT) ) continue;
   1.278 -                mfn = page[j] >> PAGE_SHIFT;
   1.279 -                if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   1.280 -                {
   1.281 -                    ERROR("Frame number in pagetable page is invalid");
   1.282 -                    goto out;
   1.283 -                }
   1.284 -                page[j] &= PAGE_SIZE - 1;
   1.285 -                page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
   1.286 -            }
   1.287 -        }
   1.288 +	    ppage = map_pfn_readonly(pm_handle, mfn);
   1.289 +	    memcpy(page, ppage, PAGE_SIZE);
   1.290 +	    unmap_pfn(pm_handle, ppage);
   1.291  
   1.292 -        if ( !checked_write(gfd, page, PAGE_SIZE) )
   1.293 -        {
   1.294 -            ERROR("Error when writing to state file");
   1.295 -            goto out;
   1.296 -        }
   1.297 +	    if ( (pfn_type[i] == L1TAB) || (pfn_type[i] == L2TAB) )
   1.298 +	    {
   1.299 +		for ( j = 0; 
   1.300 +		      j < ((pfn_type[i] == L2TAB) ? 
   1.301 +			   (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) : 1024); 
   1.302 +		      j++ )
   1.303 +		{
   1.304 +		    if ( !(page[j] & _PAGE_PRESENT) ) continue;
   1.305 +		    mfn = page[j] >> PAGE_SHIFT;
   1.306 +		    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(mfn) )
   1.307 +		    {
   1.308 +			ERROR("Frame number in pagetable page is invalid");
   1.309 +			goto out;
   1.310 +		    }
   1.311 +		    page[j] &= PAGE_SIZE - 1;
   1.312 +		    page[j] |= mfn_to_pfn_table[mfn] << PAGE_SHIFT;
   1.313 +		}
   1.314 +	    }
   1.315 +
   1.316 +	    if ( !checked_write(gfd, page, PAGE_SIZE) )
   1.317 +	    {
   1.318 +		ERROR("Error when writing to state file");
   1.319 +		goto out;
   1.320 +	    }
   1.321 +	}
   1.322 +	
   1.323 +	n+=j; /* i is the master loop counter */
   1.324      }
   1.325  
   1.326      verbose_printf("\b\b\b\b100%%\nMemory saved.\n");
   1.327 @@ -371,7 +446,7 @@ int xc_linux_save(int xc_handle,
   1.328      /* Success! */
   1.329      rc = 0;
   1.330  
   1.331 - out:
   1.332 +out:
   1.333      /* Restart the domain if we had to stop it to save its state. */
   1.334      if ( we_stopped_it )
   1.335      {
   1.336 @@ -397,4 +472,6 @@ int xc_linux_save(int xc_handle,
   1.337          unlink(state_file);
   1.338      
   1.339      return !!rc;
   1.340 +
   1.341 +
   1.342  }
     2.1 --- a/tools/xc/lib/xc_private.c	Tue Apr 27 13:13:06 2004 +0000
     2.2 +++ b/tools/xc/lib/xc_private.c	Tue Apr 27 16:15:55 2004 +0000
     2.3 @@ -45,6 +45,112 @@ void unmap_pfn(int pm_handle, void *vadd
     2.4      (void)munmap(vaddr, PAGE_SIZE);
     2.5  }
     2.6  
     2.7 +/*******************/
     2.8 +
     2.9 +void * mfn_mapper_map_single(int xc_handle, int prot, 
    2.10 +			     unsigned long mfn, int size)
    2.11 +{
    2.12 +    privcmd_mmap_t ioctlx; 
    2.13 +    privcmd_mmap_entry_t entry; 
    2.14 +    void *addr;
    2.15 +    addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
    2.16 +    if (addr)
    2.17 +    {
    2.18 +	ioctlx.num=1;
    2.19 +	ioctlx.entry=&entry;
    2.20 +	entry.va=(unsigned long) addr;
    2.21 +	entry.mfn=mfn;
    2.22 +	entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
    2.23 +	if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 )
    2.24 +	    return 0;
    2.25 +    }
    2.26 +    return addr;
    2.27 +}
    2.28 +
    2.29 +mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot)
    2.30 +{
    2.31 +    mfn_mapper_t * t;
    2.32 +    t = calloc( 1, sizeof(mfn_mapper_t)+
    2.33 +		mfn_mapper_queue_size*sizeof(privcmd_mmap_entry_t) );
    2.34 +    if (!t) return NULL;
    2.35 +    t->xc_handle = xc_handle;
    2.36 +    t->size = size;
    2.37 +    t->prot = prot;
    2.38 +    t->max_queue_size = mfn_mapper_queue_size;
    2.39 +    t->addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 );
    2.40 +    if (!t->addr)
    2.41 +    {
    2.42 +	free(t);
    2.43 +	return NULL;
    2.44 +    }
    2.45 +    t->ioctl.num = 0;
    2.46 +    t->ioctl.entry = (privcmd_mmap_entry_t *) &t[1];
    2.47 +    return t;
    2.48 +}
    2.49 +
    2.50 +void * mfn_mapper_base(mfn_mapper_t *t)
    2.51 +{
    2.52 +    return t->addr;
    2.53 +}
    2.54 +
    2.55 +void mfn_mapper_close(mfn_mapper_t *t)
    2.56 +{
    2.57 +    if(t->addr) munmap( t->addr, t->size );
    2.58 +    free(t);    
    2.59 +}
    2.60 +
    2.61 +int mfn_mapper_flush_queue(mfn_mapper_t *t)
    2.62 +{
    2.63 +    int rc;
    2.64 +
    2.65 +    rc = ioctl( t->xc_handle, IOCTL_PRIVCMD_MMAP, &t->ioctl );
    2.66 +    if (rc<0) return rc;
    2.67 +    t->ioctl.num = 0;
    2.68 +    return 0;
    2.69 +}
    2.70 +
    2.71 +void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
    2.72 +			      unsigned long mfn, int size)
    2.73 +{
    2.74 +    privcmd_mmap_entry_t *entry, *prev;
    2.75 +    int pages;
    2.76 +
    2.77 +    offset &= PAGE_MASK;
    2.78 +    pages =(size+PAGE_SIZE-1)>>PAGE_SHIFT;
    2.79 +    entry = &t->ioctl.entry[t->ioctl.num];       
    2.80 +
    2.81 +    if ( t->ioctl.num > 0 )
    2.82 +    {
    2.83 +	prev = &t->ioctl.entry[t->ioctl.num-1];       
    2.84 +
    2.85 +	if ( (prev->va+(prev->npages*PAGE_SIZE)) == (t->addr+offset) &&
    2.86 +	     (prev->mfn+prev->npages) == mfn )
    2.87 +	{
    2.88 +	    prev->npages += pages;
    2.89 +printf("merge\n");
    2.90 +	    return t->addr+offset;
    2.91 +	}
    2.92 +    }
    2.93 +     
    2.94 +    entry->va = t->addr+offset;
    2.95 +    entry->mfn = mfn;
    2.96 +    entry->npages = pages;
    2.97 +    t->ioctl.num++;       
    2.98 +
    2.99 +    if(t->ioctl.num == t->max_queue_size)
   2.100 +    {
   2.101 +	if ( mfn_mapper_flush_queue(t) )
   2.102 +	return 0;
   2.103 +    }
   2.104 +
   2.105 +    return t->addr+offset;
   2.106 +}
   2.107 +
   2.108 +
   2.109 +
   2.110 +
   2.111 +/*******************/
   2.112 +
   2.113  #define FIRST_MMU_UPDATE 2
   2.114  
   2.115  static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
     3.1 --- a/tools/xc/lib/xc_private.h	Tue Apr 27 13:13:06 2004 +0000
     3.2 +++ b/tools/xc/lib/xc_private.h	Tue Apr 27 16:15:55 2004 +0000
     3.3 @@ -174,4 +174,49 @@ int add_mmu_update(int xc_handle, mmu_t 
     3.4                     unsigned long ptr, unsigned long val);
     3.5  int finish_mmu_updates(int xc_handle, mmu_t *mmu);
     3.6  
     3.7 +
     3.8 +/*
     3.9 + * ioctl-based mfn mapping interface
    3.10 + */
    3.11 +
    3.12 +/*
    3.13 +typedef struct privcmd_mmap_entry {
    3.14 +    unsigned long va;
    3.15 +    unsigned long mfn;
    3.16 +    unsigned long npages;
    3.17 +} privcmd_mmap_entry_t; 
    3.18 +
    3.19 +typedef struct privcmd_mmap {
    3.20 +    int num;
    3.21 +    privcmd_mmap_entry_t *entry;
    3.22 +} privcmd_mmap_t; 
    3.23 +*/
    3.24 +
    3.25 +#define mfn_mapper_queue_size 128
    3.26 +
    3.27 +typedef struct mfn_mapper {
    3.28 +    int xc_handle;
    3.29 +    int size;
    3.30 +    int prot;
    3.31 +    int max_queue_size;
    3.32 +    void * addr;
    3.33 +    privcmd_mmap_t ioctl; 
    3.34 +    
    3.35 +} mfn_mapper_t;
    3.36 +
    3.37 +void * mfn_mapper_map_single(int xc_handle, int prot, 
    3.38 +			     unsigned long mfn, int size);
    3.39 +
    3.40 +mfn_mapper_t * mfn_mapper_init(int xc_handle, int size, int prot);
    3.41 +
    3.42 +void * mfn_mapper_base(mfn_mapper_t *t);
    3.43 +
    3.44 +void mfn_mapper_close(mfn_mapper_t *t);
    3.45 +
    3.46 +int mfn_mapper_flush_queue(mfn_mapper_t *t);
    3.47 +
    3.48 +void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset, 
    3.49 +			      unsigned long mfn, int size );
    3.50 +
    3.51 +
    3.52  #endif /* __XC_PRIVATE_H__ */
     4.1 --- a/xen/common/memory.c	Tue Apr 27 13:13:06 2004 +0000
     4.2 +++ b/xen/common/memory.c	Tue Apr 27 16:15:55 2004 +0000
     4.3 @@ -1041,6 +1041,12 @@ int do_mmu_update(mmu_update_t *ureqs, i
     4.4  
     4.5              machine_to_phys_mapping[pfn] = req.val;
     4.6              okay = 1;
     4.7 +
     4.8 +	    /*  if in log dirty shadow mode, mark the corresponding 
     4.9 +		psuedo-physical page as dirty */
    4.10 +	    if( unlikely(current->mm.shadow_mode == SHM_logdirty) )
    4.11 +		mark_dirty( &current->mm, pfn );
    4.12 +
    4.13              put_page(&frame_table[pfn]);
    4.14              break;
    4.15  
     5.1 --- a/xen/net/dev.c	Tue Apr 27 13:13:06 2004 +0000
     5.2 +++ b/xen/net/dev.c	Tue Apr 27 16:15:55 2004 +0000
     5.3 @@ -555,8 +555,11 @@ void deliver_packet(struct sk_buff *skb,
     5.4  
     5.5          /* Avoid the fault later. */
     5.6  	*sptr = new_pte;
     5.7 +	unmap_domain_mem(sptr);
     5.8  
     5.9 -	unmap_domain_mem(sptr);
    5.10 +	if( p->mm.shadow_mode == SHM_logdirty )
    5.11 +		mark_dirty( &p->mm, new_page-frame_table );
    5.12 +
    5.13  	put_shadow_status(&p->mm);
    5.14      }
    5.15  
     6.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c	Tue Apr 27 13:13:06 2004 +0000
     6.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/dom0/core.c	Tue Apr 27 16:15:55 2004 +0000
     6.3 @@ -62,16 +62,70 @@ static int privcmd_ioctl(struct inode *i
     6.4      }
     6.5      break;
     6.6  
     6.7 +    case IOCTL_PRIVCMD_MMAP:
     6.8 +    {
     6.9 +#define PRIVCMD_MMAP_SZ 32
    6.10 +	privcmd_mmap_t mmapcmd;
    6.11 +	privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
    6.12 +	int i;
    6.13 +
    6.14 +        if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
    6.15 +            return -EFAULT;
    6.16 +
    6.17 +	p = mmapcmd.entry;
    6.18 +
    6.19 +	for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
    6.20 +	{
    6.21 +	    int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
    6.22 +		PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
    6.23 +	    if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
    6.24 +		return -EFAULT;
    6.25 +	    
    6.26 +	    for (j=0;j<n;j++)
    6.27 +	    {
    6.28 +		struct vm_area_struct *vma = 
    6.29 +		    find_vma( current->mm, msg[j].va );
    6.30 +
    6.31 +		if (!vma)
    6.32 +		    return -EINVAL;
    6.33 +
    6.34 +		if (msg[j].va > PAGE_OFFSET)
    6.35 +		    return -EINVAL;
    6.36 +
    6.37 +		if (msg[j].va + (msg[j].npages<<PAGE_SHIFT) > vma->vm_end)
    6.38 +		    return -EINVAL;
    6.39 +
    6.40 +		if (direct_remap_area_pages(vma->vm_mm, 
    6.41 +					    msg[j].va&PAGE_MASK, 
    6.42 +					    msg[j].mfn<<PAGE_SHIFT, 
    6.43 +					    msg[j].npages<<PAGE_SHIFT, 
    6.44 +					    vma->vm_page_prot))
    6.45 +		    return -EINVAL;
    6.46 +	    }
    6.47 +	}
    6.48 +	ret = 0;
    6.49 +    }
    6.50 +    break;
    6.51 +
    6.52      default:
    6.53          ret = -EINVAL;
    6.54      	break;
    6.55 -	}
    6.56 +    }
    6.57      return ret;
    6.58  }
    6.59  
    6.60 +static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
    6.61 +{
    6.62 +printk(KERN_ALERT"privcmd_mmap\n");
    6.63 +	/* DONTCOPY is essential for Xen as copy_page_range is broken. */
    6.64 +	vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
    6.65 +
    6.66 +	return 0;
    6.67 +}
    6.68  
    6.69  static struct file_operations privcmd_file_ops = {
    6.70 -  ioctl : privcmd_ioctl
    6.71 +  ioctl : privcmd_ioctl,
    6.72 +  mmap:   privcmd_mmap
    6.73  };
    6.74  
    6.75  
     7.1 --- a/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c	Tue Apr 27 13:13:06 2004 +0000
     7.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/mm/ioremap.c	Tue Apr 27 16:15:55 2004 +0000
     7.3 @@ -60,10 +60,12 @@ static inline void direct_remap_area_pte
     7.4      if (address >= end)
     7.5          BUG();
     7.6      do {
     7.7 +#if 0  /* thanks to new ioctl mmaping interface this is no longer a bug */
     7.8          if (!pte_none(*pte)) {
     7.9              printk("direct_remap_area_pte: page already exists\n");
    7.10              BUG();
    7.11          }
    7.12 +#endif
    7.13          v->ptr = virt_to_machine(pte);
    7.14          v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot) | _PAGE_IO;
    7.15          v++;
    7.16 @@ -118,6 +120,9 @@ int direct_remap_area_pages(struct mm_st
    7.17      pgd_t * dir;
    7.18      unsigned long end = address + size;
    7.19  
    7.20 +printk("direct_remap_area_pages va=%08lx ma=%08lx size=%d\n",
    7.21 +       address, machine_addr, size);
    7.22 +
    7.23      machine_addr -= address;
    7.24      dir = pgd_offset(mm, address);
    7.25      flush_cache_all();
     8.1 --- a/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h	Tue Apr 27 13:13:06 2004 +0000
     8.2 +++ b/xenolinux-2.4.26-sparse/include/asm-xen/proc_cmd.h	Tue Apr 27 16:15:55 2004 +0000
     8.3 @@ -13,6 +13,17 @@ typedef struct privcmd_hypercall
     8.4      unsigned long arg[5];
     8.5  } privcmd_hypercall_t;
     8.6  
     8.7 +typedef struct privcmd_mmap_entry {
     8.8 +    unsigned long va;
     8.9 +    unsigned long mfn;
    8.10 +    unsigned long npages;
    8.11 +} privcmd_mmap_entry_t; 
    8.12 +
    8.13 +typedef struct privcmd_mmap {
    8.14 +    int num;
    8.15 +    privcmd_mmap_entry_t *entry;
    8.16 +} privcmd_mmap_t; 
    8.17 +
    8.18  typedef struct privcmd_blkmsg
    8.19  {
    8.20      unsigned long op;
    8.21 @@ -24,5 +35,7 @@ typedef struct privcmd_blkmsg
    8.22      _IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
    8.23  #define IOCTL_PRIVCMD_BLKMSG           \
    8.24      _IOC(_IOC_NONE, 'P', 1, sizeof(privcmd_blkmsg_t))
    8.25 +#define IOCTL_PRIVCMD_MMAP             \
    8.26 +    _IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
    8.27  
    8.28  #endif /* __PROC_CMD_H__ */