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
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(¤t->mm, gpfn) & PSH_pfn_mask; 2.139 + spfn = __shadow_status(&d->mm, gpfn) & PSH_pfn_mask; 2.140 2.141 - delete_shadow_status(¤t->mm, gpfn); 2.142 + delete_shadow_status(&d->mm, gpfn); 2.143 2.144 - free_shadow_page( ¤t->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(¤t->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(¤t->mm.shadow_lock)); 2.162 + spin_lock(¤t->mm.shadow_lock); 2.163 2.164 if ( unlikely(__get_user(gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) ) 2.165 {