ia64/xen-unstable

changeset 2428:e7ad903ca36c

bitkeeper revision 1.1159.69.10 (413a1e6ckNNgvyiZ6JU5_vjN5ITSuA)

Add pinning of L1 table sback in, as it helps 2.4 performance. At the same
time I've fixed the 'mutable backptr' support in Xen.
author kaf24@camelot.eng.3leafnetworks.com
date Sat Sep 04 19:58:36 2004 +0000 (2004-09-04)
parents 6f9bf6379bbd
children 6b7809060d4a
files xen/arch/x86/domain.c xen/arch/x86/memory.c xen/common/dom0_ops.c xen/common/dom_mem_ops.c xen/common/page_alloc.c xen/common/schedule.c xen/include/asm-x86/mm.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/hypervisor-ifs/hypervisor-if.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Sat Sep 04 18:32:45 2004 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Sat Sep 04 19:58:36 2004 +0000
     1.3 @@ -449,12 +449,94 @@ long do_iopl(domid_t domain, unsigned in
     1.4  
     1.5  #endif
     1.6  
     1.7 -void domain_relinquish_memory(struct domain *d)
     1.8 +
     1.9 +static void relinquish_list(struct domain *d, struct list_head *list)
    1.10  {
    1.11 -    struct list_head *ent, *tmp;
    1.12 +    struct list_head *ent;
    1.13      struct pfn_info  *page;
    1.14      unsigned long     x, y;
    1.15  
    1.16 +    /* Use a recursive lock, as we may enter 'free_domheap_page'. */
    1.17 +    spin_lock_recursive(&d->page_alloc_lock);
    1.18 +
    1.19 +    /*
    1.20 +     * Careful! Any time we might decrement a page's reference count we
    1.21 +     * might invalidate our page pointer or our pointer into the page list.
    1.22 +     * In such cases we have to exit the current iteration of the loop and
    1.23 +     * start back at the beginning of the list. We are guaranteed to make
    1.24 +     * forward progress because nothign will get added to the list (the domain
    1.25 +     * is dying) and no pages will become pinned after we unpin them.
    1.26 +     */
    1.27 +    ent = list->next;
    1.28 +    while ( ent != list )
    1.29 +    {
    1.30 +        page = list_entry(ent, struct pfn_info, list);
    1.31 +
    1.32 +        if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
    1.33 +        {
    1.34 +            /* NB. Check the allocation pin /before/ put_page_and_type()! */
    1.35 +            if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
    1.36 +                put_page(page);
    1.37 +            put_page_and_type(page);
    1.38 +            /* May have lost our place in the list - start over. */
    1.39 +            ent = list->next;
    1.40 +            continue;
    1.41 +        }
    1.42 +
    1.43 +        if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
    1.44 +        {
    1.45 +            put_page(page);
    1.46 +            /* May have lost our place in the list - start over. */
    1.47 +            ent = list->next;
    1.48 +            continue;
    1.49 +        }
    1.50 +
    1.51 +        /*
    1.52 +         * Forcibly invalidate base page tables at this point to break circular
    1.53 +         * 'linear page table' references. This is okay because MMU structures
    1.54 +         * are not shared across domains and this domain is now dead. Thus base
    1.55 +         * tables are not in use so a non-zero count means circular reference.
    1.56 +         */
    1.57 +        y = page->u.inuse.type_info;
    1.58 +        do {
    1.59 +            x = y;
    1.60 +            if ( likely((x & (PGT_type_mask|PGT_validated)) != 
    1.61 +                        (PGT_base_page_table|PGT_validated)) )
    1.62 +            {
    1.63 +                /*
    1.64 +                 * We have done no work on this iteration, so it is safe
    1.65 +                 * to move on to the next page in the list.
    1.66 +                 */
    1.67 +                ent = ent->next;
    1.68 +                break;
    1.69 +            }
    1.70 +            y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
    1.71 +            if ( likely(y == x) )
    1.72 +            {
    1.73 +                free_page_type(page, PGT_base_page_table);
    1.74 +                /* May have lost our place in the list - start over. */
    1.75 +                ent = list->next;
    1.76 +            }
    1.77 +        }
    1.78 +        while ( unlikely(y != x) );
    1.79 +    }
    1.80 +
    1.81 +    spin_unlock_recursive(&d->page_alloc_lock);
    1.82 +
    1.83 +    /*
    1.84 +     * Another CPU may have raced us to free some pages. Wait for those
    1.85 +     * to trickle out now that we have released the lock.
    1.86 +     */
    1.87 +    while ( !list_empty(list) )
    1.88 +    {
    1.89 +        smp_mb();
    1.90 +        cpu_relax();
    1.91 +    }
    1.92 +}
    1.93 +
    1.94 +
    1.95 +void domain_relinquish_memory(struct domain *d)
    1.96 +{
    1.97      /* Ensure that noone is running over the dead domain's page tables. */
    1.98      synchronise_pagetables(~0UL);
    1.99  
   1.100 @@ -472,49 +554,9 @@ void domain_relinquish_memory(struct dom
   1.101       */
   1.102      destroy_gdt(d);
   1.103  
   1.104 -    /* Use a recursive lock, as we may enter 'free_domheap_page'. */
   1.105 -    spin_lock_recursive(&d->page_alloc_lock);
   1.106 -
   1.107 -    /* Relinquish Xen-heap pages. */
   1.108 -    list_for_each_safe ( ent, tmp, &d->xenpage_list )
   1.109 -    {
   1.110 -        page = list_entry(ent, struct pfn_info, list);
   1.111 -
   1.112 -        if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
   1.113 -            put_page(page);
   1.114 -    }
   1.115 -
   1.116 -    /* Relinquish all pages on the domain's allocation list. */
   1.117 -    list_for_each_safe ( ent, tmp, &d->page_list )
   1.118 -    {
   1.119 -        page = list_entry(ent, struct pfn_info, list);
   1.120 -
   1.121 -        if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) )
   1.122 -            put_page_and_type(page);
   1.123 -
   1.124 -        if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
   1.125 -            put_page(page);
   1.126 -
   1.127 -        /*
   1.128 -         * Forcibly invalidate base page tables at this point to break circular
   1.129 -         * 'linear page table' references. This is okay because MMU structures
   1.130 -         * are not shared across domains and this domain is now dead. Thus base
   1.131 -         * tables are not in use so a non-zero count means circular reference.
   1.132 -         */
   1.133 -        y = page->u.inuse.type_info;
   1.134 -        do {
   1.135 -            x = y;
   1.136 -            if ( likely((x & (PGT_type_mask|PGT_validated)) != 
   1.137 -                        (PGT_base_page_table|PGT_validated)) )
   1.138 -                break;
   1.139 -            y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
   1.140 -            if ( likely(y == x) )
   1.141 -                free_page_type(page, PGT_base_page_table);
   1.142 -        }
   1.143 -        while ( unlikely(y != x) );
   1.144 -    }
   1.145 -
   1.146 -    spin_unlock_recursive(&d->page_alloc_lock);
   1.147 +    /* Relinquish every page of memory. */
   1.148 +    relinquish_list(d, &d->xenpage_list);
   1.149 +    relinquish_list(d, &d->page_list);
   1.150  }
   1.151  
   1.152  
   1.153 @@ -739,7 +781,7 @@ int construct_dom0(struct domain *p,
   1.154              /* Get another ref to L2 page so that it can be pinned. */
   1.155              if ( !get_page_and_type(page, p, PGT_l2_page_table) )
   1.156                  BUG();
   1.157 -            set_bit(_PGC_guest_pinned, &page->count_info);
   1.158 +            set_bit(_PGT_pinned, &page->u.inuse.type_info);
   1.159          }
   1.160          else
   1.161          {
     2.1 --- a/xen/arch/x86/memory.c	Sat Sep 04 18:32:45 2004 +0000
     2.2 +++ b/xen/arch/x86/memory.c	Sat Sep 04 19:58:36 2004 +0000
     2.3 @@ -455,7 +455,8 @@ get_page_from_l1e(
     2.4  /* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */
     2.5  static int 
     2.6  get_page_from_l2e(
     2.7 -    l2_pgentry_t l2e, unsigned long pfn, struct domain *d, unsigned long va_idx)
     2.8 +    l2_pgentry_t l2e, unsigned long pfn,
     2.9 +    struct domain *d, unsigned long va_idx)
    2.10  {
    2.11      int rc;
    2.12  
    2.13 @@ -471,7 +472,7 @@ get_page_from_l2e(
    2.14  
    2.15      rc = get_page_and_type_from_pagenr(
    2.16          l2_pgentry_to_pagenr(l2e), 
    2.17 -	PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
    2.18 +        PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
    2.19  
    2.20      if ( unlikely(!rc) )
    2.21          return get_linear_pagetable(l2e, pfn, d);
    2.22 @@ -671,8 +672,8 @@ static int mod_l2_entry(l2_pgentry_t *pl
    2.23              return update_l2e(pl2e, ol2e, nl2e);
    2.24  
    2.25          if ( unlikely(!get_page_from_l2e(nl2e, pfn, current, 
    2.26 -					((unsigned long)
    2.27 -					 pl2e & ~PAGE_MASK) >> 2 )) )
    2.28 +					((unsigned long)pl2e & 
    2.29 +                                         ~PAGE_MASK) >> 2)) )
    2.30              return 0;
    2.31  
    2.32          if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) )
    2.33 @@ -828,18 +829,15 @@ static int do_extended_command(unsigned 
    2.34      {
    2.35      case MMUEXT_PIN_L1_TABLE:
    2.36      case MMUEXT_PIN_L2_TABLE:
    2.37 -
    2.38 -	/* When we pin an L1 page we now insist that the va
    2.39 -	   backpointer (used for writable page tables) must still be
    2.40 -	   mutable. This is an additional restriction even for guests
    2.41 -	   that don't use writable page tables, but I don't think it
    2.42 -	   will break anything as guests typically pin pages before
    2.43 -	   they are used, hence they'll still be mutable. */
    2.44 -
    2.45 +        /*
    2.46 +         * We insist that, if you pin an L1 page, it's the first thing that
    2.47 +         * you do to it. This is because we require the backptr to still be
    2.48 +         * mutable. This assumption seems safe.
    2.49 +         */
    2.50          okay = get_page_and_type_from_pagenr(
    2.51              pfn, 
    2.52              ((cmd==MMUEXT_PIN_L2_TABLE) ? 
    2.53 -	     PGT_l2_page_table : (PGT_l1_page_table | PGT_va_mutable) ) ,
    2.54 +	     PGT_l2_page_table : (PGT_l1_page_table|PGT_va_mutable)),
    2.55              FOREIGNDOM);
    2.56  
    2.57          if ( unlikely(!okay) )
    2.58 @@ -849,8 +847,8 @@ static int do_extended_command(unsigned 
    2.59              break;
    2.60          }
    2.61  
    2.62 -        if ( unlikely(test_and_set_bit(_PGC_guest_pinned,
    2.63 -                                       &page->count_info)) )
    2.64 +        if ( unlikely(test_and_set_bit(_PGT_pinned,
    2.65 +                                       &page->u.inuse.type_info)) )
    2.66          {
    2.67              MEM_LOG("Pfn %08lx already pinned", pfn);
    2.68              put_page_and_type(page);
    2.69 @@ -866,8 +864,8 @@ static int do_extended_command(unsigned 
    2.70              MEM_LOG("Page %08lx bad domain (dom=%p)",
    2.71                      ptr, page->u.inuse.domain);
    2.72          }
    2.73 -        else if ( likely(test_and_clear_bit(_PGC_guest_pinned, 
    2.74 -                                            &page->count_info)) )
    2.75 +        else if ( likely(test_and_clear_bit(_PGT_pinned, 
    2.76 +                                            &page->u.inuse.type_info)) )
    2.77          {
    2.78              put_page_and_type(page);
    2.79              put_page(page);
    2.80 @@ -1053,13 +1051,18 @@ static int do_extended_command(unsigned 
    2.81  
    2.82          spin_lock(&e->page_alloc_lock);
    2.83  
    2.84 -        /* Check that 'e' will accept the page and has reservation headroom. */
    2.85 +        /*
    2.86 +         * Check that 'e' will accept the page and has reservation headroom.
    2.87 +         * Also, a domain mustn't have PGC_allocated pages when it is dying.
    2.88 +         */
    2.89          ASSERT(e->tot_pages <= e->max_pages);
    2.90 -        if ( unlikely(e->tot_pages == e->max_pages) ||
    2.91 +        if ( unlikely(test_bit(DF_DYING, &e->flags)) ||
    2.92 +             unlikely(e->tot_pages == e->max_pages) ||
    2.93               unlikely(!gnttab_prepare_for_transfer(e, d, gntref)) )
    2.94          {
    2.95              MEM_LOG("Transferee has no reservation headroom (%d,%d), or "
    2.96 -                    "provided a bad grant ref.\n", e->tot_pages, e->max_pages);
    2.97 +                    "provided a bad grant ref, or is dying (%08x).\n",
    2.98 +                    e->tot_pages, e->max_pages, e->flags);
    2.99              spin_unlock(&e->page_alloc_lock);
   2.100              put_domain(e);
   2.101              okay = 0;
   2.102 @@ -1195,6 +1198,7 @@ int do_mmu_update(mmu_update_t *ureqs, i
   2.103      unsigned long prev_spfn = 0;
   2.104      l1_pgentry_t *prev_spl1e = 0;
   2.105      struct domain *d = current;
   2.106 +    u32 type_info;
   2.107  
   2.108      perfc_incrc(calls_to_mmu_update); 
   2.109      perfc_addc(num_page_updates, count);
   2.110 @@ -1243,10 +1247,11 @@ int do_mmu_update(mmu_update_t *ureqs, i
   2.111              }
   2.112  
   2.113              page = &frame_table[pfn];
   2.114 -            switch ( (page->u.inuse.type_info & PGT_type_mask) )
   2.115 +            switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask )
   2.116              {
   2.117              case PGT_l1_page_table: 
   2.118 -                if ( likely(passive_get_page_type(page, PGT_l1_page_table)) )
   2.119 +                if ( likely(get_page_type(
   2.120 +                    page, type_info & (PGT_type_mask|PGT_va_mask))) )
   2.121                  {
   2.122                      okay = mod_l1_entry((l1_pgentry_t *)va, 
   2.123                                          mk_l1_pgentry(req.val)); 
   2.124 @@ -1496,11 +1501,11 @@ void ptwr_reconnect_disconnected(unsigne
   2.125          [ptwr_info[cpu].writable_l1>>PAGE_SHIFT];
   2.126  
   2.127  #ifdef PTWR_TRACK_DOMAIN
   2.128 -    if (ptwr_domain[cpu] != get_current()->domain)
   2.129 +    if (ptwr_domain[cpu] != current->domain)
   2.130          printk("ptwr_reconnect_disconnected domain mismatch %d != %d\n",
   2.131 -               ptwr_domain[cpu], get_current()->domain);
   2.132 +               ptwr_domain[cpu], current->domain);
   2.133  #endif
   2.134 -    PTWR_PRINTK(("[A] page fault in disconnected space: addr %08lx space %08lx\n",
   2.135 +    PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n",
   2.136                   addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT));
   2.137      pl2e = &linear_l2_table[ptwr_info[cpu].disconnected];
   2.138  
   2.139 @@ -1572,9 +1577,9 @@ void ptwr_flush_inactive(void)
   2.140      int i, idx;
   2.141  
   2.142  #ifdef PTWR_TRACK_DOMAIN
   2.143 -    if (ptwr_info[cpu].domain != get_current()->domain)
   2.144 +    if (ptwr_info[cpu].domain != current->domain)
   2.145          printk("ptwr_flush_inactive domain mismatch %d != %d\n",
   2.146 -               ptwr_info[cpu].domain, get_current()->domain);
   2.147 +               ptwr_info[cpu].domain, current->domain);
   2.148  #endif
   2.149  #if 0
   2.150      {
   2.151 @@ -1655,9 +1660,9 @@ int ptwr_do_page_fault(unsigned long add
   2.152          if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table )
   2.153          {
   2.154  #ifdef PTWR_TRACK_DOMAIN
   2.155 -            if ( ptwr_info[cpu].domain != get_current()->domain )
   2.156 +            if ( ptwr_info[cpu].domain != current->domain )
   2.157                  printk("ptwr_do_page_fault domain mismatch %d != %d\n",
   2.158 -                       ptwr_info[cpu].domain, get_current()->domain);
   2.159 +                       ptwr_info[cpu].domain, current->domain);
   2.160  #endif
   2.161              pl2e = &linear_l2_table[(page->u.inuse.type_info &
   2.162                                       PGT_va_mask) >> PGT_va_shift];
     3.1 --- a/xen/common/dom0_ops.c	Sat Sep 04 18:32:45 2004 +0000
     3.2 +++ b/xen/common/dom0_ops.c	Sat Sep 04 19:58:36 2004 +0000
     3.3 @@ -628,7 +628,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     3.4                          break;
     3.5                      }
     3.6  
     3.7 -		    if ( page->count_info & PGC_guest_pinned )
     3.8 +		    if ( page->u.inuse.type_info & PGT_pinned )
     3.9  			type |= LPINTAB;
    3.10  		    l_arr[j] |= type;
    3.11                      put_page(page);
     4.1 --- a/xen/common/dom_mem_ops.c	Sat Sep 04 18:32:45 2004 +0000
     4.2 +++ b/xen/common/dom_mem_ops.c	Sat Sep 04 19:58:36 2004 +0000
     4.3 @@ -82,7 +82,7 @@ static long free_dom_mem(struct domain *
     4.4                  return i;
     4.5              }
     4.6  
     4.7 -            if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) )
     4.8 +            if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
     4.9                  put_page_and_type(page);
    4.10              
    4.11              if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
     5.1 --- a/xen/common/page_alloc.c	Sat Sep 04 18:32:45 2004 +0000
     5.2 +++ b/xen/common/page_alloc.c	Sat Sep 04 19:58:36 2004 +0000
     5.3 @@ -393,10 +393,13 @@ struct pfn_info *alloc_domheap_pages(str
     5.4  
     5.5      spin_lock(&d->page_alloc_lock);
     5.6  
     5.7 -    if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
     5.8 +    if ( unlikely(test_bit(DF_DYING, &d->flags)) ||
     5.9 +         unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
    5.10      {
    5.11          DPRINTK("Over-allocation for domain %u: %u > %u\n",
    5.12                  d->domain, d->tot_pages + (1 << order), d->max_pages);
    5.13 +        DPRINTK("...or the domain is dying (%d)\n", 
    5.14 +                !!test_bit(DF_DYING, &d->flags));
    5.15          spin_unlock(&d->page_alloc_lock);
    5.16          free_heap_pages(MEMZONE_DOM, pg, order);
    5.17          return NULL;
    5.18 @@ -427,6 +430,7 @@ void free_domheap_pages(struct pfn_info 
    5.19  
    5.20      if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
    5.21      {
    5.22 +        /* NB. May recursively lock from domain_relinquish_memory(). */
    5.23          spin_lock_recursive(&d->page_alloc_lock);
    5.24  
    5.25          for ( i = 0; i < (1 << order); i++ )
     6.1 --- a/xen/common/schedule.c	Sat Sep 04 18:32:45 2004 +0000
     6.2 +++ b/xen/common/schedule.c	Sat Sep 04 19:58:36 2004 +0000
     6.3 @@ -374,20 +374,6 @@ void __enter_scheduler(void)
     6.4      cleanup_writable_pagetable(
     6.5          prev, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
     6.6  
     6.7 -#ifdef PTWR_TRACK_DOMAIN
     6.8 -    {
     6.9 -        extern domid_t ptwr_domain[];
    6.10 -        int cpu = smp_processor_id();
    6.11 -        if (ptwr_domain[cpu] != prev->domain)
    6.12 -            printk("switch_to domain mismatch %d != %d\n",
    6.13 -                   ptwr_domain[cpu], prev->domain);
    6.14 -        ptwr_domain[cpu] = next->domain;
    6.15 -        if (ptwr_disconnected[cpu] != ENTRIES_PER_L2_PAGETABLE ||
    6.16 -            ptwr_writable_idx[cpu])
    6.17 -            printk("switch_to ptwr dirty!!!\n");
    6.18 -    }
    6.19 -#endif
    6.20 -
    6.21      perfc_incrc(sched_ctx);
    6.22  
    6.23  #if defined(WAKE_HISTO)
     7.1 --- a/xen/include/asm-x86/mm.h	Sat Sep 04 18:32:45 2004 +0000
     7.2 +++ b/xen/include/asm-x86/mm.h	Sat Sep 04 19:58:36 2004 +0000
     7.3 @@ -71,27 +71,27 @@ struct pfn_info
     7.4   /* Has this page been validated for use as its current type? */
     7.5  #define _PGT_validated      28
     7.6  #define PGT_validated       (1<<_PGT_validated)
     7.7 - /* 10-bit most significant bits of va address if used as l1 page table */
     7.8 -#define PGT_va_shift        18
     7.9 + /* Owning guest has pinned this page to its current type? */
    7.10 +#define _PGT_pinned         27
    7.11 +#define PGT_pinned          (1<<_PGT_pinned)
    7.12 + /* The 10 most significant bits of virt address if this is a page table. */
    7.13 +#define PGT_va_shift        17
    7.14  #define PGT_va_mask         (((1<<10)-1)<<PGT_va_shift)
    7.15 -#define PGT_va_mutable      PGT_va_mask /* va backpointer is still mutable */
    7.16 - /* 18-bit count of uses of this frame as its current type. */
    7.17 -#define PGT_count_mask      ((1<<18)-1)
    7.18 +#define PGT_va_mutable      PGT_va_mask /* va backpointer is mutable? */
    7.19 + /* 17-bit count of uses of this frame as its current type. */
    7.20 +#define PGT_count_mask      ((1<<17)-1)
    7.21  
    7.22   /* For safety, force a TLB flush when this page's type changes. */
    7.23  #define _PGC_tlb_flush_on_type_change 31
    7.24  #define PGC_tlb_flush_on_type_change  (1<<_PGC_tlb_flush_on_type_change)
    7.25 - /* Owning guest has pinned this page to its current type? */
    7.26 -#define _PGC_guest_pinned             30
    7.27 -#define PGC_guest_pinned              (1<<_PGC_guest_pinned)
    7.28   /* Cleared when the owning guest 'frees' this page. */
    7.29 -#define _PGC_allocated                29
    7.30 +#define _PGC_allocated                30
    7.31  #define PGC_allocated                 (1<<_PGC_allocated)
    7.32   /* This bit is always set, guaranteeing that the count word is never zero. */
    7.33 -#define _PGC_always_set               28
    7.34 +#define _PGC_always_set               29
    7.35  #define PGC_always_set                (1<<_PGC_always_set)
    7.36 - /* 27-bit count of references to this frame. */
    7.37 -#define PGC_count_mask                ((1<<28)-1)
    7.38 + /* 29-bit count of references to this frame. */
    7.39 +#define PGC_count_mask                ((1<<29)-1)
    7.40  
    7.41  /* We trust the slab allocator in slab.c, and our use of it. */
    7.42  #define PageSlab(page)		(1)
    7.43 @@ -199,11 +199,10 @@ static inline void put_page_type(struct 
    7.44                  nx &= ~PGT_validated;
    7.45              }
    7.46          }
    7.47 -	else if ( unlikely( ((nx & PGT_count_mask) == 1) && 
    7.48 -	    test_bit(_PGC_guest_pinned, &page->count_info)) )
    7.49 +	else if ( unlikely((nx & (PGT_pinned | PGT_count_mask)) == 
    7.50 +                           (PGT_pinned | 1)) )
    7.51  	{
    7.52 -	    /* if the page is pinned, but we're dropping the last reference
    7.53 -	       then make the va backpointer mutable again */
    7.54 +            /* Page is now only pinned. Make the back pointer mutable again. */
    7.55  	    nx |= PGT_va_mutable;
    7.56  	}
    7.57      }
    7.58 @@ -230,33 +229,36 @@ static inline int get_page_type(struct p
    7.59                  nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated);
    7.60                  nx |= type;
    7.61                  /* No extra validation needed for writable pages. */
    7.62 -                if ( (type & PGT_type_mask) == PGT_writable_page )
    7.63 +                if ( type == PGT_writable_page )
    7.64                      nx |= PGT_validated;
    7.65              }
    7.66          }
    7.67 -        else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
    7.68 +        else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) )
    7.69          {
    7.70 -            DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n",
    7.71 -                    x & PGT_type_mask, type, page_to_pfn(page));
    7.72 -            return 0;
    7.73 -        }
    7.74 -	else if ( (x & PGT_va_mask) == PGT_va_mutable )
    7.75 -	{
    7.76 -	    /* The va_backpointer is currently mutable, hence we update it. */
    7.77 -	    nx &= ~PGT_va_mask;
    7.78 -	    nx |= type; /* we know the actual type is correct */
    7.79 -	}
    7.80 -        else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask) ) )
    7.81 -        {
    7.82 -	    /* The va backpointer wasn't mutable, and is different :-( */
    7.83 -            DPRINTK("Unexpected va backpointer (saw %08x != exp %08x) for pfn %08lx\n",
    7.84 -                    x, type, page_to_pfn(page));
    7.85 -            return 0;
    7.86 +            if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
    7.87 +            {
    7.88 +                DPRINTK("Bad type (saw %08x != exp %08x) for pfn %08lx\n",
    7.89 +                        x & PGT_type_mask, type, page_to_pfn(page));
    7.90 +                return 0;
    7.91 +            }
    7.92 +            else if ( (x & PGT_va_mask) == PGT_va_mutable )
    7.93 +            {
    7.94 +                /* The va backpointer is mutable, hence we update it. */
    7.95 +                nx &= ~PGT_va_mask;
    7.96 +                nx |= type; /* we know the actual type is correct */
    7.97 +            }
    7.98 +            else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask)) )
    7.99 +            {
   7.100 +                /* The va backpointer wasn't mutable, and is different. */
   7.101 +                DPRINTK("Unexpected va backpointer (saw %08x != exp %08x)"
   7.102 +                        " for pfn %08lx\n", x, type, page_to_pfn(page));
   7.103 +                return 0;
   7.104 +            }
   7.105          }
   7.106  	else if ( unlikely(!(x & PGT_validated)) )
   7.107          {
   7.108              /* Someone else is updating validation of this page. Wait... */
   7.109 -            while ( (y = page->u.inuse.type_info) != x )
   7.110 +            while ( (y = page->u.inuse.type_info) == x )
   7.111              {
   7.112                  rep_nop();
   7.113                  barrier();
   7.114 @@ -286,55 +288,6 @@ static inline int get_page_type(struct p
   7.115      return 1;
   7.116  }
   7.117  
   7.118 -/* This 'passive' version of get_page_type doesn't attempt to validate
   7.119 -the page, but just checks the type and increments the type count.  The
   7.120 -function is called while doing a NORMAL_PT_UPDATE of an entry in an L1
   7.121 -page table: We want to 'lock' the page for the brief beriod while
   7.122 -we're doing the update, but we're not actually linking it in to a
   7.123 -pagetable. */
   7.124 -
   7.125 -static inline int passive_get_page_type(struct pfn_info *page, u32 type)
   7.126 -{
   7.127 -    u32 nx, x, y = page->u.inuse.type_info;
   7.128 - again:
   7.129 -    do {
   7.130 -        x  = y;
   7.131 -        nx = x + 1;
   7.132 -        if ( unlikely((nx & PGT_count_mask) == 0) )
   7.133 -        {
   7.134 -            DPRINTK("Type count overflow on pfn %08lx\n", page_to_pfn(page));
   7.135 -            return 0;
   7.136 -        }
   7.137 -        else if ( unlikely((x & PGT_count_mask) == 0) )
   7.138 -        {
   7.139 -            if ( (x & (PGT_type_mask|PGT_va_mask)) != type )
   7.140 -            {
   7.141 -                nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated);
   7.142 -                nx |= type;
   7.143 -            }
   7.144 -        }
   7.145 -        else if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
   7.146 -        {
   7.147 -            DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n",
   7.148 -                    x & PGT_type_mask, type, page_to_pfn(page));
   7.149 -            return 0;
   7.150 -        }
   7.151 -	else if ( unlikely(!(x & PGT_validated)) )
   7.152 -        {
   7.153 -            /* Someone else is updating validation of this page. Wait... */
   7.154 -            while ( (y = page->u.inuse.type_info) != x )
   7.155 -            {
   7.156 -                rep_nop();
   7.157 -                barrier();
   7.158 -            }
   7.159 -            goto again;
   7.160 -        }
   7.161 -    }
   7.162 -    while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
   7.163 -
   7.164 -    return 1;
   7.165 -}
   7.166 -
   7.167  
   7.168  static inline void put_page_and_type(struct pfn_info *page)
   7.169  {
     8.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Sat Sep 04 18:32:45 2004 +0000
     8.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Sat Sep 04 19:58:36 2004 +0000
     8.3 @@ -19,7 +19,7 @@
     8.4   * This makes sure that old versions of dom0 tools will stop working in a
     8.5   * well-defined way (rather than crashing the machine, for instance).
     8.6   */
     8.7 -#define DOM0_INTERFACE_VERSION   0xAAAA0013
     8.8 +#define DOM0_INTERFACE_VERSION   0xAAAA0014
     8.9  
    8.10  #define MAX_DOMAIN_NAME    16
    8.11  
     9.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h	Sat Sep 04 18:32:45 2004 +0000
     9.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h	Sat Sep 04 19:58:36 2004 +0000
     9.3 @@ -149,16 +149,16 @@
     9.4  #define MMUEXT_PIN_L2_TABLE      1 /* ptr = MA of frame to pin               */
     9.5  #define MMUEXT_PIN_L3_TABLE      2 /* ptr = MA of frame to pin               */
     9.6  #define MMUEXT_PIN_L4_TABLE      3 /* ptr = MA of frame to pin               */
     9.7 -#define MMUEXT_UNPIN_TABLE       1 /* ptr = MA of frame to unpin             */
     9.8 -#define MMUEXT_NEW_BASEPTR       2 /* ptr = MA of new pagetable base         */
     9.9 -#define MMUEXT_TLB_FLUSH         3 /* ptr = NULL                             */
    9.10 -#define MMUEXT_INVLPG            4 /* ptr = VA to invalidate                 */
    9.11 -#define MMUEXT_FLUSH_CACHE       5
    9.12 -#define MMUEXT_SET_LDT           6 /* ptr = VA of table; val = # entries     */
    9.13 -#define MMUEXT_SET_FOREIGNDOM    7 /* val[31:16] = dom                       */
    9.14 -#define MMUEXT_CLEAR_FOREIGNDOM  8
    9.15 -#define MMUEXT_TRANSFER_PAGE     9 /* ptr = MA of frame; val[31:16] = dom    */
    9.16 -#define MMUEXT_REASSIGN_PAGE    10
    9.17 +#define MMUEXT_UNPIN_TABLE       4 /* ptr = MA of frame to unpin             */
    9.18 +#define MMUEXT_NEW_BASEPTR       5 /* ptr = MA of new pagetable base         */
    9.19 +#define MMUEXT_TLB_FLUSH         6 /* ptr = NULL                             */
    9.20 +#define MMUEXT_INVLPG            7 /* ptr = VA to invalidate                 */
    9.21 +#define MMUEXT_FLUSH_CACHE       8
    9.22 +#define MMUEXT_SET_LDT           9 /* ptr = VA of table; val = # entries     */
    9.23 +#define MMUEXT_SET_FOREIGNDOM   10 /* val[31:16] = dom                       */
    9.24 +#define MMUEXT_CLEAR_FOREIGNDOM 11
    9.25 +#define MMUEXT_TRANSFER_PAGE    12 /* ptr = MA of frame; val[31:16] = dom    */
    9.26 +#define MMUEXT_REASSIGN_PAGE    13
    9.27  #define MMUEXT_CMD_MASK        255
    9.28  #define MMUEXT_CMD_SHIFT         8
    9.29