direct-io.hg

changeset 1259:a0d70d73a737

bitkeeper revision 1.831 (406995dbwlqGk2qHrfw3kwGxQ37WSw)

Flush and clean shadow page table ops added.
Add 'dist' target back to Xen Makefile.
author iap10@tetris.cl.cam.ac.uk
date Tue Mar 30 15:44:27 2004 +0000 (2004-03-30)
parents b9ab14271453
children ae024a256b34
files tools/xc/py/Xc.c xen/Makefile xen/common/shadow.c xen/include/asm-i386/processor.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/xen/shadow.h
line diff
     1.1 --- a/tools/xc/py/Xc.c	Fri Mar 26 15:09:04 2004 +0000
     1.2 +++ b/tools/xc/py/Xc.c	Tue Mar 30 15:44:27 2004 +0000
     1.3 @@ -914,6 +914,28 @@ static PyObject *pyxc_rrobin_global_set(
     1.4      return zero;
     1.5  }
     1.6  
     1.7 +static PyObject *pyxc_shadow_control(PyObject *self,
     1.8 +                                     PyObject *args,
     1.9 +                                     PyObject *kwds)
    1.10 +{
    1.11 +    XcObject *xc = (XcObject *)self;
    1.12 +
    1.13 +    u64 dom;
    1.14 +    int op=0;
    1.15 +
    1.16 +    static char *kwd_list[] = { "dom", "op", NULL };
    1.17 +
    1.18 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwd_list, 
    1.19 +                                      &dom, &op) )
    1.20 +        return NULL;
    1.21 +
    1.22 +    if ( xc_shadow_control(xc->xc_handle, dom, op) != 0 )
    1.23 +        return PyErr_SetFromErrno(xc_error);
    1.24 +    
    1.25 +    Py_INCREF(zero);
    1.26 +    return zero;
    1.27 +}
    1.28 +
    1.29  
    1.30  static PyMethodDef pyxc_methods[] = {
    1.31      { "domain_create", 
    1.32 @@ -1211,6 +1233,15 @@ static PyMethodDef pyxc_methods[] = {
    1.33        "Returns [dict]: information about the hardware"
    1.34        "        [None]: on failure.\n" },
    1.35  
    1.36 +    { "shadow_control", 
    1.37 +      (PyCFunction)pyxc_shadow_control, 
    1.38 +      METH_VARARGS | METH_KEYWORDS, "\n"
    1.39 +      "Set parameter for shadow pagetable interface\n"
    1.40 +      " dom [long]:    Identifier of domain.\n"
    1.41 +      " op [int, 0]: operation\n\n"
    1.42 +      "Returns: [int] 0 on success; -1 on error.\n" },
    1.43 +
    1.44 +
    1.45      { NULL, NULL, 0, NULL }
    1.46  };
    1.47  
     2.1 --- a/xen/Makefile	Fri Mar 26 15:09:04 2004 +0000
     2.2 +++ b/xen/Makefile	Tue Mar 30 15:44:27 2004 +0000
     2.3 @@ -22,6 +22,9 @@ install: $(TARGET)
     2.4  	mkdir -p $(prefix)/boot
     2.5  	install -m0644 $(TARGET).gz $(prefix)/boot
     2.6  
     2.7 +dist: $(TARGET)
     2.8 +	$(MAKE) prefix=`pwd`/../../install dist=yes install
     2.9 +
    2.10  clean: delete-links
    2.11  	$(MAKE) -C tools clean
    2.12  	$(MAKE) -C common clean
     3.1 --- a/xen/common/shadow.c	Fri Mar 26 15:09:04 2004 +0000
     3.2 +++ b/xen/common/shadow.c	Tue Mar 30 15:44:27 2004 +0000
     3.3 @@ -26,21 +26,107 @@ hypercall lock anyhow (at least initiall
     3.4  
     3.5  ********/
     3.6  
     3.7 -static inline void free_shadow_page( struct mm_struct *m, unsigned int pfn )
     3.8 +static inline void free_shadow_page( struct mm_struct *m, 
     3.9 +									 struct pfn_info *pfn_info )
    3.10  {
    3.11      unsigned long flags;
    3.12 +	unsigned long type = pfn_info->type_and_flags & PGT_type_mask;
    3.13  
    3.14  	m->shadow_page_count--;
    3.15  
    3.16 +	if (type == PGT_l1_page_table)
    3.17 +		perfc_decr(shadow_l1_pages);
    3.18 +    else if (type == PGT_l2_page_table)
    3.19 +		perfc_decr(shadow_l2_pages);
    3.20 +	else printk("Free shadow weird page type pfn=%08x type=%08lx\n",
    3.21 +				frame_table-pfn_info, pfn_info->type_and_flags);
    3.22 +				
    3.23 +
    3.24 +	pfn_info->type_and_flags = 0;
    3.25 +
    3.26      spin_lock_irqsave(&free_list_lock, flags);
    3.27 -    list_add(&frame_table[pfn].list, &free_list);
    3.28 +    list_add(&pfn_info->list, &free_list);
    3.29      free_pfns++;
    3.30      spin_unlock_irqrestore(&free_list_lock, flags);
    3.31  }
    3.32  
    3.33  static void __free_shadow_table( struct mm_struct *m )
    3.34  {
    3.35 -	int j;
    3.36 +	int j, free=0;
    3.37 +	struct shadow_status *a,*next;
    3.38 +	
    3.39 +	// the code assumes you're not using the page tables i.e.
    3.40 +    // the domain is stopped and cr3 is something else!!
    3.41 +
    3.42 +    // walk the hash table and call free_shadow_page on all pages
    3.43 +
    3.44 +	shadow_audit(m,1);
    3.45 +
    3.46 +    for(j=0;j<shadow_ht_buckets;j++)
    3.47 +    {
    3.48 +        a = &m->shadow_ht[j];        
    3.49 +        if (a->pfn)
    3.50 +        {
    3.51 +            free_shadow_page( m, 
    3.52 +                          &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
    3.53 +            a->pfn = 0;
    3.54 +            a->spfn_and_flags = 0;
    3.55 +            free++;
    3.56 +        }
    3.57 +        next=a->next;
    3.58 +        a->next=NULL;
    3.59 +        a=next;
    3.60 +        while(a)
    3.61 +		{ 
    3.62 +            struct shadow_status *next = a->next;
    3.63 +
    3.64 +            free_shadow_page( m, 
    3.65 +                          &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
    3.66 +            a->pfn = 0;
    3.67 +            a->spfn_and_flags = 0;
    3.68 +            free++;
    3.69 +            a->next = m->shadow_ht_free;           
    3.70 +            m->shadow_ht_free = a;
    3.71 +            a=next;
    3.72 +		}
    3.73 +	shadow_audit(m,0);
    3.74 +	}
    3.75 +   SH_LOG("Free shadow table. Freed= %d",free);
    3.76 +}
    3.77 +
    3.78 +static inline int shadow_page_op( struct mm_struct *m, unsigned int op,
    3.79 +                                   struct pfn_info *spfn_info )
    3.80 +{
    3.81 +    int work = 0;
    3.82 +    unsigned int spfn = spfn_info-frame_table;
    3.83 +
    3.84 +    switch( op )
    3.85 +    {
    3.86 +        case DOM0_SHADOW_CONTROL_OP_CLEAN:
    3.87 +        {
    3.88 +            int i;
    3.89 +            if ( (spfn_info->type_and_flags & PGT_type_mask) == 
    3.90 +                                                      PGT_l1_page_table )
    3.91 +            {
    3.92 +                unsigned long * spl1e = map_domain_mem( spfn<<PAGE_SHIFT );
    3.93 +
    3.94 +                for (i=0;i<ENTRIES_PER_L1_PAGETABLE;i++)
    3.95 +                {                    
    3.96 +                    if ( spl1e[i] & _PAGE_RW )
    3.97 +                    {
    3.98 +                        work++;
    3.99 +                        spl1e[i] &= ~_PAGE_RW;
   3.100 +                    }
   3.101 +                }
   3.102 +                unmap_domain_mem( spl1e );
   3.103 +            }
   3.104 +        }
   3.105 +    }
   3.106 +    return work;
   3.107 +}
   3.108 +static void __scan_shadow_table( struct mm_struct *m, unsigned int op )
   3.109 +{
   3.110 +	int j, work=0;
   3.111  	struct shadow_status *a;
   3.112  	
   3.113  	// the code assumes you're not using the page tables i.e.
   3.114 @@ -48,32 +134,30 @@ static void __free_shadow_table( struct 
   3.115  
   3.116      // walk the hash table and call free_shadow_page on all pages
   3.117  
   3.118 +	shadow_audit(m,1);
   3.119 +
   3.120      for(j=0;j<shadow_ht_buckets;j++)
   3.121      {
   3.122          a = &m->shadow_ht[j];        
   3.123          if (a->pfn)
   3.124          {
   3.125 -            free_shadow_page( m, a->spfn_and_flags & PSH_pfn_mask );
   3.126 -            a->pfn = 0;
   3.127 -            a->spfn_and_flags = 0;
   3.128 +            work += shadow_page_op( m, op, &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
   3.129          }
   3.130          a=a->next;
   3.131          while(a)
   3.132  		{ 
   3.133 -            struct shadow_status *next = a->next;
   3.134 -            free_shadow_page( m, a->spfn_and_flags & PSH_pfn_mask );
   3.135 -            a->pfn = 0;
   3.136 -            a->spfn_and_flags = 0;
   3.137 -            a->next = m->shadow_ht_free;
   3.138 -            m->shadow_ht_free = a;
   3.139 -            a=next;
   3.140 +            work += shadow_page_op( m, op, &frame_table[a->spfn_and_flags & PSH_pfn_mask] );
   3.141 +            a=a->next;
   3.142  		}
   3.143 +	shadow_audit(m,0);
   3.144  	}
   3.145 +   SH_LOG("Scan shadow table. Work=%d l1=%d l2=%d", work, perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages));
   3.146  }
   3.147  
   3.148  
   3.149 -int shadow_mode_enable( struct mm_struct *m, unsigned int mode )
   3.150 +int shadow_mode_enable( struct task_struct *p, unsigned int mode )
   3.151  {
   3.152 +    struct mm_struct *m = &p->mm;
   3.153  	struct shadow_status **fptr;
   3.154  	int i;
   3.155  
   3.156 @@ -102,6 +186,8 @@ int shadow_mode_enable( struct mm_struct
   3.157  
   3.158  	memset( m->shadow_ht_extras, 0, sizeof(void*) + (shadow_ht_extra_size * 
   3.159  							   sizeof(struct shadow_status)) );
   3.160 +
   3.161 +    m->shadow_extras_count++;
   3.162  	
   3.163      // add extras to free list
   3.164  	fptr = &m->shadow_ht_free;
   3.165 @@ -114,6 +200,13 @@ int shadow_mode_enable( struct mm_struct
   3.166  	*((struct shadow_status ** ) 
   3.167          &m->shadow_ht_extras[shadow_ht_extra_size]) = NULL;
   3.168  
   3.169 +    if ( mode == SHM_logdirty )
   3.170 +    {
   3.171 +        m->shadow_dirty_bitmap = kmalloc( p->max_pages/8, GFP_KERNEL );
   3.172 +        if( !m->shadow_dirty_bitmap  ) goto nomem;
   3.173 +        memset(m->shadow_dirty_bitmap,0,p->max_pages/8);
   3.174 +    }
   3.175 +
   3.176  	spin_unlock(&m->shadow_lock);
   3.177  
   3.178      // call shadow_mk_pagetable
   3.179 @@ -126,16 +219,43 @@ nomem:
   3.180  	return -ENOMEM;
   3.181  }
   3.182  
   3.183 -static void shadow_mode_disable( struct mm_struct *m )
   3.184 +static void shadow_mode_disable( struct task_struct *p )
   3.185  {
   3.186 +    struct mm_struct *m = &p->mm;
   3.187 +	struct shadow_status *next;
   3.188  
   3.189 -    // free the hash buckets as you go
   3.190 +    spin_lock(&m->shadow_lock);
   3.191 +	__free_shadow_table( m );
   3.192 +	m->shadow_mode = 0;
   3.193 +	spin_unlock(&m->shadow_lock);
   3.194 +
   3.195 +	SH_LOG("freed tables count=%d l1=%d l2=%d",
   3.196 +		   m->shadow_page_count, perfc_value(shadow_l1_pages), perfc_value(shadow_l2_pages));
   3.197 +
   3.198 +	next = m->shadow_ht_extras;
   3.199 +	while( next )
   3.200 +    {
   3.201 +		struct shadow_status * this = next;
   3.202 +		m->shadow_extras_count--;
   3.203 +		next = *((struct shadow_status **)(&next[shadow_ht_extra_size]));
   3.204 +		kfree( this );
   3.205 +	}
   3.206 +
   3.207 +	SH_LOG("freed extras, now %d", m->shadow_extras_count);
   3.208 +
   3.209 +    if( m->shadow_dirty_bitmap  )
   3.210 +    {
   3.211 +        kfree( m->shadow_dirty_bitmap );
   3.212 +		m->shadow_dirty_bitmap = 0;
   3.213 +    }
   3.214  
   3.215      // free the hashtable itself
   3.216 +	kfree( &m->shadow_ht[0] );
   3.217  }
   3.218  
   3.219 -static void shadow_mode_flush( struct mm_struct *m )
   3.220 +static void shadow_mode_table_op( struct task_struct *p, unsigned int op )
   3.221  {
   3.222 +	struct mm_struct *m = &p->mm;
   3.223  
   3.224      // since Dom0 did the hypercall, we should be running with it's page
   3.225      // tables right now. Calling flush on yourself would be really
   3.226 @@ -147,10 +267,32 @@ static void shadow_mode_flush( struct mm
   3.227          return;
   3.228      }
   3.229     
   3.230 +
   3.231      spin_lock(&m->shadow_lock);
   3.232 -	__free_shadow_table( m );
   3.233 +
   3.234 +    SH_LOG("shadow mode table op %08lx %08lx count %d",pagetable_val( m->pagetable),pagetable_val(m->shadow_table), m->shadow_page_count);
   3.235 +
   3.236 +    shadow_audit(m,1);
   3.237 +
   3.238 +    switch(op)
   3.239 +    {
   3.240 +    case DOM0_SHADOW_CONTROL_OP_FLUSH:
   3.241 +	    __free_shadow_table( m );
   3.242 +        break;
   3.243 +   
   3.244 +    case DOM0_SHADOW_CONTROL_OP_CLEAN:
   3.245 +       __scan_shadow_table( m, op );
   3.246 +       if( m->shadow_dirty_bitmap )
   3.247 +           memset(m->shadow_dirty_bitmap,0,p->max_pages/8);
   3.248 +       break;
   3.249 +    }
   3.250 +
   3.251  	spin_unlock(&m->shadow_lock);
   3.252  
   3.253 +    SH_LOG("shadow mode table op : page count %d", m->shadow_page_count);
   3.254 +
   3.255 +    shadow_audit(m,1);
   3.256 +
   3.257      // call shadow_mk_pagetable
   3.258      shadow_mk_pagetable( m );
   3.259  
   3.260 @@ -164,28 +306,30 @@ int shadow_mode_control( struct task_str
   3.261      // don't call if already shadowed...
   3.262  
   3.263  	// sychronously stop domain
   3.264 -    if( !(p->state & TASK_STOPPED) && !(p->state & TASK_PAUSED))
   3.265 +    if( 0 && !(p->state & TASK_STOPPED) && !(p->state & TASK_PAUSED))
   3.266      {
   3.267 +        printk("about to pause domain\n");
   3.268  	    sched_pause_sync(p);
   3.269          printk("paused domain\n");
   3.270          we_paused = 1;
   3.271      }
   3.272  
   3.273 -	if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_OFF )
   3.274 +	if ( p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_OFF )
   3.275      {
   3.276 -		shadow_mode_disable(&p->mm);
   3.277 +		shadow_mode_disable(p);
   3.278  	}
   3.279 -	else if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_ENABLE_TEST )
   3.280 +	else if ( op == DOM0_SHADOW_CONTROL_OP_ENABLE_TEST )
   3.281  	{
   3.282 -        shadow_mode_disable(&p->mm);
   3.283 -        shadow_mode_enable(&p->mm, SHM_test);
   3.284 +        if(p->mm.shadow_mode) shadow_mode_disable(p);
   3.285 +        shadow_mode_enable(p, SHM_test);
   3.286  	}	
   3.287 -	else if (p->mm.shadow_mode && op == DOM0_SHADOW_CONTROL_OP_FLUSH )
   3.288 +	else if ( p->mm.shadow_mode && op >= DOM0_SHADOW_CONTROL_OP_FLUSH && op<=DOM0_SHADOW_CONTROL_OP_CLEAN )
   3.289      {
   3.290 -		shadow_mode_flush(&p->mm);
   3.291 +		shadow_mode_table_op(p, op);
   3.292      }
   3.293  	else
   3.294      {
   3.295 +        if ( we_paused ) wake_up(p);
   3.296  		return -EINVAL;
   3.297      }
   3.298  
   3.299 @@ -220,6 +364,7 @@ void unshadow_table( unsigned long gpfn,
   3.300      // this CPU was the one that cmpxchg'ed the page to invalid
   3.301  
   3.302  	spfn = __shadow_status(&current->mm, gpfn) & PSH_pfn_mask;
   3.303 +
   3.304  	delete_shadow_status(&current->mm, gpfn);
   3.305  
   3.306  #if 0 // XXX leave as might be useful for later debugging
   3.307 @@ -235,12 +380,7 @@ void unshadow_table( unsigned long gpfn,
   3.308  	}
   3.309  #endif
   3.310  
   3.311 -	if (type == PGT_l1_page_table)
   3.312 -		perfc_decr(shadow_l1_pages);
   3.313 -    else
   3.314 -		perfc_decr(shadow_l2_pages);
   3.315 -
   3.316 -	free_shadow_page( &current->mm, spfn );
   3.317 +	free_shadow_page( &current->mm, &frame_table[spfn] );
   3.318  
   3.319  }
   3.320  
   3.321 @@ -256,7 +396,6 @@ unsigned long shadow_l2_table(
   3.322  	SH_VVLOG("shadow_l2_table( %08lx )",gpfn);
   3.323  
   3.324  	perfc_incrc(shadow_l2_table_count);
   3.325 -	perfc_incr(shadow_l2_pages);
   3.326  
   3.327      // XXX in future, worry about racing in SMP guests 
   3.328      //      -- use cmpxchg with PSH_pending flag to show progress (and spin)
   3.329 @@ -265,6 +404,9 @@ unsigned long shadow_l2_table(
   3.330  
   3.331      ASSERT( spfn_info ); // XXX deal with failure later e.g. blow cache
   3.332  
   3.333 +	spfn_info->type_and_flags = PGT_l2_page_table;
   3.334 +	perfc_incr(shadow_l2_pages);
   3.335 +
   3.336  	spfn = (unsigned long) (spfn_info - frame_table);
   3.337  
   3.338  	// mark pfn as being shadowed, update field to point at shadow
   3.339 @@ -434,7 +576,9 @@ int shadow_fault( unsigned long va, long
   3.340              struct pfn_info *sl1pfn_info;
   3.341              unsigned long *gpl1e, *spl1e;
   3.342              int i;
   3.343 -            sl1pfn_info = alloc_domain_page( NULL ); // XXX account properly! 
   3.344 +            sl1pfn_info = alloc_shadow_page( &current->mm ); 
   3.345 +  	        sl1pfn_info->type_and_flags = PGT_l1_page_table;
   3.346 +
   3.347              sl1pfn = sl1pfn_info - frame_table;
   3.348  
   3.349              SH_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn);
     4.1 --- a/xen/include/asm-i386/processor.h	Fri Mar 26 15:09:04 2004 +0000
     4.2 +++ b/xen/include/asm-i386/processor.h	Tue Mar 30 15:44:27 2004 +0000
     4.3 @@ -426,8 +426,10 @@ struct mm_struct {
     4.4      struct shadow_status *shadow_ht;
     4.5      struct shadow_status *shadow_ht_free;
     4.6      struct shadow_status *shadow_ht_extras; // extra allocation units
     4.7 +    unsigned int *shadow_dirty_bitmap;
     4.8      unsigned int shadow_page_count;
     4.9      unsigned int shadow_max_page_count;
    4.10 +    unsigned int shadow_extras_count;
    4.11  
    4.12      /* Current LDT details. */
    4.13      unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt;
     5.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Fri Mar 26 15:09:04 2004 +0000
     5.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Tue Mar 30 15:44:27 2004 +0000
     5.3 @@ -221,7 +221,9 @@ typedef struct dom0_pcidev_access_st
     5.4  
     5.5  #define DOM0_SHADOW_CONTROL_OP_OFF         0
     5.6  #define DOM0_SHADOW_CONTROL_OP_ENABLE_TEST 1
     5.7 +#define DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY 2
     5.8  #define DOM0_SHADOW_CONTROL_OP_FLUSH       10
     5.9 +#define DOM0_SHADOW_CONTROL_OP_CLEAN       11
    5.10  typedef struct dom0_shadow_control_st
    5.11  {
    5.12      /* IN variables. */
     6.1 --- a/xen/include/xen/shadow.h	Fri Mar 26 15:09:04 2004 +0000
     6.2 +++ b/xen/include/xen/shadow.h	Tue Mar 30 15:44:27 2004 +0000
     6.3 @@ -15,10 +15,10 @@
     6.4  #define PSH_pfn_mask	((1<<21)-1)
     6.5  
     6.6  /* Shadow PT operation mode : shadowmode variable in mm_struct */
     6.7 -#define SHM_test        (1<<0) /* just run domain on shadow PTs */
     6.8 -#define SHM_logdirty    (1<<1) /* log pages that are dirtied */
     6.9 -#define SHM_cow         (1<<2) /* copy on write all dirtied pages */
    6.10 -#define SHM_translate   (1<<3) /* lookup machine pages in translation table */
    6.11 +#define SHM_test        (1) /* just run domain on shadow PTs */
    6.12 +#define SHM_logdirty    (2) /* log pages that are dirtied */
    6.13 +#define SHM_cow         (3) /* copy on write all dirtied pages */
    6.14 +#define SHM_translate   (4) /* lookup machine pages in translation table */
    6.15  
    6.16  #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
    6.17  #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
    6.18 @@ -30,7 +30,7 @@ extern void shadow_l1_normal_pt_update( 
    6.19  										l1_pgentry_t **prev_spl1e_ptr  );
    6.20  extern void shadow_l2_normal_pt_update( unsigned long pa, unsigned long gpte );
    6.21  extern void unshadow_table( unsigned long gpfn, unsigned int type );
    6.22 -extern int shadow_mode_enable( struct mm_struct *m, unsigned int mode );
    6.23 +extern int shadow_mode_enable( struct task_struct *p, unsigned int mode );
    6.24  extern unsigned long shadow_l2_table( 
    6.25                       struct mm_struct *m, unsigned long gpfn );
    6.26  
    6.27 @@ -81,26 +81,33 @@ static void shadow_audit(struct mm_struc
    6.28  	
    6.29      for(j=0;j<shadow_ht_buckets;j++)
    6.30      {
    6.31 -        a = &p->mm.shadow_ht[j];        
    6.32 -		if(a->pfn) live++;
    6.33 -        while(a->next && live<9999)
    6.34 +        a = &m->shadow_ht[j];        
    6.35 +		if(a->pfn){live++; ASSERT(a->spfn_and_flags&PSH_pfn_mask);}
    6.36 +		ASSERT((a->pfn&0xf0000000)==0);
    6.37 +		ASSERT(a->pfn<0x00100000);
    6.38 +		a=a->next;
    6.39 +        while(a && live<9999)
    6.40  		{ 
    6.41  			live++; 
    6.42 -			if(a->pfn == 0)
    6.43 +			if(a->pfn == 0 || a->spfn_and_flags == 0)
    6.44  			{
    6.45  				printk("XXX live=%d pfn=%08lx sp=%08lx next=%p\n",
    6.46  					   live, a->pfn, a->spfn_and_flags, a->next);
    6.47  				BUG();
    6.48  			}
    6.49 +			ASSERT(a->pfn);
    6.50 +			ASSERT((a->pfn&0xf0000000)==0);
    6.51 +			ASSERT(a->pfn<0x00100000);
    6.52 +			ASSERT(a->spfn_and_flags&PSH_pfn_mask);
    6.53  			a=a->next; 
    6.54  		}
    6.55  		ASSERT(live<9999);
    6.56  	}
    6.57  
    6.58 -    a = p->mm.shadow_ht_free;
    6.59 +    a = m->shadow_ht_free;
    6.60      while(a) { free++; a=a->next; }
    6.61  
    6.62 -    if(print) printk("live=%d free=%d\n",live,free);
    6.63 +    if(print) printk("Xlive=%d free=%d\n",live,free);
    6.64  
    6.65  	abs=(perfc_value(shadow_l1_pages)+perfc_value(shadow_l2_pages))-live;
    6.66  	if( abs < -1 || abs > 1 )
    6.67 @@ -214,6 +221,8 @@ static inline void delete_shadow_status(
    6.68  
    6.69  			b->next = b->next->next;
    6.70  			D->next = m->shadow_ht_free;
    6.71 +			D->pfn = 0;
    6.72 +			D->spfn_and_flags = 0;
    6.73  			m->shadow_ht_free = D;
    6.74  		}
    6.75  		else
    6.76 @@ -224,6 +233,7 @@ static inline void delete_shadow_status(
    6.77  
    6.78  #if SHADOW_HASH_DEBUG
    6.79  		if( __shadow_status(m,gpfn) ) BUG();  
    6.80 +		shadow_audit(m,0);
    6.81  #endif
    6.82  		return;
    6.83      }
    6.84 @@ -246,6 +256,7 @@ static inline void delete_shadow_status(
    6.85  #if SHADOW_HASH_DEBUG
    6.86  			if( __shadow_status(m,gpfn) ) BUG();
    6.87  #endif
    6.88 +			shadow_audit(m,0);
    6.89  			return;
    6.90  		}
    6.91  
    6.92 @@ -268,8 +279,10 @@ static inline void set_shadow_status( st
    6.93  	B = b = hash_bucket( m, gpfn );
    6.94     
    6.95      ASSERT(gpfn);
    6.96 -    ASSERT(s);
    6.97 +    //ASSERT(s);
    6.98 +    //ASSERT(s&PSH_pfn_mask);
    6.99      SH_VVLOG("set gpfn=%08x s=%08lx bucket=%p(%p)", gpfn, s, b, b->next );
   6.100 +
   6.101      shadow_audit(m,0);
   6.102  
   6.103  	do
   6.104 @@ -277,6 +290,7 @@ static inline void set_shadow_status( st
   6.105  		if ( b->pfn == gpfn )			
   6.106  		{
   6.107  			b->spfn_and_flags = s;
   6.108 +			shadow_audit(m,0);
   6.109  			return;
   6.110  		}
   6.111  
   6.112 @@ -294,6 +308,7 @@ static inline void set_shadow_status( st
   6.113          ASSERT( B->next == 0 );
   6.114  		B->pfn = gpfn;
   6.115  		B->spfn_and_flags = s;
   6.116 +		shadow_audit(m,0);
   6.117  		return;
   6.118  	}
   6.119  
   6.120 @@ -309,6 +324,8 @@ static inline void set_shadow_status( st
   6.121  
   6.122  	    memset( extra, 0, sizeof(void*) + (shadow_ht_extra_size * 
   6.123  							   sizeof(struct shadow_status)) );
   6.124 +
   6.125 +        m->shadow_extras_count++;
   6.126  	
   6.127          // add extras to free list
   6.128  	    fptr = &m->shadow_ht_free;
   6.129 @@ -319,7 +336,7 @@ static inline void set_shadow_status( st
   6.130  	    }
   6.131  	    *fptr = NULL;
   6.132  
   6.133 -	    *((struct shadow_status ** ) &m->shadow_ht[shadow_ht_extra_size]) = 
   6.134 +	    *((struct shadow_status ** ) &extra[shadow_ht_extra_size]) = 
   6.135                                              m->shadow_ht_extras;
   6.136          m->shadow_ht_extras = extra;
   6.137  
   6.138 @@ -333,6 +350,8 @@ static inline void set_shadow_status( st
   6.139  	b->next = B->next;
   6.140  	B->next = b;
   6.141  
   6.142 +	shadow_audit(m,0);
   6.143 +
   6.144  	return;
   6.145  }
   6.146