direct-io.hg

changeset 2294:192c9526f217

bitkeeper revision 1.1159.42.3 (4124b290EbHmIxFeu9GnoeIKVia2lA)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
author iap10@labyrinth.cl.cam.ac.uk
date Thu Aug 19 14:00:48 2004 +0000 (2004-08-19)
parents c8a29df316b8 ada3a221df8d
children 8be25c10fa1e c43281038788
files tools/libxc/xc_linux_save.c xen/arch/x86/shadow.c
line diff
     1.1 --- a/tools/libxc/xc_linux_save.c	Thu Aug 19 13:50:49 2004 +0000
     1.2 +++ b/tools/libxc/xc_linux_save.c	Thu Aug 19 14:00:48 2004 +0000
     1.3 @@ -295,7 +295,7 @@ int xc_linux_save(int xc_handle, XcIOCon
     1.4      int rc = 1, i, j, k, last_iter, iter = 0;
     1.5      unsigned long mfn;
     1.6      u32 domid = ioctxt->domain;
     1.7 -    int live = 0; // (ioctxt->flags & XCFLAGS_LIVE);
     1.8 +    int live =  (ioctxt->flags & XCFLAGS_LIVE);
     1.9      int debug = (ioctxt->flags & XCFLAGS_DEBUG);
    1.10      int sent_last_iter, skip_this_iter;
    1.11  
    1.12 @@ -440,7 +440,8 @@ int xc_linux_save(int xc_handle, XcIOCon
    1.13  
    1.14      /* Domain is still running at this point */
    1.15  
    1.16 -    if( live ){ 
    1.17 +    if( live ){
    1.18 +printf("GO LIVE!!\n");
    1.19          if ( xc_shadow_control( xc_handle, domid, 
    1.20                                  DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
    1.21                                  NULL, 0, NULL ) < 0 ) {
     2.1 --- a/xen/arch/x86/shadow.c	Thu Aug 19 13:50:49 2004 +0000
     2.2 +++ b/xen/arch/x86/shadow.c	Thu Aug 19 14:00:48 2004 +0000
     2.3 @@ -29,41 +29,6 @@ hypercall lock anyhow (at least initiall
     2.4  ********/
     2.5  
     2.6  
     2.7 -/**
     2.8 -
     2.9 -FIXME:
    2.10 -
    2.11 -The shadow table flush command is dangerous on SMP systems as the
    2.12 -guest may be using the L2 on one CPU while the other is trying to 
    2.13 -blow the table away. 
    2.14 -
    2.15 -The current save restore code works around this by not calling FLUSH,
    2.16 -but by calling CLEAN2 which leaves all L2s in tact (this is probably
    2.17 -quicker anyhow).
    2.18 -
    2.19 -Even so, we have to be very careful. The flush code may need to cause
    2.20 -a TLB flush on another CPU. It needs to do this while holding the
    2.21 -shadow table lock. The trouble is, the guest may be in the shadow page
    2.22 -fault handler spinning waiting to grab the shadow lock. It may have
    2.23 -intterupts disabled, hence we can't use the normal flush_tlb_cpu
    2.24 -mechanism.
    2.25 -
    2.26 -For the moment, we have a grim race whereby the spinlock in the shadow
    2.27 -fault handler is actually a try lock, in a loop with a helper for the
    2.28 -tlb flush code.
    2.29 -
    2.30 -A better soloution would be to take a new flush lock, then raise a
    2.31 -per-domain soft irq on the other CPU.  The softirq will switch to
    2.32 -init's PTs, then do an atomic inc of a variable to count himself in,
    2.33 -then spin on a lock.  Having noticed that the other guy has counted
    2.34 -in, flush the shadow table, then release him by dropping the lock. He
    2.35 -will then reload cr3 from mm.page_table on the way out of the softirq.
    2.36 -
    2.37 -In domian-softirq context we know that the guy holds no locks and has
    2.38 -interrupts enabled. Nothing can go wrong ;-)
    2.39 -
    2.40 -**/
    2.41 -
    2.42  static inline void free_shadow_page(struct mm_struct *m, 
    2.43                                      struct pfn_info *page)
    2.44  {
    2.45 @@ -381,9 +346,9 @@ static int shadow_mode_table_op(struct d
    2.46  		d->mm.shadow_dirty_net_count   = 0;
    2.47  		d->mm.shadow_dirty_block_count = 0;
    2.48  	
    2.49 -		sc->pages = d->tot_pages;
    2.50 +		sc->pages = d->max_pages;
    2.51  
    2.52 -		if( d->tot_pages > sc->pages || 
    2.53 +		if( d->max_pages > sc->pages || 
    2.54  			!sc->dirty_bitmap || !d->mm.shadow_dirty_bitmap )
    2.55  		{
    2.56  			rc = -EINVAL;
    2.57 @@ -393,10 +358,10 @@ static int shadow_mode_table_op(struct d
    2.58  	
    2.59  #define chunk (8*1024) // do this in 1KB chunks for L1 cache
    2.60  	
    2.61 -		for(i=0;i<d->tot_pages;i+=chunk)
    2.62 +		for(i=0;i<d->max_pages;i+=chunk)
    2.63  		{
    2.64 -			int bytes = ((  ((d->tot_pages-i) > (chunk))?
    2.65 -							(chunk):(d->tot_pages-i) ) + 7) / 8;
    2.66 +			int bytes = ((  ((d->max_pages-i) > (chunk))?
    2.67 +							(chunk):(d->max_pages-i) ) + 7) / 8;
    2.68  	    
    2.69  			copy_to_user( sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
    2.70  						  d->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
    2.71 @@ -428,21 +393,21 @@ static int shadow_mode_table_op(struct d
    2.72  		sc->stats.dirty_net_count   = d->mm.shadow_dirty_net_count;
    2.73  		sc->stats.dirty_block_count = d->mm.shadow_dirty_block_count;
    2.74  	
    2.75 -		if( d->tot_pages > sc->pages || 
    2.76 +		if( d->max_pages > sc->pages || 
    2.77  			!sc->dirty_bitmap || !d->mm.shadow_dirty_bitmap )
    2.78  		{
    2.79  			rc = -EINVAL;
    2.80  			goto out;
    2.81  		}
    2.82  	
    2.83 -		sc->pages = d->tot_pages;
    2.84 +		sc->pages = d->max_pages;
    2.85  	
    2.86  #define chunk (8*1024) // do this in 1KB chunks for L1 cache
    2.87  	
    2.88 -		for(i=0;i<d->tot_pages;i+=chunk)
    2.89 +		for(i=0;i<d->max_pages;i+=chunk)
    2.90  		{
    2.91 -			int bytes = ((  ((d->tot_pages-i) > (chunk))?
    2.92 -							(chunk):(d->tot_pages-i) ) + 7) / 8;
    2.93 +			int bytes = ((  ((d->max_pages-i) > (chunk))?
    2.94 +							(chunk):(d->max_pages-i) ) + 7) / 8;
    2.95  	    
    2.96  			copy_to_user( sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
    2.97  						  d->mm.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
    2.98 @@ -475,7 +440,13 @@ int shadow_mode_control(struct domain *d
    2.99      unsigned int cmd = sc->op;
   2.100      int rc = 0;
   2.101  
   2.102 -    spin_lock(&d->mm.shadow_lock);
   2.103 +	if (d == current)
   2.104 +		printk("Attempt to control your _own_ shadow tables. I hope you know what you're doing!\n");
   2.105 +
   2.106 +	domain_pause(d);
   2.107 +	synchronise_pagetables(d->processor);
   2.108 +
   2.109 +	spin_lock(&d->mm.shadow_lock);
   2.110  
   2.111      if ( cmd == DOM0_SHADOW_CONTROL_OP_OFF )
   2.112      {
   2.113 @@ -502,10 +473,10 @@ int shadow_mode_control(struct domain *d
   2.114          rc = -EINVAL;
   2.115      }
   2.116  
   2.117 -	flush_tlb_cpu(d->processor);
   2.118 -   
   2.119      spin_unlock(&d->mm.shadow_lock);
   2.120  
   2.121 +	domain_unpause(d);
   2.122 +
   2.123      return rc;
   2.124  }
   2.125  
   2.126 @@ -518,6 +489,7 @@ static inline struct pfn_info *alloc_sha
   2.127  void unshadow_table( unsigned long gpfn, unsigned int type )
   2.128  {
   2.129      unsigned long spfn;
   2.130 +	struct domain *d = frame_table[gpfn].u.inuse.domain;
   2.131  
   2.132      SH_VLOG("unshadow_table type=%08x gpfn=%08lx",
   2.133              type,
   2.134 @@ -530,11 +502,11 @@ void unshadow_table( unsigned long gpfn,
   2.135      // even in the SMP guest case, there won't be a race here as
   2.136      // this CPU was the one that cmpxchg'ed the page to invalid
   2.137  
   2.138 -    spfn = __shadow_status(&current->mm, gpfn) & PSH_pfn_mask;
   2.139 +    spfn = __shadow_status(&d->mm, gpfn) & PSH_pfn_mask;
   2.140  
   2.141 -    delete_shadow_status(&current->mm, gpfn);
   2.142 +    delete_shadow_status(&d->mm, gpfn);
   2.143  
   2.144 -    free_shadow_page( &current->mm, &frame_table[spfn] );
   2.145 +    free_shadow_page(&d->mm, &frame_table[spfn] );
   2.146  
   2.147  }
   2.148  
   2.149 @@ -651,15 +623,7 @@ int shadow_fault( unsigned long va, long
   2.150  
   2.151      // take the lock and reread gpte
   2.152  
   2.153 -    while( unlikely(!spin_trylock(&current->mm.shadow_lock)) )
   2.154 -	{
   2.155 -		extern volatile unsigned long flush_cpumask;
   2.156 -		if ( test_and_clear_bit(smp_processor_id(), &flush_cpumask) )
   2.157 -			local_flush_tlb();
   2.158 -		rep_nop();
   2.159 -	}
   2.160 -	
   2.161 -	ASSERT(spin_is_locked(&current->mm.shadow_lock));
   2.162 +	spin_lock(&current->mm.shadow_lock);
   2.163  	
   2.164      if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
   2.165      {